add initial jwt code
This commit is contained in:
		
							parent
							
								
									dea8968f6b
								
							
						
					
					
						commit
						99246773ef
					
				
					 8 changed files with 218 additions and 20 deletions
				
			
		
							
								
								
									
										124
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										124
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -462,6 +462,15 @@ dependencies = [
 | 
				
			||||||
 "zeroize",
 | 
					 "zeroize",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "deranged"
 | 
				
			||||||
 | 
					version = "0.3.9"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "powerfmt",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "digest"
 | 
					name = "digest"
 | 
				
			||||||
version = "0.10.7"
 | 
					version = "0.10.7"
 | 
				
			||||||
| 
						 | 
					@ -897,6 +906,7 @@ dependencies = [
 | 
				
			||||||
 "eyre",
 | 
					 "eyre",
 | 
				
			||||||
 "handlebars",
 | 
					 "handlebars",
 | 
				
			||||||
 "headers",
 | 
					 "headers",
 | 
				
			||||||
 | 
					 "jsonwebtoken",
 | 
				
			||||||
 "rust-embed",
 | 
					 "rust-embed",
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "sqlx",
 | 
					 "sqlx",
 | 
				
			||||||
| 
						 | 
					@ -955,6 +965,20 @@ dependencies = [
 | 
				
			||||||
 "wasm-bindgen",
 | 
					 "wasm-bindgen",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "jsonwebtoken"
 | 
				
			||||||
 | 
					version = "9.1.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "155c4d7e39ad04c172c5e3a99c434ea3b4a7ba7960b38ecd562b270b097cce09"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "base64",
 | 
				
			||||||
 | 
					 "pem",
 | 
				
			||||||
 | 
					 "ring 0.17.5",
 | 
				
			||||||
 | 
					 "serde",
 | 
				
			||||||
 | 
					 "serde_json",
 | 
				
			||||||
 | 
					 "simple_asn1",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "lazy_static"
 | 
					name = "lazy_static"
 | 
				
			||||||
version = "1.4.0"
 | 
					version = "1.4.0"
 | 
				
			||||||
| 
						 | 
					@ -1083,6 +1107,17 @@ dependencies = [
 | 
				
			||||||
 "winapi",
 | 
					 "winapi",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "num-bigint"
 | 
				
			||||||
 | 
					version = "0.4.4"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "autocfg",
 | 
				
			||||||
 | 
					 "num-integer",
 | 
				
			||||||
 | 
					 "num-traits",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "num-bigint-dig"
 | 
					name = "num-bigint-dig"
 | 
				
			||||||
version = "0.8.4"
 | 
					version = "0.8.4"
 | 
				
			||||||
| 
						 | 
					@ -1191,6 +1226,16 @@ version = "1.0.14"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
 | 
					checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "pem"
 | 
				
			||||||
 | 
					version = "3.0.2"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "3163d2912b7c3b52d651a055f2c7eec9ba5cd22d26ef75b8dd3a59980b185923"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "base64",
 | 
				
			||||||
 | 
					 "serde",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "pem-rfc7468"
 | 
					name = "pem-rfc7468"
 | 
				
			||||||
version = "0.7.0"
 | 
					version = "0.7.0"
 | 
				
			||||||
| 
						 | 
					@ -1310,6 +1355,12 @@ version = "0.3.27"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
 | 
					checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "powerfmt"
 | 
				
			||||||
 | 
					version = "0.2.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "ppv-lite86"
 | 
					name = "ppv-lite86"
 | 
				
			||||||
version = "0.2.17"
 | 
					version = "0.2.17"
 | 
				
			||||||
| 
						 | 
					@ -1421,11 +1472,25 @@ dependencies = [
 | 
				
			||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
 "once_cell",
 | 
					 "once_cell",
 | 
				
			||||||
 "spin 0.5.2",
 | 
					 "spin 0.5.2",
 | 
				
			||||||
 "untrusted",
 | 
					 "untrusted 0.7.1",
 | 
				
			||||||
 "web-sys",
 | 
					 "web-sys",
 | 
				
			||||||
 "winapi",
 | 
					 "winapi",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "ring"
 | 
				
			||||||
 | 
					version = "0.17.5"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "cc",
 | 
				
			||||||
 | 
					 "getrandom",
 | 
				
			||||||
 | 
					 "libc",
 | 
				
			||||||
 | 
					 "spin 0.9.8",
 | 
				
			||||||
 | 
					 "untrusted 0.9.0",
 | 
				
			||||||
 | 
					 "windows-sys",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "rsa"
 | 
					name = "rsa"
 | 
				
			||||||
version = "0.9.2"
 | 
					version = "0.9.2"
 | 
				
			||||||
| 
						 | 
					@ -1508,7 +1573,7 @@ version = "0.21.7"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8"
 | 
					checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "ring",
 | 
					 "ring 0.16.20",
 | 
				
			||||||
 "rustls-webpki",
 | 
					 "rustls-webpki",
 | 
				
			||||||
 "sct",
 | 
					 "sct",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
| 
						 | 
					@ -1528,8 +1593,8 @@ version = "0.101.6"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe"
 | 
					checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "ring",
 | 
					 "ring 0.16.20",
 | 
				
			||||||
 "untrusted",
 | 
					 "untrusted 0.7.1",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
| 
						 | 
					@ -1565,8 +1630,8 @@ version = "0.7.0"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
 | 
					checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "ring",
 | 
					 "ring 0.16.20",
 | 
				
			||||||
 "untrusted",
 | 
					 "untrusted 0.7.1",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
| 
						 | 
					@ -1663,6 +1728,18 @@ dependencies = [
 | 
				
			||||||
 "rand_core",
 | 
					 "rand_core",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "simple_asn1"
 | 
				
			||||||
 | 
					version = "0.6.2"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "num-bigint",
 | 
				
			||||||
 | 
					 "num-traits",
 | 
				
			||||||
 | 
					 "thiserror",
 | 
				
			||||||
 | 
					 "time",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "slab"
 | 
					name = "slab"
 | 
				
			||||||
version = "0.4.9"
 | 
					version = "0.4.9"
 | 
				
			||||||
| 
						 | 
					@ -2030,6 +2107,35 @@ dependencies = [
 | 
				
			||||||
 "once_cell",
 | 
					 "once_cell",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "time"
 | 
				
			||||||
 | 
					version = "0.3.30"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "deranged",
 | 
				
			||||||
 | 
					 "itoa",
 | 
				
			||||||
 | 
					 "powerfmt",
 | 
				
			||||||
 | 
					 "serde",
 | 
				
			||||||
 | 
					 "time-core",
 | 
				
			||||||
 | 
					 "time-macros",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "time-core"
 | 
				
			||||||
 | 
					version = "0.1.2"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "time-macros"
 | 
				
			||||||
 | 
					version = "0.2.15"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "time-core",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "tinyvec"
 | 
					name = "tinyvec"
 | 
				
			||||||
version = "1.6.0"
 | 
					version = "1.6.0"
 | 
				
			||||||
| 
						 | 
					@ -2246,6 +2352,12 @@ version = "0.7.1"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
 | 
					checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "untrusted"
 | 
				
			||||||
 | 
					version = "0.9.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "url"
 | 
					name = "url"
 | 
				
			||||||
version = "2.4.1"
 | 
					version = "2.4.1"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@ dotenvy = "0.15.7"
 | 
				
			||||||
eyre = "0.6.8"
 | 
					eyre = "0.6.8"
 | 
				
			||||||
handlebars = { version = "4.4.0", features = ["rust-embed", "dir_source"] }
 | 
					handlebars = { version = "4.4.0", features = ["rust-embed", "dir_source"] }
 | 
				
			||||||
headers = "0.3.9"
 | 
					headers = "0.3.9"
 | 
				
			||||||
 | 
					jsonwebtoken = "9.1.0"
 | 
				
			||||||
rust-embed = "8.0.0"
 | 
					rust-embed = "8.0.0"
 | 
				
			||||||
serde = { version = "1.0.189", features = ["derive"] }
 | 
					serde = { version = "1.0.189", features = ["derive"] }
 | 
				
			||||||
sqlx = { version = "0.7.2", features = ["runtime-tokio", "tls-rustls", "postgres", "macros", "migrate", "chrono"] }
 | 
					sqlx = { version = "0.7.2", features = ["runtime-tokio", "tls-rustls", "postgres", "macros", "migrate", "chrono"] }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,4 +8,6 @@ pub struct Config {
 | 
				
			||||||
    pub port: u16,
 | 
					    pub port: u16,
 | 
				
			||||||
    #[arg(long, env, default_value_t = false)]
 | 
					    #[arg(long, env, default_value_t = false)]
 | 
				
			||||||
    pub dev_mode: bool,
 | 
					    pub dev_mode: bool,
 | 
				
			||||||
 | 
					    #[arg(env)]
 | 
				
			||||||
 | 
					    pub secret_key: String,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ use axum::{
 | 
				
			||||||
use headers::Cookie;
 | 
					use headers::Cookie;
 | 
				
			||||||
use tracing::error;
 | 
					use tracing::error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{model::user::User, state::AppState};
 | 
					use crate::{model::user::User, state::AppState, token::Claims};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct ExtractUserToken(pub Option<User>);
 | 
					pub struct ExtractUserToken(pub Option<User>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,17 +33,28 @@ where
 | 
				
			||||||
            Err(err) => {
 | 
					            Err(err) => {
 | 
				
			||||||
                error!("Getting cookie header: {}", err);
 | 
					                error!("Getting cookie header: {}", err);
 | 
				
			||||||
                return Ok(ExtractUserToken(None));
 | 
					                return Ok(ExtractUserToken(None));
 | 
				
			||||||
            },
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let user = match cookie.get("imgboard-token") {
 | 
					        match cookie.get("imgboard-token") {
 | 
				
			||||||
            Some(_token) => {
 | 
					            Some(token) => {
 | 
				
			||||||
                // TODO: get from token
 | 
					                let claims = Claims::decode(token, &state.decoding_key).map_err(|e| {
 | 
				
			||||||
                None
 | 
					                    error!("Decoding token claims: {}", e);
 | 
				
			||||||
            },
 | 
					                    (StatusCode::INTERNAL_SERVER_ERROR, "Internal server error")
 | 
				
			||||||
            None => None,
 | 
					                })?;
 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(ExtractUserToken(user))
 | 
					                match sqlx::query_as!(User, r#"SELECT * FROM users WHERE id = $1"#, claims.uid)
 | 
				
			||||||
 | 
					                    .fetch_one(&state.pool)
 | 
				
			||||||
 | 
					                    .await
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Ok(u) => Ok(ExtractUserToken(Some(u))),
 | 
				
			||||||
 | 
					                    Err(err) => {
 | 
				
			||||||
 | 
					                        error!("Getting user from database: {}", err);
 | 
				
			||||||
 | 
					                        Err((StatusCode::INTERNAL_SERVER_ERROR, "Internal server error"))
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            None => Ok(ExtractUserToken(None)),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										16
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								src/main.rs
									
										
									
									
									
								
							| 
						 | 
					@ -4,6 +4,7 @@ pub mod model;
 | 
				
			||||||
pub mod pages;
 | 
					pub mod pages;
 | 
				
			||||||
pub mod state;
 | 
					pub mod state;
 | 
				
			||||||
pub mod templates;
 | 
					pub mod templates;
 | 
				
			||||||
 | 
					pub mod token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
 | 
					use std::net::{IpAddr, Ipv4Addr, SocketAddr};
 | 
				
			||||||
use std::sync::Arc;
 | 
					use std::sync::Arc;
 | 
				
			||||||
| 
						 | 
					@ -11,6 +12,7 @@ use std::sync::Arc;
 | 
				
			||||||
use axum::{routing::get, Router};
 | 
					use axum::{routing::get, Router};
 | 
				
			||||||
use clap::Parser;
 | 
					use clap::Parser;
 | 
				
			||||||
use eyre::{Result, WrapErr};
 | 
					use eyre::{Result, WrapErr};
 | 
				
			||||||
 | 
					use jsonwebtoken::{DecodingKey, EncodingKey};
 | 
				
			||||||
use sqlx::migrate;
 | 
					use sqlx::migrate;
 | 
				
			||||||
use sqlx::postgres::PgPoolOptions;
 | 
					use sqlx::postgres::PgPoolOptions;
 | 
				
			||||||
use tower_http::trace::TraceLayer;
 | 
					use tower_http::trace::TraceLayer;
 | 
				
			||||||
| 
						 | 
					@ -44,14 +46,24 @@ async fn main() -> Result<()> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    migrate!().run(&pool).await.wrap_err("running migrations")?;
 | 
					    migrate!().run(&pool).await.wrap_err("running migrations")?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let state = Arc::new(AppState { pool, hbs });
 | 
					    let state = Arc::new(AppState {
 | 
				
			||||||
 | 
					        pool,
 | 
				
			||||||
 | 
					        hbs,
 | 
				
			||||||
 | 
					        encoding_key: EncodingKey::from_base64_secret(&config.secret_key)
 | 
				
			||||||
 | 
					            .wrap_err("parsing $SECRET_KEY")?,
 | 
				
			||||||
 | 
					        decoding_key: DecodingKey::from_base64_secret(&config.secret_key)
 | 
				
			||||||
 | 
					            .wrap_err("parsing $SECRET_KEY")?,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    debug!("Building router");
 | 
					    debug!("Building router");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let app = Router::new()
 | 
					    let app = Router::new()
 | 
				
			||||||
        .route("/", get(pages::index))
 | 
					        .route("/", get(pages::index))
 | 
				
			||||||
        .route("/users/:id", get(pages::get_user))
 | 
					        .route("/users/:id", get(pages::get_user))
 | 
				
			||||||
        .route("/users/new", get(pages::get_user_new).post(pages::post_user_new))
 | 
					        .route(
 | 
				
			||||||
 | 
					            "/users/new",
 | 
				
			||||||
 | 
					            get(pages::get_user_new).post(pages::post_user_new),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
        .layer(TraceLayer::new_for_http())
 | 
					        .layer(TraceLayer::new_for_http())
 | 
				
			||||||
        .with_state(state);
 | 
					        .with_state(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,7 @@ pub struct User {
 | 
				
			||||||
    pub last_active: DateTime<Utc>,
 | 
					    pub last_active: DateTime<Utc>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(sqlx::Type, Debug, Clone, PartialEq, Eq)]
 | 
					#[derive(sqlx::Type, Debug, Copy, Clone, PartialEq, Eq)]
 | 
				
			||||||
#[repr(i32)]
 | 
					#[repr(i32)]
 | 
				
			||||||
pub enum Role {
 | 
					pub enum Role {
 | 
				
			||||||
    Viewer = 1,
 | 
					    Viewer = 1,
 | 
				
			||||||
| 
						 | 
					@ -62,3 +62,25 @@ impl TryFrom<&str> for Role {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Into<&str> for Role {
 | 
				
			||||||
 | 
					    fn into(self) -> &'static str {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Self::Viewer => "viewer",
 | 
				
			||||||
 | 
					            Self::Editor => "editor",
 | 
				
			||||||
 | 
					            Self::Manager => "manager",
 | 
				
			||||||
 | 
					            Self::Admin => "admin",
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Into<String> for Role {
 | 
				
			||||||
 | 
					    fn into(self) -> String {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Self::Viewer => "viewer".into(),
 | 
				
			||||||
 | 
					            Self::Editor => "editor".into(),
 | 
				
			||||||
 | 
					            Self::Manager => "manager".into(),
 | 
				
			||||||
 | 
					            Self::Admin => "admin".into(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,19 @@
 | 
				
			||||||
use std::sync::Arc;
 | 
					use std::sync::Arc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use axum::{extract::{FromRef, FromRequestParts}, async_trait, http::request::Parts};
 | 
					use axum::{
 | 
				
			||||||
 | 
					    async_trait,
 | 
				
			||||||
 | 
					    extract::{FromRef, FromRequestParts},
 | 
				
			||||||
 | 
					    http::request::Parts,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					use jsonwebtoken::{DecodingKey, EncodingKey};
 | 
				
			||||||
use sqlx::{postgres::Postgres, Pool};
 | 
					use sqlx::{postgres::Postgres, Pool};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone, FromRef)]
 | 
					#[derive(Clone, FromRef)]
 | 
				
			||||||
pub struct AppState {
 | 
					pub struct AppState {
 | 
				
			||||||
    pub pool: Pool<Postgres>,
 | 
					    pub pool: Pool<Postgres>,
 | 
				
			||||||
    pub hbs: handlebars::Handlebars<'static>,
 | 
					    pub hbs: handlebars::Handlebars<'static>,
 | 
				
			||||||
 | 
					    pub encoding_key: EncodingKey,
 | 
				
			||||||
 | 
					    pub decoding_key: DecodingKey,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[async_trait]
 | 
					#[async_trait]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										31
									
								
								src/token.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/token.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,31 @@
 | 
				
			||||||
 | 
					use jsonwebtoken::{errors::Error, DecodingKey, EncodingKey, Header, Validation};
 | 
				
			||||||
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::model::user::User;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Serialize, Deserialize)]
 | 
				
			||||||
 | 
					pub struct Claims {
 | 
				
			||||||
 | 
					    pub exp: usize,
 | 
				
			||||||
 | 
					    pub uid: i32,
 | 
				
			||||||
 | 
					    pub role: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Claims {
 | 
				
			||||||
 | 
					    pub fn new(user: &User) -> Self {
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            exp: 0,
 | 
				
			||||||
 | 
					            uid: user.id,
 | 
				
			||||||
 | 
					            role: user.role.into(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn encode(self, key: &EncodingKey) -> Result<String, Error> {
 | 
				
			||||||
 | 
					        jsonwebtoken::encode(&Header::default(), &self, key)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn decode(token: &str, key: &DecodingKey) -> Result<Self, Error> {
 | 
				
			||||||
 | 
					        let token = jsonwebtoken::decode::<Claims>(token, key, &Validation::default())?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(token.claims)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue