* Do path joins more safely
* Improve path cleaning and tests
* Lower-case error message
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* Correct handle potential errors in `get_path`
* Use `expect` in tests, rather than `unwrap`
* Correctly handle invalid upload path without panic
* Correctly handle filesystem create errors
* Use result rather than option to allow easier error handling
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* refactor!: use `actix-web-grants` to protect endpoints
* fix: filter out blank strings
* doc: add documentation for a function
* fix: don't return body for not exposed endpoints
* test: add fixtures
* test: fix naming
* test: remove extra step in teardown
* doc(readme): explain behavior of unset `auth_tokens` & `delete_tokens`
Just a clarification on how this works in the case of uninstalled tokens, for greater clarity and security
* docs(readme): update styling
* docs(readme): update grammar
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* ci(fixtures): run fixtures on `macos` & `ubuntu`
In order to check the fixtures works on both OS
* fix: install coreutils for macos
* doc: add mention coreutils on `macOS`
* ci: fix
* ci: fix
* refactor(fixture): rename matrix.os.version to matrix.os.runner
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* feat(log): use 'tracing-subscriber' instead of 'env_logger'
resolves#161
* feat: use 'tracing' instead of 'log'
* feat: make 'INFO' the default log level
* Delete endpoint implementation with delete_tokens configuration
* style(server): remove empty line, add dot at end of doc comment
* test(fixtures): add fixture test for file delete
* refactor(config): add delete_tokens to config.toml
* docs(readme): add info on how to delete file from server
* Update README.md
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* Update README.md
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* refactor(server): use log::error! and return 500
Co-authored-by: Helmut K. C. Tessarek <tessarek@evermeet.cx>
* test(server): add test_delete_file_without_token_in_config
* refactor(server): use one function to retrieve auth/delete tokens
Co-authored-by: Helmut K. C. Tessarek <tessarek@evermeet.cx>
* test(config): add test_get_tokens
* test(config): improve test_get_tokens
* feat(config): disallow empty tokens
* feat(server): update the messages for delete endpoint
---------
Co-authored-by: Helmut K. C. Tessarek <tessarek@evermeet.cx>
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* feat(server): add url encoding
- Introduced an option to enable encoding for filenames in the returned URL.
- Modified the encoding approach to specifically target whitespaces, replacing them with `%20`.
- Included unit tests to validate this encoding approach.
- Added fixture tests for broader functional verification.
- Removed the `urlencoding` dependency from `Cargo.toml`.
* Refactor code and fixtures for better compliance and consistency
- Fixed errors in the fixture configuration to ensure tests run as expected.
- Reformatted line endings for consistency across the codebase.
- Made necessary adjustments to adhere to Clippy's recommendations.
* Enhance whitespace handling options for filenames
- Implemented a configuration choice for space handling in filenames: encode, replace with underscores or none.
- Added corresponding unit and fixture tests.
* Remove redundant function call
Fixed misplaced line as per @tessus's review feedback, preventing duplicate handling of spaces in filenames.
* Delete test file with spaces.txt
* Refactor filename space handling
- Introduced `SpaceHandling` enum to manage filename spaces.
- Updated server.rs and paste.rs to utilize the new method.
- Added unit tests for the new filename handling method.
- Adjusted fixture tests to reflect these changes.
* Move filename processing into `SpaceHandling` enum
- Relocated filename processing logic to reside within the `SpaceHandling` enum, enhancing encapsulation.
- Updated calls in `server.rs` and `paste.rs` to use the new method structure.
- Adjusted unit tests to align with the refactored function location and call pattern.
* Refactor based on review suggestions
- Incorporated the inline suggestions made by @tessus, removing the unnecessary one-line assignments.
- Ensured the code adheres to Rust guidelines by running clippy and fmt.
* chore(deps): revert changes in Cargo.lock
* chore(config): replace spaces as default
* refactor(config): move SpaceHandling to config module
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* fix(server): do not list expired files
* refactor(server): simplify list files function
* add test case
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* Start
* Wip
* Implement path based JSON index
* Remove json_index_path
* Return datetime stamp instead of relative time
* Add file size to list item
* Add auth check when retrieving JSON index
* Make json index path hardcoded
* Test (currently failing)
* Fix test for test_json_list
* Clippy fix
* Revert cargo to original versions with only needed changes
* Add detail about auth guard affecting list route
* Change json_index_path to expose_list
* Remove unneeded linebreak
* Remove unnecessary import
* Remove unnecessary space at end of line
* Move config check after auth check
* Use new auth check syntax, add docs to struct, rename test_json_list to test_list
* Replace chrono usage with uts2ts
* Check list result in test
* Add example to README
* Upgrade serde_json to 1.0.103
* Add linebreak
* Remove unneeded clone
* Remove extra nl
* Update README.md
* Update README.md
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* Update README.md
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* Remove serde_json
* Set default config to false for expose_list
* Apply suggestions from code review
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* Check that option is value in test_list
* Update Cargo.toml
Co-authored-by: Helmut K. C. Tessarek <tessarek@evermeet.cx>
* Update cargo.lock
* Use expect() to check file name
* Remove underscore from list item struct
* Keep comma after last line
* refactor(server): rename ListItem fields
* test(fixtures): add fixture test for listing files
* test push
* remove file again
* chop off ts from filename and minor refactor
* update README
* docs(readme): fix capitalization
* refactor(server): clean up list implementation
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
Co-authored-by: Helmut K. C. Tessarek <tessarek@evermeet.cx>
* feat(server): support multiple auth tokens
Example:
```toml
[server]
auth_tokens = [
"super_secret_token1",
"super_secret_token2",
]
```
The previously used `AUTH_TOKEN` environment variable can still be used
and will be evaluated as well.
* fixtures: add all tokens in array to the test
* add deprecation warning for auth_token
* also add deprecation warnings at server startup
* fix formatting
* fixed tests, so that we do not use deprecated config options
* use bash array
* refactor: use separate function
* refactor: check auth tokens
* Update fixtures/test-server-auth-multiple-tokens/test.sh
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* refactor: convert functions to methods
* refactor: check function
* refactor: get_tokens method
* style(format): add newline between functions
* refactor(server): print deprecation warnings once
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
This is a hotfix commit which allows the use of [server.landing_page]
fields even when the [landing_page] section does not exist in the
configuration file.
* add random suffix mode
* fix linter issues
* add test case
* fix linter issues
* add comments, remove empty lines and single line declarations
* more test cases
* refactor(config): rename suffix_mode to random_suffix
* refactor(paste): clean up the random suffix logic
* chore(config): add random suffix example to default config
* docs(readme): mention random suffix feature
* test(fixtures): add fixture test for random suffix mode
* random_suffix -> suffix_mode
* fix default extension for .dotfile w/o extension
* fix formatting
* style(format): fix the indentation for random suffix fixture
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* honor X-Forward-* headers
Behind a reverse proxy, the log entries always showed the IP address of the reverse proxy.
With this change the real IP address of the client is shown.
Since the IP address is only used for info in the log, there are no security implications.
* style(format): apply formatting
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* docs(readme): add information about using html form
* chore(example): improve HTML form example
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* feat(deps): allow using openssl for tls
this allows reusing the openssl present on a distro already,
and takes a release build with it from 5.5 to 4.7mb
* chore(shuttle): update the enabled features for deployment
---------
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
* feat(deploy): deploy on shuttle.rs
* chore(deploy): add automated shuttle deploy workflow
* style(readme): update the formatting in README.md
* chore(deploy): optimize shuttle workflow
* fix(deploy): start the project
* fix(deploy): remove start step
This reverts commit 4f25921aeb.
* chore(deploy): expose the version for the public instance
* docs(lib): update the comment for shuttle entry-point
* chore(deploy): run the shuttle deployment on new tag
* feat(server): add landing page
Fixesorhun/rustypaste#13
* feat(server): allow using {REPOSITORY} in landing page
* fix(server): Get rid of unused import, add line about expiration
* chore(fmt): cargo fmt
* fix(tests): inject app data for fixing index test
* feat(server): redirect to GitHub repository if landing page is not specified
* test(fixtures): add fixture test for landing page
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
Add systemd files to serve files from /var/lib/rustypaste, automatic
user creation via systemd-sysusers and AUTH_TOKEN configuration via
rustypaste.env in /etc/rustypaste/rustypaste.env.
implements #16
feat(server): support auto-deletion of expired files (#17)
chore(ci): set the number of test threads to 1
feat(config): allow the real-time update of cleanup routine
docs(readme): update README.md about deleting expired files
Even if `random_url` is set, the filename will be override.txt
[`rustypaste-cli`](https://github.com/orhun/rustypaste-cli) also has a new argument for overriding the file name:
```sh
rpaste -n filename-on-server.txt awesome.txt
```
- Use more specific HTTP status codes by @tessus in [#262](https://github.com/orhun/rustypaste/pull/262)
`rustypaste` now returns more appropriate status codes in the following 2 cases (instead of a generic 500 code):
- If the mime type is on the blacklist: `UnsupportedMediaType` (415)
- If the file already exists: `Conflict` (409)
### Changed
- Do path joins more safely by @RealOrangeOne in [#247](https://github.com/orhun/rustypaste/pull/247)
- Gracefully exit when there is no config file found by @orhun
- Switch to cargo-llvm-cov for code coverage by @orhun in [#260](https://github.com/orhun/rustypaste/pull/260)
- Replace unmaintained action by @tessus in [#266](https://github.com/orhun/rustypaste/pull/266)
- Set up mergify by @orhun
- Apply clippy suggestions by @orhun
- Update funding options by @orhun
- Update the copyright years by @orhun
- Bump dependencies
### Fixed
- Improve logging for deleted file by @tessus in [#235](https://github.com/orhun/rustypaste/pull/235)
- Fix deployment by @tessus in [#236](https://github.com/orhun/rustypaste/pull/236)
- Return the correct file on multiple files with same name by @tessus in [#234](https://github.com/orhun/rustypaste/pull/234)
- Update the hash of the example file by @tessus in [#254](https://github.com/orhun/rustypaste/pull/254)
- Error on upload with the same filename by @tessus in [#258](https://github.com/orhun/rustypaste/pull/258)
### New Contributors
- @RealOrangeOne made their first contribution in [#247](https://github.com/orhun/rustypaste/pull/247)
## [0.14.4] - 2023-12-20
### Removed
- Remove excessive warning messages when auth tokens are not found (#210)
## [0.14.3] - 2023-12-12
### Changed
- Return `404` for not exposed endpoints instead of `403`
- Disallow blank `delete_tokens` and `auth_tokens`
- Bump dependencies
## [0.14.2] - 2023-12-05
### Added
- Add installation instructions for FreeBSD (#177)
- Add auth token handling to HTML form example (#183)
- Add release instructions
### Changed
- Bump Shuttle to `0.34.1`
- Bump dependencies
## [0.14.1] - 2023-11-02
### Changed
- Switch to `tracing` for logging (#163)
- Bump Shuttle to `0.31.0`
- Bump dependencies
## [0.14.0] - 2023-09-05
### Added
- Add delete endpoint (#136)
Now you can delete files from the server with sending a [`DELETE`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE) request. To enable this, set the `delete_tokens` array in the configuration file or use the `DELETE_TOKEN` environment variable.
```toml
[server]
delete_tokens = [ "may_the_force_be_with_you" ]
```
And then you can send a `DELETE` request as follows:
The configuration is backwards compatible but we recommend using the new `landing_page` section as shown above since the other fields are now deprecated.
- Add random suffix mode (#69)
- Support appending a random suffix to the filename before the extension. For example, `foo.tar.gz` will result in `foo.eu7f92x1.tar.gz`
- This would be really useful to have for setups where the service is running behind a reverse-proxy or gateway and the possibility to adjust the logging output based on their availability, to have the real IP addresses of the clients available in the log.
- Add new line character to the 404 message (#72)
Terminal output will look better when the file is not found:
```sh
$ curl http://localhost:8000/sweeping-tahr
file is not found or expired :(
```
- Add editorconfig for correctly formatting the test fixture files
- Add pull request template
### Changed
- Bump Shuttle to `0.20.0`
- List all the supported units in the documentation (#63)
- Note that the Alpine Linux package is moved to the community
- Use the static folder for the Shuttle config (#70)
- There was a regression in the previous release that has caused the static folder to be not present in Shuttle deployments. This shouldn't be an issue anymore and the deployment should be live.
- Also, it is now possible to trigger a deployment manually via GitHub Actions.
Thanks to [@tessus](https://github.com/tessus) for his contributions to this release!
## [0.10.1] - 2023-06-05
### Added
- Add a middleware for checking the content length
- Before, the upload size was checked after full upload which was clearly wrong.
- With this change, total amount of bytes to upload is checked via [`Content-Length`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length) header before the upload.
- Allow configuring the content type for the landing page
`landing_page_content_type` is added as a configuration option for setting the [`Content-Type`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) header:
There is an example added to the repository: [html_form.toml](https://github.com/orhun/rustypaste/blob/1a8958966972f2afb04a12cb2f5537a1d971561c/examples/html_form.toml)
Also, there is an ongoing discussion about refactoring the usage of landing page fields in the configuration file. See [#52](https://github.com/orhun/rustypaste/issues/52)
- An informative log message is added for showing the server address at startup
## [0.9.1] - 2023-05-24
### Changed
- Bump Shuttle to `0.17.0`
- Tweak public instance settings
- Increase the default expiry time to 24 hours
- Increase the max content length to 20MB
- Bump dependencies
## [0.9.0] - 2023-05-17
The public instance is now available at [https://rustypaste.shuttleapp.rs](https://rustypaste.shuttleapp.rs) 🚀
Read the blog post about `rustypaste` and Shuttle deployments: [https://blog.orhun.dev/blazingly-fast-file-sharing](https://blog.orhun.dev/blazingly-fast-file-sharing)
### Added
- Deploy on Shuttle.rs
- Support setting a default expiry time
You can now specify a expiry time for uploaded files. For example, if you want all the files to expire after one hour:
```toml
[paste]
default_expiry = "1h"
```
- Support overriding the server URL
If you are using `rustypaste` with a redirect or reverse proxy, it is now possible to set a different URL for the returned results:
```toml
[server]
url = "https://rustypaste.shuttleapp.rs"
```
- Add instructions for installing on Alpine Linux
`rustypaste` is now available in [testing](https://pkgs.alpinelinux.org/packages?name=rustypaste&branch=edge) repositories.
- Add new crate features
- `shuttle`: enable an entry point for deploying on Shuttle
- `openssl`: use distro OpenSSL (binary size is reduced ~20% in release mode)
- `rustls`: use [rustls](https://github.com/rustls/rustls) (enabled as default)
### Changed
- Make the default landing page fancier
- Generate SBOM attestation for the Docker image
### Updated
- Bump dependencies
- Update the funding options
- Consider donating if you liked `rustypaste`: [https://donate.orhun.dev](https://donate.orhun.dev) 💖
## [0.8.4] - 2023-01-31
### Added
- Allow downloading files via `?download=true` parameter
- If you specify this for a file (e.g. `<server_address>/file?download=true`), `rustypaste` will override the MIME type to `application/octet-stream` and this will force your browser to download the file.
- This is useful when e.g. you want to be able to share the link to a file that would play in the browser (like `.mp4`) but also share a link that will auto-download as well.
## [0.8.3] - 2023-01-30
### Updated
- Bump dependencies
- Switch to [Rust](https://hub.docker.com/_/rust) image for the Dockerfile
- Remove unused `clap` dependency
## [0.8.2] - 2022-10-04
### Updated
- Don't expose version endpoint in default config
- Set `expose_version` to `false` in the configuration file
## [0.8.1] - 2022-10-04
### Added
- Add `<server_address>/version` endpoint for retrieving the server version
```toml
[server]
expose_version=true
```
If `expose_version` entry is not present in the configuration file, `/version` is not exposed. It is recommended to use this feature with authorization enabled.
### Fixed
- Replace unmaintained `dotenv` crate with `dotenvy`
You can now specify a landing page text in the configuration file as follows:
```toml
[server]
landing_page = """
boo 👻
======
welcome!
"""
```
If the landing page entry is not present in the configuration file, visiting the index page will redirect to the repository.
### Updated
- Do not check for duplicate files by default
- Set `duplicate_files` to `true` in the configuration file
- It is an expensive operation to do on slower hardware and can take an unreasonable amount of time for bigger files
- Enable [GitHub Sponsors](https://github.com/sponsors/orhun) for funding
- Consider supporting me for my open-source work 💖
## [0.7.1] - 2022-05-21
### Added
- Aggressively test everything
- Add the missing unit tests for the server endpoints (code coverage is increased to 84%)
- Create a custom testing framework (written in Bash) for adding [test fixtures](https://github.com/orhun/rustypaste/tree/master/fixtures)
## [0.7.0] - 2022-03-26
### Added
- Support auto-deletion of expired files
`rustypaste` can now delete the expired files by itself. To enable this feature, add the following line to the `[paste]` section in the configuration file:
For users who want to have this feature disabled, there is an alternative [shell script](README.md#cleaning-up-expired-files) recommended in the documentation.
- Add systemd service files
- [systemd files](./extra/systemd/) have been added to serve files from `/var/lib/rustypaste`, create `rustypaste` user automatically via `systemd-sysusers` and configure `AUTH_TOKEN` via `rustypaste.env`.
- For the installation and usage, see the Arch Linux [PKGBUILD](https://github.com/archlinux/svntogit-community/blob/packages/rustypaste/trunk/PKGBUILD).
### Updated
- Upgrade Actix dependencies
- `actix-web` is updated to [`4.0.*`](https://github.com/actix/actix-web/blob/master/actix-web/CHANGES.md#401---2022-02-25)
- Strip the binaries during automated builds
- Size of the Docker image is reduced by ~20%
### Fixed
- Prevent invalid attempts of serving directories
- This fixes an issue where requesting a directory was possible via e.g. `curl --path-as-is 0.0.0.0:8080/.`
- This issue had no security impact (path traversal wasn't possible) since internal server error was returned.
## [0.6.5] - 2022-03-13
### Added
- Add instructions for installing [rustypaste](https://archlinux.org/packages/community/x86_64/rustypaste/) on Arch Linux
- `pacman -S rustypaste` 🎉
### Fixed
- Fix a bug where the use of `CONFIG` environment variable causes a conflict between the configuration file path and `[config]` section
## [0.6.4] - 2022-03-11
### Added
- Support setting the refresh rate for hot-reloading the configuration file.
```toml
[config]
refresh_rate="1s"
```
- Support setting the timeout for HTTP requests.
```toml
[server]
timeout="30s"
```
### Security
- Bump [regex crate](https://github.com/rust-lang/regex) to **1.5.5**
- Support setting the authentication token in the configuration file.
- This is an alternative (but not recommended) way of setting up authentication when the use of `AUTH_TOKEN` environment variable is not applicable.
```toml
[server]
auth_token="hunter2"
```
## [0.6.2] - 2021-12-05
### Updated
- Improve the concurrency
- Shrink the scope of non-suspendable types (`#[must_not_suspend]`) for dropping them before reaching a suspend point (`.await` call). This avoids possible deadlocks, delays, and situations where `Future`s not implementing `Send`.
- Errors that may occur while locking the [Mutex](https://doc.rust-lang.org/std/sync/struct.Mutex.html) are handled properly hence a single configuration change cannot take down the whole service due to [poisoning](https://doc.rust-lang.org/std/sync/struct.Mutex.html#poisoning).
## [0.6.0] - 2021-11-07
### Added
- Support pasting files from remote URLs (via `remote=` form field)
- `{server.max_content_length}` is used for download limit
- See [README.md#paste-file-from-remote-url](https://github.com/orhun/rustypaste#paste-file-from-remote-url)
- Hot reload configuration file to apply configuration changes instantly without restarting the server
### Changed
- Library: Switch to Rust 2021 edition
### Security
- Prevent serving an already expired file
In the previous versions, it was possible to view an expired file by using the correct extension (timestamp). e.g. `paste.com/expired_file.txt.1630094518049` will serve the file normally although `paste.com/expired_file.txt` says that it is expired. This version fixes this vulnerability by regex-checking the requested file's extension.
`rustypaste` is available for [Alpine Edge](https://pkgs.alpinelinux.org/packages?name=rustypaste&branch=edge). It can be installed via [apk](https://wiki.alpinelinux.org/wiki/Alpine_Package_Keeper) after enabling the [community repository](https://wiki.alpinelinux.org/wiki/Repositories).
```sh
apk add rustypaste
```
### FreeBSD
```sh
pkg install rustypaste
```
### Binary releases
See the available binaries on the [releases](https://github.com/orhun/rustypaste/releases/) page.
### Build from source
```sh
git clone https://github.com/orhun/rustypaste.git
cd rustypaste/
cargo build --release
```
#### Feature flags
- `shuttle`: enable an entry point for deploying on Shuttle
- `openssl`: use distro OpenSSL (binary size is reduced ~20% in release mode)
- `rustls`: use [rustls](https://github.com/rustls/rustls) (enabled as default)
To enable a feature for build, pass `--features` flag to `cargo build` command.
For example, to reuse the OpenSSL present on a distro already:
Set `delete_tokens` array in [config.toml](./config.toml) to activate the [`DELETE`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE) endpoint and secure it with one (or more) auth token(s).
You can also set multiple auth tokens via the array field `[server].auth_tokens` in your `config.toml`.
> If neither `AUTH_TOKEN` nor `[server].auth_tokens` are set, the server will not require any authentication.
>
> Exception is the `DELETE` endpoint, which requires at least one token to be set. See [deleting files from server](#delete-file-from-server) for more information.
See [config.toml](./config.toml) for configuration options.
#### List endpoint
Set `expose_list` to true in [config.toml](./config.toml) to be able to retrieve a JSON formatted list of files in your uploads directory. This will not include oneshot files, oneshot URLs, or URLs.
This route will require an `AUTH_TOKEN` if one is set.
#### HTML Form
It is possible to use an HTML form for uploading files. To do so, you need to update two fields in your `config.toml`:
- Set the `[landing_page].content_type` to `text/html; charset=utf-8`.
- Update the `[landing_page].text` field with your HTML form or point `[landing_page].file` to your html file.
For an example, see [examples/html_form.toml](./examples/html_form.toml)
#### Docker
Following command can be used to run a container which is built from the [Dockerfile](./Dockerfile) in this repository:
@ -81,6 +323,7 @@ Following command can be used to run a container which is built from the [Docker
```sh
$ docker run --rm -d \
-v "$(pwd)/upload/":/app/upload \
-v "$(pwd)/config.toml":/app/config.toml \
--env-file "$(pwd)/.env" \
-e "RUST_LOG=debug" \
-p 8000:8000 \
@ -123,21 +366,11 @@ http {
}
```
### Roadmap
- Support "disappearing" files
- Support setting an expiry date for uploads
- Write a CLI tool in Rust
### Contributing
Pull requests are welcome!
Consider submitting your ideas via issues first. Also, see the [roadmap](#roadmap) and/or run the following command to see what is needed to be done:
```sh
$ grep -nr "TODO:" src/
```
Consider submitting your ideas via [issues](https://github.com/orhun/rustypaste/issues/new) first and check out the [existing issues](https://github.com/orhun/rustypaste/issues).