diff --git a/.gitignore b/.gitignore index 75aa90c..cef59bb 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ node_modules /assets/build.js /assets/build.js.map /assets/style.css +config diff --git a/assets/style.css b/assets/style.css index 3261db9..86b50e1 100644 --- a/assets/style.css +++ b/assets/style.css @@ -885,6 +885,10 @@ select { width: 1.25rem; } +.w-64 { + width: 16rem; +} + .w-8 { width: 2rem; } @@ -1113,6 +1117,11 @@ select { line-height: 1.25rem; } +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} + .font-bold { font-weight: 700; } diff --git a/crates/oswilno-parking-space/src/lib.rs b/crates/oswilno-parking-space/src/lib.rs index c43870f..6fe6f24 100644 --- a/crates/oswilno-parking-space/src/lib.rs +++ b/crates/oswilno-parking-space/src/lib.rs @@ -29,6 +29,16 @@ pub fn mount(config: &mut ServiceConfig) { ); } +pub fn translations(l10n: &mut oswilno_view::TranslationStorage) { + l10n + // Polish + .with_lang(oswilno_view::Lang::Pl) + .add("Location", "Miejsce") + .add("Spot", "Miejsce postojowe") + .add("Register parking space", "Zarejestruj miejsce postojowe") + .done(); +} + #[autometrics] #[get("/")] async fn root() -> HttpResponse { @@ -139,8 +149,8 @@ async fn load_locations(db: Arc) -> Vec) { diff --git a/crates/oswilno-parking-space/templates/parking-spaces/form-partial.html b/crates/oswilno-parking-space/templates/parking-spaces/form-partial.html index 8d36053..c76fb7d 100644 --- a/crates/oswilno-parking-space/templates/parking-spaces/form-partial.html +++ b/crates/oswilno-parking-space/templates/parking-spaces/form-partial.html @@ -1,12 +1,23 @@
+

{{ "Register parking space"|t(lang,t) }}

{% for error in errors.global() %} {{error|t(lang,t)}} {% endfor %} -
+
- - {% for loc in locations %}
+
+ + +
diff --git a/crates/oswilno-server/src/main.rs b/crates/oswilno-server/src/main.rs index 61799fa..5ea778b 100644 --- a/crates/oswilno-server/src/main.rs +++ b/crates/oswilno-server/src/main.rs @@ -49,6 +49,8 @@ async fn main() -> std::io::Result<()> { let session_config = oswilno_session::SessionConfigurator::new(redis.clone()); session_config.translations(&mut l10n); + oswilno_parking_space::translations(&mut l10n); + oswilno_parking_space::init(Arc::new(conn.clone())).await; HttpServer::new(move || { diff --git a/crates/oswilno-session/src/lib.rs b/crates/oswilno-session/src/lib.rs index 50c4326..34e2ab7 100644 --- a/crates/oswilno-session/src/lib.rs +++ b/crates/oswilno-session/src/lib.rs @@ -1,3 +1,4 @@ +use std::io::Read; use std::ops::Add; use std::sync::Arc; @@ -99,12 +100,6 @@ impl SessionConfigurator { pub fn translations(&self, l10n: &mut oswilno_view::TranslationStorage) { l10n - // English - .with_lang(oswilno_view::Lang::En) - .add("Sign in", "Sign in") - .add("Sign up", "Sign up") - .add("Bad credentials", "Bad credentials") - .done() // Polish .with_lang(oswilno_view::Lang::Pl) .add("Sign in", "Logowanie") @@ -127,7 +122,10 @@ impl SessionConfigurator { pub fn new(redis: redis_async_pool::RedisPool) -> Self { let jwt_ttl = JWTTtl(std::time::Duration::from_secs(31 * 60 * 60)); - let jwt_signing_keys = JwtSigningKeys::generate().unwrap(); + + std::fs::create_dir_all("./config").ok(); + + let jwt_signing_keys = JwtSigningKeys::load_or_create(); let auth_middleware_factory = RedisMiddlewareFactory::::new( Arc::new(jwt_signing_keys.encoding_key), Arc::new(jwt_signing_keys.decoding_key), @@ -303,11 +301,13 @@ async fn login_inner( actix_web::cookie::Cookie::build(actix_jwt_session::DEFAULT_HEADER_NAME, &bearer_token) .http_only(true) .finish(); - Ok(HttpResponse::Ok() + Ok(HttpResponse::SeeOther() .append_header(( actix_jwt_session::DEFAULT_HEADER_NAME, format!("Bearer {bearer_token}").as_str(), )) + .append_header(("Location", "/")) + .append_header(("HX-Redirect", "/")) .cookie(cookie) .body("")) } @@ -552,14 +552,42 @@ pub struct JwtSigningKeys { } impl JwtSigningKeys { + fn load_or_create() -> Self { + match Self::load_from_files() { + Ok(s) => s, + Err(e) if e.kind() == std::io::ErrorKind::NotFound => Self::generate().unwrap(), + Err(e) => panic!("{:?}", e), + } + } + fn generate() -> Result> { let doc = Ed25519KeyPair::generate_pkcs8(&SystemRandom::new())?; let keypair = Ed25519KeyPair::from_pkcs8(doc.as_ref())?; let encoding_key = EncodingKey::from_ed_der(doc.as_ref()); let decoding_key = DecodingKey::from_ed_der(keypair.public_key().as_ref()); + + std::fs::write("./config/jwt-encoding.bin", doc.as_ref()).unwrap(); + std::fs::write("./config/jwt-decoding.bin", keypair.public_key()).unwrap(); + Ok(JwtSigningKeys { encoding_key, decoding_key, }) } + + fn load_from_files() -> std::io::Result { + let mut buf = Vec::new(); + let mut e = std::fs::File::open("./config/jwt-encoding.bin")?; + e.read_to_end(&mut buf).unwrap(); + let encoding_key: EncodingKey = EncodingKey::from_ed_der(&buf); + + let mut buf = Vec::new(); + let mut e = std::fs::File::open("./config/jwt-decoding.bin")?; + e.read_to_end(&mut buf).unwrap(); + let decoding_key = DecodingKey::from_ed_der(&buf); + Ok(Self { + encoding_key, + decoding_key, + }) + } } diff --git a/crates/oswilno-view/src/filters.rs b/crates/oswilno-view/src/filters.rs index d8c9afa..31426b3 100644 --- a/crates/oswilno-view/src/filters.rs +++ b/crates/oswilno-view/src/filters.rs @@ -11,3 +11,11 @@ pub fn t( // tracing::debug!("translating {s:?} to lang {lang:?} with {t:?}"); Ok(t.to_lang(*lang, &s.to_string())) } + +pub fn skip_if(n: &T, skip: T) -> Result { + Ok(if n == &skip { + "".to_string() + } else { + n.to_string() + }) +}