\n\t\t`;\n\t\tcopyCss(shadow);\n\t}\n});\n", "import './elements/oswilno-price.js';\nimport './elements/oswilno-error.js';\nimport(\"https://unpkg.com/htmx.org@1.9.4/dist/htmx.min.js\");\n\nconst body = document.body;\nbody.addEventListener('htmx:beforeOnLoad', function (evt) {\n\tconsole.log(evt);\n\tconst detail = evt.detail;\n\tconst xhr = detail.xhr;\n\tconst status = xhr.status;\n\tconst successful = detail.successful;\n\n\tconsole.log(successful, xhr.getResponseHeader('Authorization'));\n\tif (status === 200) {\n\t\tconst bearer = xhr.getResponseHeader('Authorization');\n\t\tif (bearer) {\n\t\t\tlocalStorage.setItem('jwt', bearer.replace(/^Bearer /i, ''));\n\t\t}\n\t} else if (status === 401) {\n\t\tlocalStorage.removeItem('jwt');\n\t}\n\tif (status === 422 || status === 400) {\n\t\tdetail.shouldSwap = true;\n\t\tdetail.isError = false;\n\t}\n});\nbody.addEventListener('htmx:configRequest', function (evt) {\n\tif (localStorage.getItem('jwt')) {\n\tevt.detail.headers.Authorization = 'Bearer ' + (localStorage.getItem('jwt') || '');\n\t}\n});\n\n"],
+ "mappings": "0sBAAA,eAAe,OAAO,gBAAiB,cAAc,WAAY,CAChE,aAAc,CACb,MAAM,EACN,KAAK,aAAa,CAAE,KAAM,MAAO,CAAC,CACnC,CACA,mBAAoB,CACnB,IAAIA,EAAS,KAAK,WACdC,EAAQ,SAAS,KAAK,aAAa,OAAO,CAAC,EAC3C,MAAMA,CAAK,IAAGA,EAAQ,GAC1B,IAAMC,EAAa,SAAS,KAAK,aAAa,YAAY,CAAC,EACvDC,EAAQF,EACRG,EAAQ,EACP,MAAMF,CAAU,IACpBC,EAAQ,KAAK,MAAMF,EAAQC,CAAU,EACrCE,EAAQH,EAAQC,GAEjB,IAAMG,EAAW,KAAK,aAAa,UAAU,GAAK,MAClDL,EAAO,UAAY,4CAA4CG,CAAK,IAAIC,GAAS,GAAKA,EAAQA,EAAQ,GAAG,IAAKC,CAAS,QACxH,CACD,CAAC,ECnBM,IAAMC,EAAWC,GAAW,CAClC,IAAIC,EAAM,GACV,QAASC,EAAI,EAAGA,EAAI,SAAS,YAAY,OAAQA,IAAK,CACrD,IAAMC,EAAa,SAAS,YAAYD,CAAC,EACzC,QAASE,EAAI,EAAGA,EAAID,EAAW,MAAM,OAAQC,IAC5CH,GAAOE,EAAW,MAAMC,CAAC,EAAE,OAE7B,CACA,IAAMC,EAAQ,IAAI,cAClBA,EAAM,YAAYJ,CAAG,EACrBD,EAAO,mBAAqB,CAACK,CAAK,CACnC,ECTA,eAAe,OAAO,gBAAiB,cAAc,WAAY,CAChE,aAAc,CACb,MAAM,EACN,IAAMC,EAAS,KAAK,aAAa,CAAE,KAAM,MAAO,CAAC,EACjDA,EAAO,UAAY;AAAA;AAAA;AAAA;AAAA;AAAA,IAMnBC,EAAQD,CAAM,CACf,CACD,CAAC,ECZD,OAAO,mDAAmD,EAE1D,IAAME,EAAO,SAAS,KACtBA,EAAK,iBAAiB,oBAAqB,SAAUC,EAAK,CACzD,QAAQ,IAAIA,CAAG,EACf,IAAMC,EAASD,EAAI,OACbE,EAAMD,EAAO,IACbE,EAASD,EAAI,OACbE,EAAaH,EAAO,WAG1B,GADA,QAAQ,IAAIG,EAAYF,EAAI,kBAAkB,eAAe,CAAC,EAC1DC,IAAW,IAAK,CACnB,IAAME,EAASH,EAAI,kBAAkB,eAAe,EAChDG,GACH,aAAa,QAAQ,MAAOA,EAAO,QAAQ,YAAa,EAAE,CAAC,CAE7D,MAAWF,IAAW,KACrB,aAAa,WAAW,KAAK,GAE1BA,IAAW,KAAOA,IAAW,OAChCF,EAAO,WAAa,GACpBA,EAAO,QAAU,GAEnB,CAAC,EACDF,EAAK,iBAAiB,qBAAsB,SAAUC,EAAK,CACtD,aAAa,QAAQ,KAAK,IAC9BA,EAAI,OAAO,QAAQ,cAAgB,WAAa,aAAa,QAAQ,KAAK,GAAK,IAEhF,CAAC",
+ "names": ["shadow", "price", "multiplier", "major", "minor", "currency", "copyCss", "shadow", "css", "i", "styleSheet", "j", "sheet", "shadow", "copyCss", "body", "evt", "detail", "xhr", "status", "successful", "bearer"]
}
diff --git a/crates/actix-jwt-session/src/lib.rs b/crates/actix-jwt-session/src/lib.rs
index f9cc55f..372a203 100644
--- a/crates/actix-jwt-session/src/lib.rs
+++ b/crates/actix-jwt-session/src/lib.rs
@@ -5,6 +5,8 @@ use serde::{de::DeserializeOwned, Serialize};
use std::sync::Arc;
use uuid::Uuid;
+pub static HEADER_NAME: &str = "Authorization";
+
pub trait Claims: PartialEq + DeserializeOwned + Serialize + Clone + Send + Sync + 'static {
fn jti(&self) -> uuid::Uuid;
}
@@ -188,7 +190,7 @@ impl Extractor {
) -> Result<(), Error> {
let Some(authorisation_header) = req
.headers()
- .get("Authorization")
+ .get(HEADER_NAME)
else {
return Ok(())
};
diff --git a/crates/oswilno-contract/src/accounts.rs b/crates/oswilno-contract/src/accounts.rs
index 2aad3bd..1eefbb8 100644
--- a/crates/oswilno-contract/src/accounts.rs
+++ b/crates/oswilno-contract/src/accounts.rs
@@ -1,4 +1,4 @@
-//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
+//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2
use super::sea_orm_active_enums::Userrole;
use sea_orm::entity::prelude::*;
@@ -66,7 +66,6 @@ impl PrimaryKeyTrait for PrimaryKey {
#[derive(Copy, Clone, Debug, EnumIter)]
pub enum Relation {
- Images,
ParkingSpaces,
}
@@ -91,18 +90,11 @@ impl ColumnTrait for Column {
impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
match self {
- Self::Images => Entity::has_many(super::images::Entity).into(),
Self::ParkingSpaces => Entity::has_many(super::parking_spaces::Entity).into(),
}
}
}
-impl Related
for Entity {
- fn to() -> RelationDef {
- Relation::Images.def()
- }
-}
-
impl Related for Entity {
fn to() -> RelationDef {
Relation::ParkingSpaces.def()
diff --git a/crates/oswilno-contract/src/images.rs b/crates/oswilno-contract/src/images.rs
index d88dcde..de90460 100644
--- a/crates/oswilno-contract/src/images.rs
+++ b/crates/oswilno-contract/src/images.rs
@@ -1,4 +1,4 @@
-//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
+//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2
use super::sea_orm_active_enums::ImageState;
use sea_orm::entity::prelude::*;
@@ -59,9 +59,7 @@ impl PrimaryKeyTrait for PrimaryKey {
}
#[derive(Copy, Clone, Debug, EnumIter)]
-pub enum Relation {
- Accounts,
-}
+pub enum Relation {}
impl ColumnTrait for Column {
type EntityName = Entity;
@@ -80,18 +78,7 @@ impl ColumnTrait for Column {
impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
- match self {
- Self::Accounts => Entity::belongs_to(super::accounts::Entity)
- .from(Column::AccountId)
- .to(super::accounts::Column::Id)
- .into(),
- }
- }
-}
-
-impl Related for Entity {
- fn to() -> RelationDef {
- Relation::Accounts.def()
+ panic!("No RelationDef")
}
}
diff --git a/crates/oswilno-contract/src/lib.rs b/crates/oswilno-contract/src/lib.rs
index a25dda7..8120eb0 100644
--- a/crates/oswilno-contract/src/lib.rs
+++ b/crates/oswilno-contract/src/lib.rs
@@ -1,4 +1,4 @@
-//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
+//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2
pub mod prelude;
diff --git a/crates/oswilno-contract/src/parking_space_rents.rs b/crates/oswilno-contract/src/parking_space_rents.rs
index da12fd1..2320015 100644
--- a/crates/oswilno-contract/src/parking_space_rents.rs
+++ b/crates/oswilno-contract/src/parking_space_rents.rs
@@ -1,4 +1,4 @@
-//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
+//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2
use sea_orm::entity::prelude::*;
diff --git a/crates/oswilno-contract/src/parking_spaces.rs b/crates/oswilno-contract/src/parking_spaces.rs
index 6c3ea58..b8040f1 100644
--- a/crates/oswilno-contract/src/parking_spaces.rs
+++ b/crates/oswilno-contract/src/parking_spaces.rs
@@ -1,4 +1,4 @@
-//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
+//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2
use super::sea_orm_active_enums::ParkingSpaceState;
use sea_orm::entity::prelude::*;
diff --git a/crates/oswilno-contract/src/prelude.rs b/crates/oswilno-contract/src/prelude.rs
index 1caa932..86fe5b1 100644
--- a/crates/oswilno-contract/src/prelude.rs
+++ b/crates/oswilno-contract/src/prelude.rs
@@ -1,4 +1,4 @@
-//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
+//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2
pub use super::accounts::Entity as Accounts;
pub use super::images::Entity as Images;
diff --git a/crates/oswilno-contract/src/sea_orm_active_enums.rs b/crates/oswilno-contract/src/sea_orm_active_enums.rs
index 5eb1249..9235ad7 100644
--- a/crates/oswilno-contract/src/sea_orm_active_enums.rs
+++ b/crates/oswilno-contract/src/sea_orm_active_enums.rs
@@ -1,4 +1,4 @@
-//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
+//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2
use sea_orm::entity::prelude::*;
diff --git a/crates/oswilno-parking-space/src/lib.rs b/crates/oswilno-parking-space/src/lib.rs
index 8381663..fb9c903 100644
--- a/crates/oswilno-parking-space/src/lib.rs
+++ b/crates/oswilno-parking-space/src/lib.rs
@@ -10,7 +10,7 @@ use std::collections::HashMap;
use std::sync::Arc;
use oswilno_session::{Authenticated, Claims};
-use oswilno_view::{is_partial, Layout, LayoutOptions, Main};
+use oswilno_view::{is_partial, Layout, Main, MainOpts};
pub fn mount(config: &mut ServiceConfig) {
config.service(
@@ -45,7 +45,7 @@ async fn all_parking_spaces(
Layout {
main: Main {
body: parking_spaces,
- opts: LayoutOptions::default(),
+ opts: MainOpts::default(),
},
}
.render()
diff --git a/crates/oswilno-session/src/extract_session.rs b/crates/oswilno-session/src/extract_session.rs
deleted file mode 100644
index 8b13789..0000000
--- a/crates/oswilno-session/src/extract_session.rs
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/crates/oswilno-session/src/lib.rs b/crates/oswilno-session/src/lib.rs
index c5705c0..fa781a7 100644
--- a/crates/oswilno-session/src/lib.rs
+++ b/crates/oswilno-session/src/lib.rs
@@ -9,14 +9,13 @@ use askama_actix::Template;
use autometrics::autometrics;
use garde::Validate;
use jsonwebtoken::*;
-use oswilno_view::{Errors, Lang, Layout, LayoutOptions, Main, TranslationStorage};
+use oswilno_view::{Errors, Lang, Layout, Main, MainOpts, TranslationStorage};
use ring::rand::SystemRandom;
use ring::signature::{Ed25519KeyPair, KeyPair};
use sea_orm::DatabaseConnection;
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
-mod extract_session;
mod hashing;
pub use oswilno_view::filters;
@@ -164,7 +163,7 @@ async fn login_view(req: HttpRequest, t: Data) -> HttpRespon
t: t.into_inner(),
errors: Errors::default(),
},
- opts: LayoutOptions {
+ opts: MainOpts {
show: true,
search: None,
session: None,
@@ -180,7 +179,7 @@ async fn login_view(req: HttpRequest, t: Data) -> HttpRespon
t: t.into_inner(),
errors: Errors::default(),
},
- opts: LayoutOptions {
+ opts: MainOpts {
show: true,
..Default::default()
},
@@ -213,7 +212,7 @@ async fn login(
)
.await
{
- Ok(res) => Ok(HttpResponse::Ok().json(res)),
+ Ok(res) => Ok(res),
Err(form) => Ok(HttpResponse::Ok().body(
(SignInPartialTemplate {
form,
@@ -233,7 +232,7 @@ async fn login_inner(
db: Arc,
redis: Arc>,
errors: &mut Errors,
-) -> Result {
+) -> Result {
let iat = OffsetDateTime::now_utc().unix_timestamp() as usize;
let expires_at = OffsetDateTime::now_utc().add(jwt_ttl.0);
let exp = expires_at.unix_timestamp() as usize;
@@ -255,7 +254,8 @@ async fn login_inner(
return Err(payload);
}
};
- if hashing::verify(account.pass_hash.as_str(), payload.password.as_str()).is_err() {
+ if let Err(e) = hashing::verify(account.pass_hash.as_str(), payload.password.as_str()) {
+ tracing::warn!("Hashing verification failed: {e}");
errors.push_global("Bad credentials");
return Err(payload);
}
@@ -284,10 +284,16 @@ async fn login_inner(
return Err(payload);
}
};
- Ok(LoginResponse {
- bearer_token,
- claims: jwt_claims,
- })
+ Ok(HttpResponse::Ok()
+ .append_header((
+ actix_jwt_session::HEADER_NAME,
+ format!("Bearer {bearer_token}").as_str(),
+ ))
+ .body(""))
+ // Ok(LoginResponse {
+ // bearer_token,
+ // claims: jwt_claims,
+ // })
}
#[autometrics]
@@ -319,6 +325,8 @@ struct AccountInfo {
email: String,
#[garde(length(min = 8, max = 50), custom(is_strong_password))]
password: String,
+ #[garde(length(min = 8, max = 50), custom(is_strong_password), custom(check_pass_differ))]
+ password_confirmation: String,
}
#[get("/register")]
@@ -332,7 +340,7 @@ async fn register_view(req: HttpRequest, t: Data) -> HttpRes
lang: Lang::Pl,
errors: oswilno_view::Errors::default(),
},
- opts: LayoutOptions {
+ opts: MainOpts {
show: true,
search: None,
session: None,
@@ -348,7 +356,7 @@ async fn register_view(req: HttpRequest, t: Data) -> HttpRes
lang: Lang::Pl,
errors: oswilno_view::Errors::default(),
},
- opts: LayoutOptions::default(),
+ opts: MainOpts::default(),
},
}
.render()
@@ -369,6 +377,7 @@ struct RegisterPartialTemplate {
#[autometrics]
#[post("/register")]
async fn register(
+ req: HttpRequest,
db: Data,
payload: Form,
t: Data,
@@ -377,7 +386,7 @@ async fn register(
let t = t.into_inner();
let mut errors = oswilno_view::Errors::default();
Ok(
- match register_internal(db.into_inner(), payload.into_inner(), &mut errors).await {
+ match register_internal(req, db.into_inner(), payload.into_inner(), &mut errors).await {
Ok(res) => res,
Err(p) => HttpResponse::BadRequest().body(
RegisterPartialTemplate {
@@ -396,6 +405,7 @@ async fn register(
struct RegisterContext {
login_taken: bool,
email_taken: bool,
+ pass_differ: bool,
}
fn is_email_free(_value: &str, context: &RegisterContext) -> garde::Result {
@@ -412,6 +422,15 @@ fn is_login_free(_value: &str, context: &RegisterContext) -> garde::Result {
}
static WEAK_PASS: &str = "is not strong enough";
+fn check_pass_differ(_v: &str, ctx: &RegisterContext) -> garde::Result {
+ if ctx.pass_differ {
+ Err(garde::Error::new(DIFFER_PASS))
+ } else {
+ Ok(())
+ }
+}
+
+static DIFFER_PASS: &str = "passwords differ";
fn is_strong_password(value: &str, _context: &RegisterContext) -> garde::Result {
if !(8..50).contains(&value.len()) {
return Err(garde::Error::new(WEAK_PASS));
@@ -434,6 +453,7 @@ fn is_strong_password(value: &str, _context: &RegisterContext) -> garde::Result
}
async fn register_internal(
+ _req: HttpRequest,
db: Arc,
p: AccountInfo,
errors: &mut oswilno_view::Errors,
@@ -467,6 +487,7 @@ async fn register_internal(
if let Err(e) = p.validate(&RegisterContext {
login_taken,
email_taken,
+ pass_differ: p.password != p.password_confirmation,
}) {
errors.consume_garde(e);
return Err(p);
@@ -499,7 +520,8 @@ async fn register_internal(
Ok(HttpResponse::SeeOther()
.append_header(("Location", "/login"))
- .json(EmptyResponse {}))
+ .append_header(("Accept", "text/html-partial"))
+ .body(""))
}
pub struct JwtSigningKeys {
diff --git a/crates/oswilno-session/templates/register/partial.html b/crates/oswilno-session/templates/register/partial.html
index 97355bb..47acfae 100644
--- a/crates/oswilno-session/templates/register/partial.html
+++ b/crates/oswilno-session/templates/register/partial.html
@@ -45,6 +45,19 @@
{{error|t(lang,t)}}
{% endfor %}