Compare commits
2 Commits
335a84838f
...
6692df9aeb
Author | SHA1 | Date | |
---|---|---|---|
6692df9aeb | |||
26dea34054 |
116
Cargo.lock
generated
116
Cargo.lock
generated
@ -26,9 +26,9 @@ dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"parking_lot 0.12.1",
|
||||
"pin-project-lite 0.2.9",
|
||||
"pin-project-lite 0.2.12",
|
||||
"smallvec",
|
||||
"tokio 1.29.1",
|
||||
"tokio 1.30.0",
|
||||
"tokio-util 0.7.3",
|
||||
]
|
||||
|
||||
@ -81,8 +81,8 @@ dependencies = [
|
||||
"futures-sink",
|
||||
"log",
|
||||
"memchr",
|
||||
"pin-project-lite 0.2.9",
|
||||
"tokio 1.29.1",
|
||||
"pin-project-lite 0.2.12",
|
||||
"tokio 1.30.0",
|
||||
"tokio-util 0.7.3",
|
||||
]
|
||||
|
||||
@ -106,7 +106,7 @@ dependencies = [
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"percent-encoding",
|
||||
"pin-project-lite 0.2.9",
|
||||
"pin-project-lite 0.2.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -149,11 +149,11 @@ dependencies = [
|
||||
"local-channel",
|
||||
"mime",
|
||||
"percent-encoding",
|
||||
"pin-project-lite 0.2.9",
|
||||
"pin-project-lite 0.2.12",
|
||||
"rand 0.8.5",
|
||||
"sha1 0.10.1",
|
||||
"smallvec",
|
||||
"tokio 1.29.1",
|
||||
"tokio 1.30.0",
|
||||
"tokio-util 0.7.3",
|
||||
"tracing",
|
||||
"zstd",
|
||||
@ -172,10 +172,29 @@ dependencies = [
|
||||
"jsonwebtoken",
|
||||
"serde",
|
||||
"time 0.3.25",
|
||||
"tokio 1.29.1",
|
||||
"tokio 1.30.0",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-jwt-session"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"async-trait",
|
||||
"bincode",
|
||||
"futures",
|
||||
"futures-lite",
|
||||
"futures-util",
|
||||
"jsonwebtoken",
|
||||
"redis",
|
||||
"redis-async-pool",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tokio 1.30.0",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-macros"
|
||||
version = "0.2.3"
|
||||
@ -208,7 +227,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_plain",
|
||||
"tempfile",
|
||||
"tokio 1.29.1",
|
||||
"tokio 1.30.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -246,7 +265,7 @@ checksum = "15265b6b8e2347670eb363c47fc8c75208b4a4994b27192f345fcbe707804f3e"
|
||||
dependencies = [
|
||||
"actix-macros",
|
||||
"futures-core",
|
||||
"tokio 1.29.1",
|
||||
"tokio 1.30.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -262,8 +281,8 @@ dependencies = [
|
||||
"futures-util",
|
||||
"mio 0.8.8",
|
||||
"num_cpus",
|
||||
"socket2",
|
||||
"tokio 1.29.1",
|
||||
"socket2 0.4.9",
|
||||
"tokio 1.30.0",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@ -275,7 +294,7 @@ checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"paste",
|
||||
"pin-project-lite 0.2.9",
|
||||
"pin-project-lite 0.2.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -320,7 +339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e491cbaac2e7fc788dfff99ff48ef317e23b3cf63dbaf7aaab6418f40f92aa94"
|
||||
dependencies = [
|
||||
"local-waker",
|
||||
"pin-project-lite 0.2.9",
|
||||
"pin-project-lite 0.2.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -353,13 +372,13 @@ dependencies = [
|
||||
"log",
|
||||
"mime",
|
||||
"once_cell",
|
||||
"pin-project-lite 0.2.9",
|
||||
"pin-project-lite 0.2.12",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"smallvec",
|
||||
"socket2",
|
||||
"socket2 0.4.9",
|
||||
"time 0.3.25",
|
||||
"url",
|
||||
]
|
||||
@ -640,7 +659,7 @@ dependencies = [
|
||||
"blocking",
|
||||
"futures-lite",
|
||||
"once_cell",
|
||||
"tokio 1.29.1",
|
||||
"tokio 1.30.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -658,7 +677,7 @@ dependencies = [
|
||||
"parking",
|
||||
"polling",
|
||||
"slab",
|
||||
"socket2",
|
||||
"socket2 0.4.9",
|
||||
"waker-fn",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
@ -693,7 +712,7 @@ dependencies = [
|
||||
"log",
|
||||
"memchr",
|
||||
"once_cell",
|
||||
"pin-project-lite 0.2.9",
|
||||
"pin-project-lite 0.2.12",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
"wasm-bindgen-futures",
|
||||
@ -707,7 +726,7 @@ checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
|
||||
dependencies = [
|
||||
"async-stream-impl",
|
||||
"futures-core",
|
||||
"pin-project-lite 0.2.9",
|
||||
"pin-project-lite 0.2.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1186,7 +1205,7 @@ dependencies = [
|
||||
"bytes 1.1.0",
|
||||
"futures-core",
|
||||
"memchr",
|
||||
"pin-project-lite 0.2.9",
|
||||
"pin-project-lite 0.2.12",
|
||||
"tokio 0.2.25",
|
||||
]
|
||||
|
||||
@ -1666,7 +1685,7 @@ dependencies = [
|
||||
"futures-io",
|
||||
"memchr",
|
||||
"parking",
|
||||
"pin-project-lite 0.2.9",
|
||||
"pin-project-lite 0.2.12",
|
||||
"waker-fn",
|
||||
]
|
||||
|
||||
@ -1706,7 +1725,7 @@ dependencies = [
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project-lite 0.2.9",
|
||||
"pin-project-lite 0.2.12",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
]
|
||||
@ -1837,7 +1856,7 @@ dependencies = [
|
||||
"http",
|
||||
"indexmap 1.9.1",
|
||||
"slab",
|
||||
"tokio 1.29.1",
|
||||
"tokio 1.30.0",
|
||||
"tokio-util 0.7.3",
|
||||
"tracing",
|
||||
]
|
||||
@ -2281,7 +2300,7 @@ dependencies = [
|
||||
"oswilno-contract",
|
||||
"sea-orm",
|
||||
"sea-orm-migration",
|
||||
"tokio 1.29.1",
|
||||
"tokio 1.30.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2515,7 +2534,7 @@ dependencies = [
|
||||
"sea-orm",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio 1.29.1",
|
||||
"tokio 1.30.0",
|
||||
"toml 0.7.6",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
@ -2577,7 +2596,7 @@ dependencies = [
|
||||
"sea-orm",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio 1.29.1",
|
||||
"tokio 1.30.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2604,7 +2623,7 @@ dependencies = [
|
||||
"sea-orm",
|
||||
"serde",
|
||||
"time 0.3.25",
|
||||
"tokio 1.29.1",
|
||||
"tokio 1.30.0",
|
||||
"tracing",
|
||||
"uuid",
|
||||
]
|
||||
@ -2861,9 +2880,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.9"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||
checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
@ -3713,6 +3732,16 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spez"
|
||||
version = "0.1.2"
|
||||
@ -3835,7 +3864,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"tokio 1.29.1",
|
||||
"tokio 1.30.0",
|
||||
"tokio-rustls",
|
||||
]
|
||||
|
||||
@ -4045,25 +4074,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46409491c9375a693ce7032101970a54f8a2010efb77e13f70788f0d84489e39"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"pin-project-lite 0.2.9",
|
||||
"pin-project-lite 0.2.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.29.1"
|
||||
version = "1.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
|
||||
checksum = "2d3ce25f50619af8b0aec2eb23deebe84249e19e2ddd393a6e16e3300a6dadfd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"backtrace",
|
||||
"bytes 1.1.0",
|
||||
"libc",
|
||||
"mio 0.8.8",
|
||||
"num_cpus",
|
||||
"parking_lot 0.12.1",
|
||||
"pin-project-lite 0.2.9",
|
||||
"pin-project-lite 0.2.12",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"socket2 0.5.3",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
@ -4086,7 +4114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
|
||||
dependencies = [
|
||||
"rustls",
|
||||
"tokio 1.29.1",
|
||||
"tokio 1.30.0",
|
||||
"webpki",
|
||||
]
|
||||
|
||||
@ -4097,8 +4125,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"pin-project-lite 0.2.9",
|
||||
"tokio 1.29.1",
|
||||
"pin-project-lite 0.2.12",
|
||||
"tokio 1.30.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4124,8 +4152,8 @@ dependencies = [
|
||||
"bytes 1.1.0",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"pin-project-lite 0.2.9",
|
||||
"tokio 1.29.1",
|
||||
"pin-project-lite 0.2.12",
|
||||
"tokio 1.30.0",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@ -4180,7 +4208,7 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"log",
|
||||
"pin-project-lite 0.2.9",
|
||||
"pin-project-lite 0.2.12",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
]
|
||||
@ -4542,7 +4570,7 @@ dependencies = [
|
||||
"askama",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio 1.29.1",
|
||||
"tokio 1.30.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -6,4 +6,5 @@ members = [
|
||||
'./crates/oswilno-parking-space',
|
||||
'./crates/migration',
|
||||
'./crates/oswilno-actix-admin',
|
||||
'./crates/actix-jwt-session',
|
||||
]
|
||||
|
23
crates/actix-jwt-session/Cargo.toml
Normal file
23
crates/actix-jwt-session/Cargo.toml
Normal file
@ -0,0 +1,23 @@
|
||||
[package]
|
||||
name = "actix-jwt-session"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
default = ['use-redis']
|
||||
use-redis = ["redis", "redis-async-pool"]
|
||||
|
||||
[dependencies]
|
||||
actix-web = "4"
|
||||
async-trait = "0.1.72"
|
||||
bincode = "1.3.3"
|
||||
futures = "0.3.28"
|
||||
futures-lite = "1.13.0"
|
||||
futures-util = { version = "0.3.28", features = ['async-await'] }
|
||||
jsonwebtoken = "8.3.0"
|
||||
redis = { version = "0.17", optional = true }
|
||||
redis-async-pool = { version = "0.2.4", optional = true }
|
||||
serde = { version = "1.0.183", features = ["derive"] }
|
||||
thiserror = "1.0.44"
|
||||
tokio = { version = "1.30.0", features = ["full"] }
|
||||
uuid = { version = "1.4.1", features = ["v4"] }
|
85
crates/actix-jwt-session/src/lib.rs
Normal file
85
crates/actix-jwt-session/src/lib.rs
Normal file
@ -0,0 +1,85 @@
|
||||
use actix_web::dev::ServiceRequest;
|
||||
use actix_web::HttpMessage;
|
||||
use jsonwebtoken::{decode, DecodingKey, Validation};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait Claims: PartialEq + DeserializeOwned + Serialize + Clone + Send + Sync + 'static {
|
||||
fn jti(&self) -> uuid::Uuid;
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, PartialEq)]
|
||||
pub enum Error {
|
||||
#[error("Failed to obtain redis connection")]
|
||||
RedisConn,
|
||||
#[error("Record not found")]
|
||||
NotFound,
|
||||
#[error("Record malformed")]
|
||||
RecordMalformed,
|
||||
#[error("Invalid session")]
|
||||
InvalidSession,
|
||||
#[error("No http authentication header")]
|
||||
NoAuthHeader,
|
||||
}
|
||||
|
||||
impl actix_web::ResponseError for Error {
|
||||
fn status_code(&self) -> actix_web::http::StatusCode {
|
||||
match self {
|
||||
Self::RedisConn => actix_web::http::StatusCode::INTERNAL_SERVER_ERROR,
|
||||
_ => actix_web::http::StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Authenticated<T>(Arc<T>);
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
pub trait TokenStorage {
|
||||
type ClaimsType: Claims;
|
||||
|
||||
async fn get_from_jti(self: Arc<Self>, jti: uuid::Uuid) -> Result<Self::ClaimsType, Error>;
|
||||
}
|
||||
|
||||
struct Extractor;
|
||||
|
||||
impl Extractor {
|
||||
async fn extract_bearer_jwt<ClaimsType: Claims>(
|
||||
req: &ServiceRequest,
|
||||
jwt_decoding_key: Arc<DecodingKey>,
|
||||
jwt_validator: Arc<Validation>,
|
||||
storage: Arc<dyn TokenStorage<ClaimsType = ClaimsType>>,
|
||||
) -> Result<(), Error> {
|
||||
|
||||
let authorisation_header = req
|
||||
.headers()
|
||||
.get("Authorization")
|
||||
.ok_or(Error::NoAuthHeader)?;
|
||||
let as_str = authorisation_header
|
||||
.to_str()
|
||||
.map_err(|_| Error::NoAuthHeader)?;
|
||||
|
||||
let decoded_claims = decode::<ClaimsType>(as_str, &*jwt_decoding_key, &*jwt_validator)
|
||||
.map_err(|_e| {
|
||||
// let error_message = e.to_string();
|
||||
Error::InvalidSession
|
||||
})?;
|
||||
|
||||
let stored = storage
|
||||
.get_from_jti(decoded_claims.claims.jti())
|
||||
.await
|
||||
.map_err(|_| Error::InvalidSession)?;
|
||||
|
||||
if stored != decoded_claims.claims {
|
||||
return Err(Error::InvalidSession);
|
||||
}
|
||||
|
||||
req.extensions_mut()
|
||||
.insert(Authenticated(Arc::new(decoded_claims.claims)));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "redis")]
|
||||
mod redis_adapter;
|
||||
#[cfg(feature = "redis")]
|
||||
pub use redis_adapter::*;
|
100
crates/actix-jwt-session/src/redis_adapter.rs
Normal file
100
crates/actix-jwt-session/src/redis_adapter.rs
Normal file
@ -0,0 +1,100 @@
|
||||
use super::*;
|
||||
use actix_web::dev::{forward_ready, Service, ServiceRequest, ServiceResponse};
|
||||
use futures_util::future::LocalBoxFuture;
|
||||
use jsonwebtoken::{DecodingKey, Validation};
|
||||
use redis::AsyncCommands;
|
||||
use std::marker::PhantomData;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RedisStorage<ClaimsType: Claims> {
|
||||
pool: redis_async_pool::RedisPool,
|
||||
_claims_type_marker: PhantomData<ClaimsType>,
|
||||
}
|
||||
|
||||
impl<ClaimsType: Claims> RedisStorage<ClaimsType> {
|
||||
pub fn new(pool: redis_async_pool::RedisPool) -> Self {
|
||||
Self {
|
||||
pool,
|
||||
_claims_type_marker: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl<ClaimsType> TokenStorage for RedisStorage<ClaimsType>
|
||||
where
|
||||
ClaimsType: Claims,
|
||||
{
|
||||
type ClaimsType = ClaimsType;
|
||||
|
||||
async fn get_from_jti(self: Arc<Self>, jti: uuid::Uuid) -> Result<ClaimsType, Error> {
|
||||
let pool = self.pool.clone();
|
||||
let mut conn = pool.get().await.map_err(|_| Error::RedisConn)?;
|
||||
let val = conn
|
||||
.get::<_, Vec<u8>>(jti.as_bytes())
|
||||
.await
|
||||
.map_err(|_| Error::NotFound)?;
|
||||
bincode::deserialize(&val).map_err(|_| Error::RecordMalformed)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RedisMiddleware<S, ClaimsType>
|
||||
where
|
||||
ClaimsType: Claims,
|
||||
{
|
||||
_claims_type_marker: std::marker::PhantomData<ClaimsType>,
|
||||
service: Rc<S>,
|
||||
jwt_decoding_key: Arc<DecodingKey>,
|
||||
jwt_validator: Arc<Validation>,
|
||||
storage: Arc<RedisStorage<ClaimsType>>,
|
||||
}
|
||||
|
||||
impl<S, B, ClaimsType> Service<ServiceRequest> for RedisMiddleware<S, ClaimsType>
|
||||
where
|
||||
ClaimsType: Claims,
|
||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = actix_web::Error> + 'static,
|
||||
{
|
||||
type Response = ServiceResponse<B>;
|
||||
type Error = actix_web::Error;
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||
|
||||
forward_ready!(service);
|
||||
|
||||
fn call(&self, req: ServiceRequest) -> Self::Future {
|
||||
use futures_lite::FutureExt;
|
||||
|
||||
let svc = self.service.clone();
|
||||
let jwt_decoding_key = self.jwt_decoding_key.clone();
|
||||
let validation = self.jwt_validator.clone();
|
||||
let storage = self.storage.clone();
|
||||
|
||||
async move {
|
||||
Extractor::extract_bearer_jwt(&req, jwt_decoding_key, validation, storage).await?;
|
||||
let res = svc.call(req).await?;
|
||||
Ok(res)
|
||||
}
|
||||
.boxed_local()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
struct Out {
|
||||
id: uuid::Uuid,
|
||||
}
|
||||
impl Claims for Out {
|
||||
fn jti(&self) -> uuid::Uuid {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn extract() {
|
||||
}
|
||||
}
|
@ -11,9 +11,7 @@ impl MigrationTrait for Migration {
|
||||
m.alter_table(
|
||||
Table::alter()
|
||||
.table(ParkingSpace::ParkingSpaces)
|
||||
.add_column(
|
||||
ColumnDef::new(ParkingSpace::Spot)
|
||||
.integer())
|
||||
.add_column(ColumnDef::new(ParkingSpace::Spot).integer())
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
1
crates/oswilno-session/src/extract_session.rs
Normal file
1
crates/oswilno-session/src/extract_session.rs
Normal file
@ -0,0 +1 @@
|
||||
|
@ -4,7 +4,7 @@ use std::sync::Arc;
|
||||
use actix_jwt_authc::*;
|
||||
use actix_web::web::{Data, Form, ServiceConfig};
|
||||
use actix_web::{get, post, HttpResponse};
|
||||
use askama_actix::{Template, TemplateToResponse as _};
|
||||
use askama_actix::Template;
|
||||
use autometrics::autometrics;
|
||||
use futures::channel::{mpsc, mpsc::Sender};
|
||||
use futures::stream::Stream;
|
||||
@ -20,6 +20,7 @@ use time::ext::*;
|
||||
use time::OffsetDateTime;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
mod extract_session;
|
||||
mod hashing;
|
||||
|
||||
pub use oswilno_view::filters;
|
||||
@ -30,11 +31,13 @@ pub type UserSession = Authenticated<Claims>;
|
||||
pub struct JWTTtl(time::Duration);
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
enum Audience {
|
||||
Web,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub struct Claims {
|
||||
#[serde(rename = "exp")]
|
||||
expires_at: usize,
|
||||
@ -196,7 +199,7 @@ async fn login(
|
||||
let mut errors = Errors::default();
|
||||
match login_inner(
|
||||
jwt_encoding_key,
|
||||
jwt_ttl,
|
||||
jwt_ttl.into_inner(),
|
||||
payload.into_inner(),
|
||||
db.into_inner(),
|
||||
redis.into_inner(),
|
||||
@ -206,7 +209,12 @@ async fn login(
|
||||
{
|
||||
Ok(res) => Ok(HttpResponse::Ok().json(res)),
|
||||
Err(form) => Ok(HttpResponse::Ok().body(
|
||||
(SignInPartialTemplate { form, lang, t, errors })
|
||||
(SignInPartialTemplate {
|
||||
form,
|
||||
lang,
|
||||
t,
|
||||
errors,
|
||||
})
|
||||
.render()
|
||||
.unwrap(),
|
||||
)),
|
||||
@ -215,7 +223,7 @@ async fn login(
|
||||
|
||||
async fn login_inner(
|
||||
jwt_encoding_key: Data<EncodingKey>,
|
||||
jwt_ttl: Data<JWTTtl>,
|
||||
jwt_ttl: Arc<JWTTtl>,
|
||||
payload: SignInPayload,
|
||||
db: Arc<DatabaseConnection>,
|
||||
redis: Arc<redis_async_pool::RedisPool>,
|
||||
@ -274,8 +282,13 @@ async fn login_inner(
|
||||
errors.push_global("Failed to sign in. Please try later");
|
||||
return Err(payload);
|
||||
};
|
||||
|
||||
if let Err(e) = conn
|
||||
.set::<'_, _, _, String>(jwt_claims.jwt_id.as_bytes(), bin_value)
|
||||
.set_ex::<'_, _, _, String>(
|
||||
jwt_claims.jwt_id.as_bytes(),
|
||||
bin_value,
|
||||
jwt_ttl.0.as_seconds_f32() as usize,
|
||||
)
|
||||
.await
|
||||
{
|
||||
tracing::warn!("Failed to set sign-in claims in redis: {e}");
|
||||
@ -298,10 +311,16 @@ async fn session_info(authenticated: UserSession) -> Result<HttpResponse, Error>
|
||||
#[autometrics]
|
||||
#[get("/logout")]
|
||||
async fn logout(
|
||||
invalidated_jwts: Data<InvalidatedJWTStore>,
|
||||
authenticated: Authenticated<Claims>,
|
||||
redis: Data<redis_async_pool::RedisPool>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
invalidated_jwts.add_to_invalidated(authenticated).await;
|
||||
{
|
||||
use redis::AsyncCommands;
|
||||
let jwt_id = authenticated.claims.jwt_id;
|
||||
if let Ok(mut conn) = redis.get().await {
|
||||
if conn.del::<_, String>(jwt_id.as_bytes()).await.is_err() {}
|
||||
}
|
||||
}
|
||||
Ok(HttpResponse::Ok().json(EmptyResponse {}))
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user