get complete session from login request instead of fetching again
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::domain::warren::models::auth_session::requests::CreateAuthSessionError;
|
||||
use crate::domain::warren::models::auth_session::{AuthSession, requests::CreateAuthSessionError};
|
||||
|
||||
use super::{UserEmail, UserName};
|
||||
use super::{User, UserEmail, UserName};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct RegisterUserRequest {
|
||||
@@ -125,6 +125,26 @@ pub struct LoginUserRequest {
|
||||
password: UserPassword,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct LoginUserResponse {
|
||||
session: AuthSession,
|
||||
user: User,
|
||||
}
|
||||
|
||||
impl LoginUserResponse {
|
||||
pub fn new(session: AuthSession, user: User) -> Self {
|
||||
Self { session, user }
|
||||
}
|
||||
|
||||
pub fn session(&self) -> &AuthSession {
|
||||
&self.session
|
||||
}
|
||||
|
||||
pub fn user(&self) -> &User {
|
||||
&self.user
|
||||
}
|
||||
}
|
||||
|
||||
impl LoginUserRequest {
|
||||
pub fn new(email: UserEmail, password: UserPassword) -> Self {
|
||||
Self { email, password }
|
||||
|
||||
@@ -19,7 +19,10 @@ use super::models::{
|
||||
DeleteDirectoryError, DeleteDirectoryRequest, DeleteFileError, DeleteFileRequest, File,
|
||||
FilePath, ListFilesError, ListFilesRequest, RenameEntryError, RenameEntryRequest,
|
||||
},
|
||||
user::{LoginUserError, LoginUserRequest, RegisterUserError, RegisterUserRequest, User},
|
||||
user::{
|
||||
LoginUserError, LoginUserRequest, LoginUserResponse, RegisterUserError,
|
||||
RegisterUserRequest, User,
|
||||
},
|
||||
warren::{
|
||||
CreateWarrenDirectoryError, CreateWarrenDirectoryRequest, DeleteWarrenDirectoryError,
|
||||
DeleteWarrenDirectoryRequest, DeleteWarrenFileError, DeleteWarrenFileRequest,
|
||||
@@ -108,7 +111,7 @@ pub trait AuthService: Clone + Send + Sync + 'static {
|
||||
fn login_user(
|
||||
&self,
|
||||
request: LoginUserRequest,
|
||||
) -> impl Future<Output = Result<AuthSession, LoginUserError>> + Send;
|
||||
) -> impl Future<Output = Result<LoginUserResponse, LoginUserError>> + Send;
|
||||
fn create_auth_session(
|
||||
&self,
|
||||
request: CreateAuthSessionRequest,
|
||||
|
||||
@@ -3,7 +3,7 @@ use uuid::Uuid;
|
||||
use crate::domain::warren::models::{
|
||||
auth_session::requests::FetchAuthSessionResponse,
|
||||
file::{AbsoluteFilePath, File, FilePath},
|
||||
user::User,
|
||||
user::{LoginUserResponse, User},
|
||||
warren::Warren,
|
||||
};
|
||||
|
||||
@@ -75,7 +75,7 @@ pub trait FileSystemNotifier: Clone + Send + Sync + 'static {
|
||||
|
||||
pub trait AuthNotifier: Clone + Send + Sync + 'static {
|
||||
fn user_registered(&self, user: &User) -> impl Future<Output = ()> + Send;
|
||||
fn user_logged_in(&self, user: &User) -> impl Future<Output = ()> + Send;
|
||||
fn user_logged_in(&self, response: &LoginUserResponse) -> impl Future<Output = ()> + Send;
|
||||
fn auth_session_created(&self, user_id: &Uuid) -> impl Future<Output = ()> + Send;
|
||||
fn auth_session_fetched(
|
||||
&self,
|
||||
|
||||
@@ -10,7 +10,8 @@ use crate::{
|
||||
},
|
||||
},
|
||||
user::{
|
||||
LoginUserError, LoginUserRequest, RegisterUserError, RegisterUserRequest, User,
|
||||
LoginUserError, LoginUserRequest, LoginUserResponse, RegisterUserError,
|
||||
RegisterUserRequest, User,
|
||||
},
|
||||
},
|
||||
ports::{AuthMetrics, AuthNotifier, AuthRepository, AuthService},
|
||||
@@ -93,7 +94,10 @@ where
|
||||
result
|
||||
}
|
||||
|
||||
async fn login_user(&self, request: LoginUserRequest) -> Result<AuthSession, LoginUserError> {
|
||||
async fn login_user(
|
||||
&self,
|
||||
request: LoginUserRequest,
|
||||
) -> Result<LoginUserResponse, LoginUserError> {
|
||||
let user = self
|
||||
.repository
|
||||
.verify_user_password(request.into())
|
||||
@@ -105,11 +109,12 @@ where
|
||||
user.clone(),
|
||||
self.config.session_lifetime(),
|
||||
))
|
||||
.await;
|
||||
.await
|
||||
.map(|session| LoginUserResponse::new(session, user));
|
||||
|
||||
if result.as_ref().is_ok() {
|
||||
if let Ok(response) = result.as_ref() {
|
||||
self.metrics.record_user_login_success().await;
|
||||
self.notifier.user_logged_in(&user).await;
|
||||
self.notifier.user_logged_in(response).await;
|
||||
} else {
|
||||
self.metrics.record_user_login_failure().await;
|
||||
}
|
||||
|
||||
@@ -3,45 +3,22 @@ use axum::{
|
||||
http::{HeaderMap, StatusCode},
|
||||
};
|
||||
use serde::Serialize;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
domain::warren::{
|
||||
models::{
|
||||
auth_session::{
|
||||
AuthSessionId,
|
||||
requests::{FetchAuthSessionRequest, FetchAuthSessionResponse},
|
||||
},
|
||||
user::User,
|
||||
models::auth_session::{
|
||||
AuthSessionId,
|
||||
requests::{FetchAuthSessionRequest, FetchAuthSessionResponse},
|
||||
},
|
||||
ports::{AuthService, WarrenService},
|
||||
},
|
||||
inbound::http::{
|
||||
AppState,
|
||||
handlers::SessionUser,
|
||||
responses::{ApiError, ApiSuccess},
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct SessionUser {
|
||||
id: Uuid,
|
||||
name: String,
|
||||
email: String,
|
||||
admin: bool,
|
||||
}
|
||||
|
||||
impl From<User> for SessionUser {
|
||||
fn from(value: User) -> Self {
|
||||
Self {
|
||||
id: *value.id(),
|
||||
name: value.name().to_string(),
|
||||
email: value.email().to_string(),
|
||||
admin: value.admin(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FetchSessionResponseBody {
|
||||
|
||||
@@ -4,14 +4,15 @@ use thiserror::Error;
|
||||
|
||||
use crate::{
|
||||
domain::warren::{
|
||||
models::{
|
||||
auth_session::AuthSession,
|
||||
user::{LoginUserRequest, UserEmail, UserEmailError, UserPassword, UserPasswordError},
|
||||
models::user::{
|
||||
LoginUserRequest, LoginUserResponse, UserEmail, UserEmailError, UserPassword,
|
||||
UserPasswordError,
|
||||
},
|
||||
ports::{AuthService, WarrenService},
|
||||
},
|
||||
inbound::http::{
|
||||
AppState,
|
||||
handlers::SessionUser,
|
||||
responses::{ApiError, ApiSuccess},
|
||||
},
|
||||
};
|
||||
@@ -66,16 +67,19 @@ impl LoginUserHttpRequestBody {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Include `user` and `expires_at` fields
|
||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||
pub struct LoginResponseBody {
|
||||
token: String,
|
||||
user: SessionUser,
|
||||
expires_at: i64,
|
||||
}
|
||||
|
||||
impl From<AuthSession> for LoginResponseBody {
|
||||
fn from(value: AuthSession) -> Self {
|
||||
impl From<LoginUserResponse> for LoginResponseBody {
|
||||
fn from(value: LoginUserResponse) -> Self {
|
||||
Self {
|
||||
token: value.session_id().to_string(),
|
||||
token: value.session().session_id().to_string(),
|
||||
user: value.user().to_owned().into(),
|
||||
expires_at: value.session().expires_at().and_utc().timestamp_millis(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,28 @@
|
||||
use serde::Serialize;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::domain::warren::models::user::User;
|
||||
|
||||
pub mod auth;
|
||||
pub mod warrens;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
/// A session user that can be safely sent to the client
|
||||
pub struct SessionUser {
|
||||
id: Uuid,
|
||||
name: String,
|
||||
email: String,
|
||||
admin: bool,
|
||||
}
|
||||
|
||||
impl From<User> for SessionUser {
|
||||
fn from(value: User) -> Self {
|
||||
Self {
|
||||
id: *value.id(),
|
||||
name: value.name().to_string(),
|
||||
email: value.email().to_string(),
|
||||
admin: value.admin(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::domain::warren::{
|
||||
models::{
|
||||
auth_session::requests::FetchAuthSessionResponse,
|
||||
file::{File, FilePath},
|
||||
user::User,
|
||||
user::{LoginUserResponse, User},
|
||||
warren::Warren,
|
||||
},
|
||||
ports::{AuthNotifier, FileSystemNotifier, WarrenNotifier},
|
||||
@@ -122,8 +122,8 @@ impl AuthNotifier for NotifierDebugLogger {
|
||||
tracing::debug!("[Notifier] Registered user {}", user.name());
|
||||
}
|
||||
|
||||
async fn user_logged_in(&self, user: &User) {
|
||||
tracing::debug!("[Notifier] Logged in user {}", user.name());
|
||||
async fn user_logged_in(&self, response: &LoginUserResponse) {
|
||||
tracing::debug!("[Notifier] Logged in user {}", response.user().name());
|
||||
}
|
||||
|
||||
async fn auth_session_created(&self, user_id: &Uuid) {
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import { toast } from 'vue-sonner';
|
||||
import type { ApiResponse } from '~/types/api';
|
||||
import { getAuthSessionData } from './getSession';
|
||||
import type { AuthUser } from '~/types/auth';
|
||||
|
||||
export async function loginUser(
|
||||
email: string,
|
||||
password: string
|
||||
): Promise<{ success: boolean }> {
|
||||
const { data, error } = await useFetch<ApiResponse<{ token: string }>>(
|
||||
getApiUrl('auth/login'),
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
password: password,
|
||||
}),
|
||||
responseType: 'json',
|
||||
}
|
||||
);
|
||||
const { data, error } = await useFetch<
|
||||
ApiResponse<{ token: string; user: AuthUser; expiresAt: number }>
|
||||
>(getApiUrl('auth/login'), {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
password: password,
|
||||
}),
|
||||
responseType: 'json',
|
||||
});
|
||||
|
||||
if (data.value == null) {
|
||||
toast.error('Login', {
|
||||
@@ -31,23 +31,14 @@ export async function loginUser(
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Get this data directly from the login request
|
||||
const sessionData = await getAuthSessionData({
|
||||
sessionType: 'WarrenAuth',
|
||||
sessionId: data.value.data.token,
|
||||
});
|
||||
|
||||
if (!sessionData.success) {
|
||||
return {
|
||||
success: false,
|
||||
};
|
||||
}
|
||||
const token = data.value.data.token;
|
||||
const { user, expiresAt } = data.value.data;
|
||||
|
||||
useAuthSession().value = {
|
||||
type: 'WarrenAuth',
|
||||
id: data.value.data.token,
|
||||
user: sessionData.user,
|
||||
expiresAt: sessionData.expiresAt,
|
||||
id: token,
|
||||
user,
|
||||
expiresAt,
|
||||
};
|
||||
|
||||
toast.success('Login', {
|
||||
|
||||
Reference in New Issue
Block a user