Finish sign out
This commit is contained in:
parent
93155b6cbf
commit
25390c0c56
36
Cargo.lock
generated
36
Cargo.lock
generated
@ -86,9 +86,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "actix-jwt-session"
|
name = "actix-jwt-session"
|
||||||
version = "1.0.4"
|
version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6317d3303618eea36d68898bf720ce94d8b5bb2bf1a23c8ffdf714024f0a49a6"
|
checksum = "5417207a8cf4ac0c420464ea0b457143a4a172a0ee39eb5adf6cb70fa21c3065"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"argon2",
|
"argon2",
|
||||||
@ -2047,9 +2047,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libnghttp2-sys"
|
name = "libnghttp2-sys"
|
||||||
version = "0.1.8+1.55.1"
|
version = "0.1.9+1.58.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4fae956c192dadcdb5dace96db71fa0b827333cce7c7b38dc71446f024d8a340"
|
checksum = "b57e858af2798e167e709b9d969325b6d8e9d50232fcbc494d7d54f976854a64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@ -2079,9 +2079,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libz-sys"
|
name = "libz-sys"
|
||||||
version = "1.1.14"
|
version = "1.1.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "295c17e837573c8c821dbaeb3cceb3d745ad082f7572191409e69cbc1b3fd050"
|
checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@ -2714,18 +2714,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project"
|
name = "pin-project"
|
||||||
version = "1.1.3"
|
version = "1.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
|
checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pin-project-internal",
|
"pin-project-internal",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-internal"
|
name = "pin-project-internal"
|
||||||
version = "1.1.3"
|
version = "1.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
|
checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -3680,9 +3680,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.195"
|
version = "1.0.196"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
|
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
@ -3741,9 +3741,9 @@ checksum = "794e44574226fc701e3be5c651feb7939038fc67fb73f6f4dd5c4ba90fd3be70"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.195"
|
version = "1.0.196"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
|
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -3752,9 +3752,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.111"
|
version = "1.0.112"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
|
checksum = "4d1bd37ce2324cf3bf85e5a25f96eb4baf0d5aa6eba43e7ae8958870c4ec48ed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
@ -5144,9 +5144,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.5.34"
|
version = "0.5.35"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16"
|
checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
@ -4,12 +4,11 @@ use actix_jwt_session::{
|
|||||||
Duration, Hashing, JwtTtl, RefreshTtl, SessionStorage, JWT_HEADER_NAME, REFRESH_HEADER_NAME,
|
Duration, Hashing, JwtTtl, RefreshTtl, SessionStorage, JWT_HEADER_NAME, REFRESH_HEADER_NAME,
|
||||||
};
|
};
|
||||||
use actix_web::web::{Data, ServiceConfig};
|
use actix_web::web::{Data, ServiceConfig};
|
||||||
use actix_web::{delete, get, HttpRequest, HttpResponse};
|
use actix_web::{HttpRequest, HttpResponse};
|
||||||
use entities::prelude::Users;
|
use entities::prelude::Users;
|
||||||
use entities::users::Model as User;
|
use entities::users::Model as User;
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
use sea_orm::prelude::*;
|
use sea_orm::prelude::*;
|
||||||
use sea_orm::DatabaseConnection;
|
|
||||||
use sea_orm::*;
|
use sea_orm::*;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@ -28,9 +27,9 @@ pub struct AuthResponseBody {
|
|||||||
pub fn configure(http_client: reqwest::Client, config: &mut ServiceConfig) {
|
pub fn configure(http_client: reqwest::Client, config: &mut ServiceConfig) {
|
||||||
config
|
config
|
||||||
.service(email_check::email_check)
|
.service(email_check::email_check)
|
||||||
.service(oauth)
|
|
||||||
.service(sign_in::sign_in)
|
.service(sign_in::sign_in)
|
||||||
.service(sign_up::sign_up);
|
.service(sign_up::sign_up)
|
||||||
|
.service(sign_out::sign_out);
|
||||||
social_auth::configure(http_client, config);
|
social_auth::configure(http_client, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,52 @@
|
|||||||
use actix_jwt_session::{Authenticated, SessionStorage};
|
use actix_jwt_session::{Authenticated, RefreshToken, SessionStorage};
|
||||||
|
use actix_web::HttpRequest;
|
||||||
use actix_web::{post, web::Data, HttpResponse};
|
use actix_web::{post, web::Data, HttpResponse};
|
||||||
use sea_orm::DatabaseConnection;
|
use entities::prelude::Users;
|
||||||
|
use entities::users::{ActiveModel as UserModel, Column};
|
||||||
|
use sea_orm::prelude::*;
|
||||||
|
use sea_orm::Set;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
use crate::models::{Error, JsonError};
|
||||||
use crate::session::AppClaims;
|
use crate::session::AppClaims;
|
||||||
|
use crate::utils::extract_req_ip;
|
||||||
|
|
||||||
#[post("/sign-out")]
|
#[post("/sign-out")]
|
||||||
pub async fn sign_out(
|
pub async fn sign_out(
|
||||||
_db: Data<DatabaseConnection>,
|
req: HttpRequest,
|
||||||
claims: Authenticated<AppClaims>,
|
db: Data<DatabaseConnection>,
|
||||||
|
claims: Authenticated<RefreshToken>,
|
||||||
session: Data<SessionStorage>,
|
session: Data<SessionStorage>,
|
||||||
) -> HttpResponse {
|
) -> Result<HttpResponse, JsonError> {
|
||||||
HttpResponse::NotImplemented().finish()
|
let Ok(access_token) = session.find_jwt::<AppClaims>(claims.access_jti()).await else {
|
||||||
|
return Err(JsonError::new("No refresh token provided"));
|
||||||
|
};
|
||||||
|
let mut user: UserModel = match Users::find()
|
||||||
|
.filter(Column::Id.eq(access_token.account_id()))
|
||||||
|
.one(&**db)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(Some(user)) => user,
|
||||||
|
Ok(None) => {
|
||||||
|
return Err(JsonError::new(
|
||||||
|
"User for this token does not exists. Please contact administrator",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("Failed to connect to database on sign-out: {e}");
|
||||||
|
return Err(JsonError::new(Error::DatabaseError));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into();
|
||||||
|
|
||||||
|
user.last_logout_ip = Set(extract_req_ip(&req)?);
|
||||||
|
user.last_logout_time = Set(Some(chrono::Utc::now().fixed_offset()));
|
||||||
|
user.save(&**db).await.map_err(|e| {
|
||||||
|
tracing::error!("Failed to update user in sign-out: {e}");
|
||||||
|
return JsonError::new(Error::DatabaseError);
|
||||||
|
})?;
|
||||||
|
|
||||||
|
session.erase::<AppClaims>(access_token.jwt_id).await.ok();
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok().json(json!({ "message": "success" } )))
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ async fn main() {
|
|||||||
dotenv::from_filename(".env.development").ok();
|
dotenv::from_filename(".env.development").ok();
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
if let Ok(entry_dsn) = env::var("SENTRY_DSN") {
|
if let Ok(sentry_dsn) = env::var("SENTRY_DSN") {
|
||||||
let _guard = sentry::init(sentry_dsn);
|
let _guard = sentry::init(sentry_dsn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +54,8 @@ async fn main() {
|
|||||||
.with_refresh_header(REFRESH_HEADER_NAME)
|
.with_refresh_header(REFRESH_HEADER_NAME)
|
||||||
// Check if cookie JWT exists and contains encoded JWT
|
// Check if cookie JWT exists and contains encoded JWT
|
||||||
.with_refresh_cookie(REFRESH_COOKIE_NAME)
|
.with_refresh_cookie(REFRESH_COOKIE_NAME)
|
||||||
|
.with_jwt_json(&["refresh_token"])
|
||||||
|
.with_jwt_json(&["access_token"])
|
||||||
.finish();
|
.finish();
|
||||||
let jwt_ttl = JwtTtl(Duration::days(9999));
|
let jwt_ttl = JwtTtl(Duration::days(9999));
|
||||||
let refresh_ttl = RefreshTtl(Duration::days(3 * 31 * 999));
|
let refresh_ttl = RefreshTtl(Duration::days(3 * 31 * 999));
|
||||||
|
@ -23,17 +23,34 @@ use uuid::Uuid;
|
|||||||
use crate::http::OAuthError;
|
use crate::http::OAuthError;
|
||||||
use crate::{http::AuthError, models::Error};
|
use crate::{http::AuthError, models::Error};
|
||||||
|
|
||||||
pub fn extract_req_info(req: &HttpRequest) -> Result<(String, String, String), Error> {
|
pub fn extract_req_ip(req: &HttpRequest) -> Result<String, Error> {
|
||||||
let ip = req.peer_addr().ok_or(AuthError::NoPeerAddr)?.ip();
|
Ok(req
|
||||||
let user_agent = req
|
.peer_addr()
|
||||||
|
.ok_or(AuthError::NoPeerAddr)?
|
||||||
|
.ip()
|
||||||
|
.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_req_uagent(req: &HttpRequest) -> Result<String, Error> {
|
||||||
|
Ok(req
|
||||||
.headers()
|
.headers()
|
||||||
.get(USER_AGENT)
|
.get(USER_AGENT)
|
||||||
.ok_or(AuthError::NoUserAgent)?
|
.ok_or(AuthError::NoUserAgent)?
|
||||||
.to_str()
|
.to_str()
|
||||||
.map_err(|_| AuthError::InvalidUserAgent)?
|
.map_err(|_| AuthError::InvalidUserAgent)?
|
||||||
.to_string();
|
.to_string())
|
||||||
let current_site = req.uri().host().ok_or(Error::NoHost)?.to_owned();
|
}
|
||||||
Ok((ip.to_string(), user_agent, current_site))
|
|
||||||
|
pub fn extract_req_current_site(req: &HttpRequest) -> Result<String, Error> {
|
||||||
|
Ok(req.uri().host().ok_or(Error::NoHost)?.to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_req_info(req: &HttpRequest) -> Result<(String, String, String), Error> {
|
||||||
|
Ok((
|
||||||
|
extract_req_ip(&*req)?,
|
||||||
|
extract_req_uagent(&*req)?,
|
||||||
|
extract_req_current_site(req)?,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn invites_to_membership(
|
pub async fn invites_to_membership(
|
||||||
|
Loading…
Reference in New Issue
Block a user