oauth2
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
use axum::{
|
||||
extract::State,
|
||||
http::StatusCode,
|
||||
Json,
|
||||
};
|
||||
use axum_login::AuthSession;
|
||||
use sea_orm::{DatabaseConnection, EntityTrait, ColumnTrait, QueryFilter, ActiveModelTrait, Set};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::auth::{AuthBackend, Credentials};
|
||||
use crate::models::{user, User, family, Family};
|
||||
use crate::services::FamilyService;
|
||||
|
||||
#[derive(Debug, Deserialize, ToSchema)]
|
||||
pub struct LoginRequest {
|
||||
@@ -20,6 +24,15 @@ pub struct LoginResponse {
|
||||
pub is_admin: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub struct MeResponse {
|
||||
pub id: i32,
|
||||
pub username: Option<String>,
|
||||
pub email: Option<String>,
|
||||
pub is_admin: bool,
|
||||
pub family_id: Option<i32>,
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/login",
|
||||
@@ -72,3 +85,105 @@ pub async fn logout(
|
||||
|
||||
Ok(StatusCode::OK)
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/me",
|
||||
tag = "auth",
|
||||
responses(
|
||||
(status = 200, description = "Current user info", body = MeResponse),
|
||||
(status = 401, description = "Not authenticated")
|
||||
)
|
||||
)]
|
||||
pub async fn me(
|
||||
auth_session: AuthSession<AuthBackend>,
|
||||
) -> Result<Json<MeResponse>, StatusCode> {
|
||||
let user = auth_session.user.ok_or(StatusCode::UNAUTHORIZED)?;
|
||||
|
||||
Ok(Json(MeResponse {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
is_admin: user.is_admin,
|
||||
family_id: user.family_id,
|
||||
}))
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, ToSchema)]
|
||||
pub struct FamilyLoginRequest {
|
||||
pub family_name: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub struct FamilyLoginResponse {
|
||||
pub success: bool,
|
||||
pub family_id: i32,
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/auth/family-login",
|
||||
tag = "auth",
|
||||
request_body = FamilyLoginRequest,
|
||||
responses(
|
||||
(status = 200, description = "Login successful", body = FamilyLoginResponse),
|
||||
(status = 401, description = "Invalid credentials"),
|
||||
(status = 404, description = "Family not found")
|
||||
)
|
||||
)]
|
||||
pub async fn family_login(
|
||||
mut auth_session: AuthSession<AuthBackend>,
|
||||
State(db): State<DatabaseConnection>,
|
||||
Json(payload): Json<FamilyLoginRequest>,
|
||||
) -> Result<Json<FamilyLoginResponse>, StatusCode> {
|
||||
let family = Family::find()
|
||||
.filter(family::Column::Name.eq(&payload.family_name))
|
||||
.one(&db)
|
||||
.await
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?
|
||||
.ok_or(StatusCode::NOT_FOUND)?;
|
||||
|
||||
let valid = FamilyService::verify_password(&db, family.id, payload.password.clone())
|
||||
.await
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
|
||||
if !valid {
|
||||
return Err(StatusCode::UNAUTHORIZED);
|
||||
}
|
||||
|
||||
let existing_member = User::find()
|
||||
.filter(user::Column::FamilyId.eq(family.id))
|
||||
.filter(user::Column::GoogleId.is_null())
|
||||
.filter(user::Column::Username.eq(&payload.family_name))
|
||||
.one(&db)
|
||||
.await
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
|
||||
let member_user = if let Some(user) = existing_member {
|
||||
user
|
||||
} else {
|
||||
let new_member = user::ActiveModel {
|
||||
username: Set(Some(payload.family_name)),
|
||||
email: Set(None),
|
||||
google_id: Set(None),
|
||||
password_hash: Set(None),
|
||||
is_admin: Set(false),
|
||||
family_id: Set(Some(family.id)),
|
||||
..Default::default()
|
||||
};
|
||||
new_member.insert(&db)
|
||||
.await
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?
|
||||
};
|
||||
|
||||
auth_session
|
||||
.login(&member_user)
|
||||
.await
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
|
||||
Ok(Json(FamilyLoginResponse {
|
||||
success: true,
|
||||
family_id: family.id,
|
||||
}))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user