diff --git a/assets/build.js b/assets/build.js index c8a2e12..77ec6d6 100644 --- a/assets/build.js +++ b/assets/build.js @@ -1,7 +1,7 @@ -(()=>{var c=Object.create;var i=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var h=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty;var u=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,s)=>(typeof require<"u"?require:e)[s]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var m=(t,e,s,l)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of a(e))!p.call(t,o)&&o!==s&&i(t,o,{get:()=>e[o],enumerable:!(l=d(e,o))||l.enumerable});return t};var y=(t,e,s)=>(s=t!=null?c(h(t)):{},m(e||!t||!t.__esModule?i(s,"default",{value:t,enumerable:!0}):s,t));customElements.define("oswilno-price",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){let t=this.shadowRoot,e=parseInt(this.getAttribute("price"));isNaN(e)&&(e=0);let s=parseInt(this.getAttribute("multiplier")),l=e,o=0;isNaN(s)||(l=Math.floor(e/s),o=e%s);let r=this.getAttribute("currency")||"PLN";t.innerHTML=`
${l}.${o>=10?o:o+"0"} ${r}
`}});var n=t=>{let e="";for(let l=0;l{var a=Object.create;var n=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var u=Object.getPrototypeOf,m=Object.prototype.hasOwnProperty;var p=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,s)=>(typeof require<"u"?require:t)[s]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var f=(e,t,s,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of h(t))!m.call(e,o)&&o!==s&&n(e,o,{get:()=>t[o],enumerable:!(r=d(t,o))||r.enumerable});return e};var g=(e,t,s)=>(s=e!=null?a(u(e)):{},f(t||!e||!e.__esModule?n(s,"default",{value:e,enumerable:!0}):s,e));customElements.define("oswilno-price",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){let e=this.shadowRoot,t=parseInt(this.getAttribute("price"));isNaN(t)&&(t=0);let s=parseInt(this.getAttribute("multiplier")),r=t,o=0;isNaN(s)||(r=Math.floor(t/s),o=t%s);let l=this.getAttribute("currency")||"PLN";e.innerHTML=`
${r}.${o>=10?o:o+"0"} ${l}
`}});var i=e=>{let t="";for(let r=0;r:host{display:block;}
- `,n(t)}});import("https://unpkg.com/htmx.org@1.9.4/dist/htmx.min.js");document.body.addEventListener("htmx:beforeOnLoad",function(t){let e=t.detail.xhr.status;(e===422||e===400)&&(t.detail.shouldSwap=!0,t.detail.isError=!1)});})(); + `,i(e)}});import("https://unpkg.com/htmx.org@1.9.4/dist/htmx.min.js");var c=document.body;c.addEventListener("htmx:beforeOnLoad",function(e){console.log(e);let t=e.detail,s=t.xhr,r=s.status,o=t.successful;if(console.log(o,s.getResponseHeader("Authorization")),r===200){let l=s.getResponseHeader("Authorization");l&&localStorage.setItem("jwt",l.replace(/^Bearer /i,""))}else r===401&&localStorage.removeItem("jwt");(r===422||r===400)&&(t.shouldSwap=!0,t.isError=!1)});c.addEventListener("htmx:configRequest",function(e){localStorage.getItem("jwt")&&(e.detail.headers.Authorization="Bearer "+(localStorage.getItem("jwt")||""))});})(); //# sourceMappingURL=build.js.map diff --git a/assets/build.js.map b/assets/build.js.map index f955eb8..70c270f 100644 --- a/assets/build.js.map +++ b/assets/build.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../crates/web-assets/assets/elements/oswilno-price.js", "../crates/web-assets/assets/css.js", "../crates/web-assets/assets/elements/oswilno-error.js", "../crates/web-assets/assets/app.js"], - "sourcesContent": ["customElements.define('oswilno-price', class extends HTMLElement {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.attachShadow({ mode: 'open' });\n\t}\n\tconnectedCallback() {\n\t\tlet shadow = this.shadowRoot;\n\t\tlet price = parseInt(this.getAttribute('price'));\n\t\tif (isNaN(price)) price = 0;\n\t\tconst multiplier = parseInt(this.getAttribute('multiplier'));\n\t\tlet major = price;\n\t\tlet minor = 0;\n\t\tif (!isNaN(multiplier)) {\n\t\t\tmajor = Math.floor(price / multiplier);\n\t\t\tminor = price % multiplier;\n\t\t}\n\t\tconst currency = this.getAttribute('currency') || 'PLN';\n\t\tshadow.innerHTML = `
${major}.${minor >= 10 ? minor : minor + '0'} ${ currency }
`;\n\t}\n});\n", "export const copyCss = (shadow) => {\n\tlet css = '';\n\tfor (let i = 0; i < document.styleSheets.length; i++) {\n\t\tconst styleSheet = document.styleSheets[i];\n\t\tfor (let j = 0; j < styleSheet.rules.length; j++) {\n\t\t\tcss += styleSheet.rules[j].cssText;\t\n\t\t}\n\t}\n\tconst sheet = new CSSStyleSheet();\n\tsheet.replaceSync(css);\n\tshadow.adoptedStyleSheets = [sheet];\n};\n", "import { copyCss } from \"../css.js\";\n\ncustomElements.define('oswilno-error', class extends HTMLElement {\n\tconstructor() {\n\t\tsuper();\n\t\tconst shadow = this.attachShadow({ mode: 'open' });\n\t\tshadow.innerHTML = `\n\t\t\t\n\t\t\t
\n\t\t\t\t\n\t\t\t
\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\ndocument.body.addEventListener('htmx:beforeOnLoad', function (evt) {\n\tconst status = evt.detail.xhr.status;\n\tif (status === 422 || status === 400) {\n\t\tevt.detail.shouldSwap = true;\n\t\tevt.detail.isError = false;\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,SAAS,KAAK,iBAAiB,oBAAqB,SAAUE,EAAK,CAClE,IAAMC,EAASD,EAAI,OAAO,IAAI,QAC1BC,IAAW,KAAOA,IAAW,OAChCD,EAAI,OAAO,WAAa,GACxBA,EAAI,OAAO,QAAU,GAEvB,CAAC", - "names": ["shadow", "price", "multiplier", "major", "minor", "currency", "copyCss", "shadow", "css", "i", "styleSheet", "j", "sheet", "shadow", "copyCss", "evt", "status"] + "sourcesContent": ["customElements.define('oswilno-price', class extends HTMLElement {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.attachShadow({ mode: 'open' });\n\t}\n\tconnectedCallback() {\n\t\tlet shadow = this.shadowRoot;\n\t\tlet price = parseInt(this.getAttribute('price'));\n\t\tif (isNaN(price)) price = 0;\n\t\tconst multiplier = parseInt(this.getAttribute('multiplier'));\n\t\tlet major = price;\n\t\tlet minor = 0;\n\t\tif (!isNaN(multiplier)) {\n\t\t\tmajor = Math.floor(price / multiplier);\n\t\t\tminor = price % multiplier;\n\t\t}\n\t\tconst currency = this.getAttribute('currency') || 'PLN';\n\t\tshadow.innerHTML = `
${major}.${minor >= 10 ? minor : minor + '0'} ${ currency }
`;\n\t}\n});\n", "export const copyCss = (shadow) => {\n\tlet css = '';\n\tfor (let i = 0; i < document.styleSheets.length; i++) {\n\t\tconst styleSheet = document.styleSheets[i];\n\t\tfor (let j = 0; j < styleSheet.rules.length; j++) {\n\t\t\tcss += styleSheet.rules[j].cssText;\t\n\t\t}\n\t}\n\tconst sheet = new CSSStyleSheet();\n\tsheet.replaceSync(css);\n\tshadow.adoptedStyleSheets = [sheet];\n};\n", "import { copyCss } from \"../css.js\";\n\ncustomElements.define('oswilno-error', class extends HTMLElement {\n\tconstructor() {\n\t\tsuper();\n\t\tconst shadow = this.attachShadow({ mode: 'open' });\n\t\tshadow.innerHTML = `\n\t\t\t\n\t\t\t
\n\t\t\t\t\n\t\t\t
\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 %}
+
+ + + {% for error in errors.field("password_confirmation") %} + {{error|t(lang,t)}} + {% endfor %} +
, } -#[derive(Debug, Default)] -pub struct LayoutOptions { +#[derive(Debug)] +pub struct MainOpts { pub show: bool, pub search: Option, pub session: Option, } +impl Default for MainOpts { + fn default() -> Self { + Self { + show: true, + search: None, + session: None, + } + } +} + #[derive(Debug, askama_actix::Template)] #[template(path = "../templates/main.html")] pub struct Main { pub body: BodyTemplate, - pub opts: LayoutOptions, + pub opts: MainOpts, } #[derive(Debug, askama_actix::Template)] diff --git a/crates/oswilno-view/templates/nav/links-large.html b/crates/oswilno-view/templates/nav/links-large.html index 6ad2836..6623417 100644 --- a/crates/oswilno-view/templates/nav/links-large.html +++ b/crates/oswilno-view/templates/nav/links-large.html @@ -1,7 +1,14 @@