Table of content:
The general info about this project you can read in the README.md file. In this document, you will find a more detailed explanation of how it works, how we write components, etc.
From README.md:
So, as you can already guess, the Rust code is compiled into WASM using trunk and then executes on the client side in the browser. It also means that any heavy computation will affect the client browser performance and can even freeze it (for example, bcrypt
with 20 rounds).
The compiled app looks like a bunch of files (.html
, .css
, .wasm
, .js
). All these files are just served in the user's browser.
Why yew
?
Because it's a great framework for building web applications in Rust. It is very familiar to React.js
devs. The only disadvantage I've seen is styling: yew doesn't have any good tools/libraries for styling at this moment. At this moment, all styles are written in .scss
files. Classes are used in components via the classes!
macro.
- Rust is the main programming language in this project. It allows us to write highly maintained code with less amount of bugs.
- Fast computations thanks to the WASM.
- We use the custom
rustfmt.toml
configuration. If you want to change some formatting options then create a pull request with changes and an explanation of your motivation, how it'll help us, etc. - All code must be formatted using the
cargo fmt
. Runcargo +nightly fmt --all -- --check
. - All build and clippy warnings must be fixed. Run
cargo clippy -- -D warnings
.
We have three main groups of components (divided by purpose):
- General purpose components.
- Crypto-helper related components.
- Jwt related components.
- Other components.
Those components can be used on any app page and located in the src/common
directory. They are small, without side effects, and have only one special purpose. Examples:
ByteInput
. This component is used for the bytes entering. You can use it in any place where you need to take any input bytes from the user. It automatically supports many input formats, validation, etc.
Switch
. Just a regular switch. Can be used to switch between any two options. For example,encrypt <-> decrypt
,hash <-> verify
, etc.
- There are and will be more common components. The above two are just examples. If some component was purpose specialized during creation but become common, then it should be moved in the
src/common
directory.
In short: all components from the src/crypto_helper
directory belong to this group. Here are the input/output components for the different algorithms, computations, etc.
If some components will be used only on the /crypto-helper
page, then they should be placed somewhere in the src/crypto_helper
directory.
In short: all components from the src/jwt
directory belong to this group. Here are the input/output components for the JWT, its parts parsing/editing/viewing, etc.
If some components will be used only on the /jwt
page, then they should be placed somewhere in the src/jwt
directory.
The About
page, Header
, Footer
, etc.
- Validate on input.
Components that take some input from the user usually have their validation rules. For example, the ByteInput
component with the ByteFormat::Hex
parameter will require only hex-encoded bytes from the user.
In the app state, we save only validated/parsed data. If the user enters an invalid string, then inform about it. But do not save raw String
or smth like that in the state. If you look at the Algorithm
enum, you can see that all input data for algorithms save in a "parsed" state:
// some fields and structures are omitted
enum Algorithm {
Md5(Vec<u8>),
Rsa(RsaInput),
}
struct RsaInput {
pub action: RsaAction,
pub payload: Vec<u8>,
}
enum RsaAction {
Encrypt(RsaPublicKey),
Decrypt(RsaPrivateKey),
Sign(RsaSignInput),
Verify(RsaVerifyInput),
}
You won't find any raw Strings. Bytes for hashing/encryption are Vec<u8>
(not raw String
), RSA keys are parsed and saved in Public/PrivateKey
structures, etc.
- Logging.
This app has a simple and typical logging system: wasm-logger
+ log
crates. If you want to log something, then just use any suitable for you macros from the log
crate. All logs will be written into the browser's console. This is how it looks:
- Inform user about everything.
You have two main ways how to tell the user that something went wrong:
- Spawn notifications using the
use_notifications
hook from theyew_notifications
crate. - Different UI tricks like painting the input component in red, on-page messages, etc. Example: