Compare commits
No commits in common. "0d6810f3d52e5159c37b788ad0f1300701185ca9" and "dd0567c937b9a4db59ba140be10f548da7e68313" have entirely different histories.
0d6810f3d5
...
dd0567c937
1
backend/.gitignore
vendored
1
backend/.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
.env
|
.env
|
||||||
|
/.sqlx
|
||||||
/target
|
/target
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT id, mime_type\n FROM image\n WHERE id = $1 AND deleted_time IS NULL\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "mime_type",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int4"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "1926140fd0232511d302cd514f41af1e619a1c68b94e18cdc53234c9de701390"
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n INSERT INTO image (mime_type)\n VALUES ($1)\n RETURNING id\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Varchar"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "715922e4ffa6881f23ea890ebf77abd86937c3f4fe606572156a29d4441028e9"
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT id, issuer, source_id, displayed_name, email\n FROM \"user\"\n WHERE issuer = $1 AND source_id = $2\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "issuer",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "source_id",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "displayed_name",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "email",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Text",
|
|
||||||
"Text"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "9c3ae9a539390e3b0493d325439fdc73cb2925bdb17330a21db4341e5822291b"
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n INSERT INTO \"user\" (issuer, source_id, displayed_name, email)\n VALUES ($1, $2, $3, $4)\n RETURNING id\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Varchar",
|
|
||||||
"Varchar",
|
|
||||||
"Varchar",
|
|
||||||
"Varchar"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "e9741186ea464ef1ba3598223ad9f042ec876cbdc4e2d9eca787ff1de598551c"
|
|
||||||
}
|
|
1
backend/Cargo.lock
generated
1
backend/Cargo.lock
generated
@ -428,7 +428,6 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"openidconnect",
|
"openidconnect",
|
||||||
"serde",
|
"serde",
|
||||||
"sqlx",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -10,4 +10,3 @@ async-trait.workspace = true
|
|||||||
log.workspace = true
|
log.workspace = true
|
||||||
openidconnect.workspace = true
|
openidconnect.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
sqlx.workspace = true
|
|
||||||
|
@ -4,7 +4,7 @@ use crate::domain::entity::user::User;
|
|||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct UserResponseDto {
|
pub struct UserResponseDto {
|
||||||
pub id: i32,
|
pub source_id: String,
|
||||||
pub displayed_name: String,
|
pub displayed_name: String,
|
||||||
pub email: String,
|
pub email: String,
|
||||||
}
|
}
|
||||||
@ -12,7 +12,7 @@ pub struct UserResponseDto {
|
|||||||
impl From<User> for UserResponseDto {
|
impl From<User> for UserResponseDto {
|
||||||
fn from(user: User) -> Self {
|
fn from(user: User) -> Self {
|
||||||
UserResponseDto {
|
UserResponseDto {
|
||||||
id: user.id,
|
source_id: user.source_id,
|
||||||
displayed_name: user.displayed_name,
|
displayed_name: user.displayed_name,
|
||||||
email: user.email,
|
email: user.email,
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
|
pub mod oidc_claims_response_dto;
|
||||||
pub mod auth_oidc_service;
|
pub mod auth_oidc_service;
|
||||||
pub mod auth_repository_impl;
|
pub mod auth_repository_impl;
|
||||||
pub mod oidc_claims_response_dto;
|
|
||||||
pub mod user_db_service;
|
|
||||||
pub mod user_db_mapper;
|
|
||||||
|
@ -3,9 +3,7 @@ use std::sync::Arc;
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
adapter::gateway::{
|
adapter::gateway::auth_oidc_service::AuthOidcService,
|
||||||
auth_oidc_service::AuthOidcService, user_db_service::UserDbService, user_db_mapper::UserMapper,
|
|
||||||
},
|
|
||||||
application::{
|
application::{
|
||||||
error::auth_error::AuthError, gateway::auth_repository::AuthRepository,
|
error::auth_error::AuthError, gateway::auth_repository::AuthRepository,
|
||||||
use_case::get_auth_url_use_case::AuthUrl,
|
use_case::get_auth_url_use_case::AuthUrl,
|
||||||
@ -14,19 +12,12 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub struct AuthRepositoryImpl {
|
pub struct AuthRepositoryImpl {
|
||||||
user_db_service: Arc<dyn UserDbService>,
|
|
||||||
auth_oidc_service: Arc<dyn AuthOidcService>,
|
auth_oidc_service: Arc<dyn AuthOidcService>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AuthRepositoryImpl {
|
impl AuthRepositoryImpl {
|
||||||
pub fn new(
|
pub fn new(auth_oidc_service: Arc<dyn AuthOidcService>) -> Self {
|
||||||
user_db_service: Arc<dyn UserDbService>,
|
Self { auth_oidc_service }
|
||||||
auth_oidc_service: Arc<dyn AuthOidcService>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
user_db_service,
|
|
||||||
auth_oidc_service,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,21 +37,4 @@ impl AuthRepository for AuthRepositoryImpl {
|
|||||||
.await
|
.await
|
||||||
.map(|dto| dto.into_entity())
|
.map(|dto| dto.into_entity())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user_by_source_id(
|
|
||||||
&self,
|
|
||||||
issuer: &str,
|
|
||||||
source_id: &str,
|
|
||||||
) -> Result<User, AuthError> {
|
|
||||||
self.user_db_service
|
|
||||||
.get_user_by_source_id(issuer, source_id)
|
|
||||||
.await
|
|
||||||
.map(|mapper| mapper.into_entity())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn save_user(&self, user: User) -> Result<i32, AuthError> {
|
|
||||||
self.user_db_service
|
|
||||||
.create_user(UserMapper::from(user))
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ use crate::domain::entity::user::User;
|
|||||||
|
|
||||||
pub struct OidcClaimsResponseDto {
|
pub struct OidcClaimsResponseDto {
|
||||||
pub sub: String,
|
pub sub: String,
|
||||||
pub issuer: String,
|
|
||||||
pub preferred_username: Option<String>,
|
pub preferred_username: Option<String>,
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
}
|
}
|
||||||
@ -10,8 +9,6 @@ pub struct OidcClaimsResponseDto {
|
|||||||
impl OidcClaimsResponseDto {
|
impl OidcClaimsResponseDto {
|
||||||
pub fn into_entity(self) -> User {
|
pub fn into_entity(self) -> User {
|
||||||
User {
|
User {
|
||||||
id: -1,
|
|
||||||
issuer: self.issuer,
|
|
||||||
source_id: self.sub,
|
source_id: self.sub,
|
||||||
displayed_name: self.preferred_username.unwrap_or_default(),
|
displayed_name: self.preferred_username.unwrap_or_default(),
|
||||||
email: self.email.unwrap_or_default(),
|
email: self.email.unwrap_or_default(),
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
use crate::domain::entity::user::User;
|
|
||||||
|
|
||||||
pub struct UserMapper {
|
|
||||||
pub id: i32,
|
|
||||||
pub issuer: String,
|
|
||||||
pub source_id: String,
|
|
||||||
pub displayed_name: String,
|
|
||||||
pub email: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<User> for UserMapper {
|
|
||||||
fn from(user: User) -> Self {
|
|
||||||
Self {
|
|
||||||
id: user.id,
|
|
||||||
issuer: user.issuer,
|
|
||||||
source_id: user.source_id,
|
|
||||||
displayed_name: user.displayed_name,
|
|
||||||
email: user.email,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UserMapper {
|
|
||||||
pub fn into_entity(self) -> User {
|
|
||||||
User {
|
|
||||||
id: self.id,
|
|
||||||
issuer: self.issuer,
|
|
||||||
source_id: self.source_id,
|
|
||||||
displayed_name: self.displayed_name,
|
|
||||||
email: self.email,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
use async_trait::async_trait;
|
|
||||||
|
|
||||||
use crate::{adapter::gateway::user_db_mapper::UserMapper, application::error::auth_error::AuthError};
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
pub trait UserDbService: Send + Sync {
|
|
||||||
async fn get_user_by_source_id(
|
|
||||||
&self,
|
|
||||||
issuer: &str,
|
|
||||||
source_id: &str,
|
|
||||||
) -> Result<UserMapper, AuthError>;
|
|
||||||
|
|
||||||
async fn create_user(&self, user: UserMapper) -> Result<i32, AuthError>;
|
|
||||||
}
|
|
@ -1,10 +1,8 @@
|
|||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum AuthError {
|
pub enum AuthError {
|
||||||
DatabaseError(String),
|
|
||||||
OidcError(String),
|
OidcError(String),
|
||||||
InvalidState,
|
InvalidState,
|
||||||
InvalidNonce,
|
InvalidNonce,
|
||||||
InvalidAuthCode,
|
InvalidAuthCode,
|
||||||
InvalidIdToken,
|
InvalidIdToken,
|
||||||
UserNotFound,
|
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,6 @@ use crate::{
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait AuthRepository: Send + Sync {
|
pub trait AuthRepository: Send + Sync {
|
||||||
fn get_auth_url(&self) -> Result<AuthUrl, AuthError>;
|
fn get_auth_url(&self) -> Result<AuthUrl, AuthError>;
|
||||||
|
|
||||||
async fn exchange_auth_code(&self, code: &str, expected_nonce: &str)
|
async fn exchange_auth_code(&self, code: &str, expected_nonce: &str)
|
||||||
-> Result<User, AuthError>;
|
-> Result<User, AuthError>;
|
||||||
|
|
||||||
async fn get_user_by_source_id(&self, issuer: &str, source_id: &str)
|
|
||||||
-> Result<User, AuthError>;
|
|
||||||
|
|
||||||
async fn save_user(&self, user: User) -> Result<i32, AuthError>;
|
|
||||||
}
|
}
|
||||||
|
@ -41,32 +41,8 @@ impl ExchangeAuthCodeUseCase for ExchangeAuthCodeUseCaseImpl {
|
|||||||
return Err(AuthError::InvalidState);
|
return Err(AuthError::InvalidState);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut logged_in_user = self
|
self.auth_repository
|
||||||
.auth_repository
|
|
||||||
.exchange_auth_code(code, expected_nonce)
|
.exchange_auth_code(code, expected_nonce)
|
||||||
.await?;
|
.await
|
||||||
|
|
||||||
let saved_user_result = self
|
|
||||||
.auth_repository
|
|
||||||
.get_user_by_source_id(&logged_in_user.issuer, &logged_in_user.source_id)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
match saved_user_result {
|
|
||||||
Ok(user) => {
|
|
||||||
logged_in_user.id = user.id;
|
|
||||||
}
|
|
||||||
Err(AuthError::UserNotFound) => {
|
|
||||||
let id = self
|
|
||||||
.auth_repository
|
|
||||||
.save_user(logged_in_user.clone())
|
|
||||||
.await?;
|
|
||||||
logged_in_user.id = id;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
return Err(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(logged_in_user)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
#[derive(Clone)]
|
|
||||||
pub struct User {
|
pub struct User {
|
||||||
pub id: i32,
|
|
||||||
pub issuer: String,
|
|
||||||
pub source_id: String,
|
pub source_id: String,
|
||||||
pub displayed_name: String,
|
pub displayed_name: String,
|
||||||
pub email: String,
|
pub email: String,
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
pub mod db;
|
|
||||||
pub mod oidc;
|
pub mod oidc;
|
||||||
pub mod web;
|
pub mod web;
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
pub mod user_db_service_impl;
|
|
||||||
pub mod user_record;
|
|
@ -1,65 +0,0 @@
|
|||||||
use async_trait::async_trait;
|
|
||||||
use sqlx::{Pool, Postgres};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
adapter::gateway::{user_db_service::UserDbService, user_db_mapper::UserMapper},
|
|
||||||
application::error::auth_error::AuthError,
|
|
||||||
framework::db::user_record::UserRecord,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct UserDbServiceImpl {
|
|
||||||
db_pool: Pool<Postgres>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UserDbServiceImpl {
|
|
||||||
pub fn new(db_pool: Pool<Postgres>) -> Self {
|
|
||||||
Self { db_pool }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl UserDbService for UserDbServiceImpl {
|
|
||||||
async fn get_user_by_source_id(
|
|
||||||
&self,
|
|
||||||
issuer: &str,
|
|
||||||
source_id: &str,
|
|
||||||
) -> Result<UserMapper, AuthError> {
|
|
||||||
let record = sqlx::query_as!(
|
|
||||||
UserRecord,
|
|
||||||
r#"
|
|
||||||
SELECT id, issuer, source_id, displayed_name, email
|
|
||||||
FROM "user"
|
|
||||||
WHERE issuer = $1 AND source_id = $2
|
|
||||||
"#,
|
|
||||||
issuer,
|
|
||||||
source_id
|
|
||||||
)
|
|
||||||
.fetch_optional(&self.db_pool)
|
|
||||||
.await
|
|
||||||
.map_err(|e| AuthError::DatabaseError(e.to_string()))?;
|
|
||||||
|
|
||||||
match record {
|
|
||||||
Some(record) => Ok(record.into_mapper()),
|
|
||||||
None => Err(AuthError::UserNotFound),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn create_user(&self, user: UserMapper) -> Result<i32, AuthError> {
|
|
||||||
let id = sqlx::query_scalar!(
|
|
||||||
r#"
|
|
||||||
INSERT INTO "user" (issuer, source_id, displayed_name, email)
|
|
||||||
VALUES ($1, $2, $3, $4)
|
|
||||||
RETURNING id
|
|
||||||
"#,
|
|
||||||
user.issuer,
|
|
||||||
user.source_id,
|
|
||||||
user.displayed_name,
|
|
||||||
user.email
|
|
||||||
)
|
|
||||||
.fetch_one(&self.db_pool)
|
|
||||||
.await
|
|
||||||
.map_err(|e| AuthError::DatabaseError(e.to_string()))?;
|
|
||||||
|
|
||||||
Ok(id)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
use sqlx::FromRow;
|
|
||||||
|
|
||||||
use crate::adapter::gateway::user_db_mapper::UserMapper;
|
|
||||||
|
|
||||||
#[derive(FromRow)]
|
|
||||||
pub struct UserRecord {
|
|
||||||
pub id: i32,
|
|
||||||
pub issuer: String,
|
|
||||||
pub source_id: String,
|
|
||||||
pub displayed_name: String,
|
|
||||||
pub email: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UserRecord {
|
|
||||||
pub fn into_mapper(self) -> UserMapper {
|
|
||||||
UserMapper {
|
|
||||||
id: self.id,
|
|
||||||
issuer: self.issuer,
|
|
||||||
source_id: self.source_id,
|
|
||||||
displayed_name: self.displayed_name,
|
|
||||||
email: self.email,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -93,8 +93,6 @@ impl AuthOidcService for AuthOidcServiceImpl {
|
|||||||
)
|
)
|
||||||
.map_err(|_| AuthError::InvalidIdToken)?;
|
.map_err(|_| AuthError::InvalidIdToken)?;
|
||||||
|
|
||||||
let issuer = claims.issuer().to_string();
|
|
||||||
|
|
||||||
let preferred_username = claims
|
let preferred_username = claims
|
||||||
.preferred_username()
|
.preferred_username()
|
||||||
.map(|username| username.to_string());
|
.map(|username| username.to_string());
|
||||||
@ -103,7 +101,6 @@ impl AuthOidcService for AuthOidcServiceImpl {
|
|||||||
|
|
||||||
Ok(OidcClaimsResponseDto {
|
Ok(OidcClaimsResponseDto {
|
||||||
sub: claims.subject().to_string(),
|
sub: claims.subject().to_string(),
|
||||||
issuer: issuer,
|
|
||||||
preferred_username: preferred_username,
|
preferred_username: preferred_username,
|
||||||
email: email,
|
email: email,
|
||||||
})
|
})
|
||||||
|
@ -1,3 +1 @@
|
|||||||
pub mod auth_web_routes;
|
pub mod auth_web_routes;
|
||||||
|
|
||||||
mod constants;
|
|
||||||
|
@ -6,11 +6,12 @@ use crate::{
|
|||||||
auth_controller::AuthController, oidc_callback_query_dto::OidcCallbackQueryDto,
|
auth_controller::AuthController, oidc_callback_query_dto::OidcCallbackQueryDto,
|
||||||
},
|
},
|
||||||
application::error::auth_error::AuthError,
|
application::error::auth_error::AuthError,
|
||||||
framework::web::constants::{
|
|
||||||
SESSION_KEY_AUTH_NONCE, SESSION_KEY_AUTH_STATE, SESSION_KEY_USER_ID,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SESSION_KEY_AUTH_STATE: &str = "auth_state";
|
||||||
|
const SESSION_KEY_AUTH_NONCE: &str = "auth_nonce";
|
||||||
|
const SESSION_KEY_USER: &str = "user";
|
||||||
|
|
||||||
pub fn configure_auth_routes(cfg: &mut web::ServiceConfig) {
|
pub fn configure_auth_routes(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(
|
cfg.service(
|
||||||
web::scope("/auth")
|
web::scope("/auth")
|
||||||
@ -28,11 +29,11 @@ async fn oidc_login_handler(
|
|||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(auth_url) => {
|
Ok(auth_url) => {
|
||||||
if let Err(e) = session.insert::<String>(SESSION_KEY_AUTH_STATE, auth_url.state) {
|
if let Err(e) = session.insert(SESSION_KEY_AUTH_STATE, auth_url.state) {
|
||||||
log::error!("{e:?}");
|
log::error!("{e:?}");
|
||||||
return HttpResponse::InternalServerError().finish();
|
return HttpResponse::InternalServerError().finish();
|
||||||
}
|
}
|
||||||
if let Err(e) = session.insert::<String>(SESSION_KEY_AUTH_NONCE, auth_url.nonce) {
|
if let Err(e) = session.insert(SESSION_KEY_AUTH_NONCE, auth_url.nonce) {
|
||||||
log::error!("{e:?}");
|
log::error!("{e:?}");
|
||||||
return HttpResponse::InternalServerError().finish();
|
return HttpResponse::InternalServerError().finish();
|
||||||
}
|
}
|
||||||
@ -52,12 +53,12 @@ async fn oidc_callback_handler(
|
|||||||
query: web::Query<OidcCallbackQueryDto>,
|
query: web::Query<OidcCallbackQueryDto>,
|
||||||
session: Session,
|
session: Session,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let expected_state = match session.get::<String>(SESSION_KEY_AUTH_STATE) {
|
let expected_state: String = match session.get(SESSION_KEY_AUTH_STATE) {
|
||||||
Ok(Some(state)) => state,
|
Ok(Some(state)) => state,
|
||||||
_ => return HttpResponse::BadRequest().finish(),
|
_ => return HttpResponse::BadRequest().finish(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let expected_nonce = match session.get::<String>(SESSION_KEY_AUTH_NONCE) {
|
let expected_nonce: String = match session.get(SESSION_KEY_AUTH_NONCE) {
|
||||||
Ok(Some(nonce)) => nonce,
|
Ok(Some(nonce)) => nonce,
|
||||||
_ => return HttpResponse::BadRequest().finish(),
|
_ => return HttpResponse::BadRequest().finish(),
|
||||||
};
|
};
|
||||||
@ -70,7 +71,7 @@ async fn oidc_callback_handler(
|
|||||||
session.remove(SESSION_KEY_AUTH_NONCE);
|
session.remove(SESSION_KEY_AUTH_NONCE);
|
||||||
match result {
|
match result {
|
||||||
Ok(user) => {
|
Ok(user) => {
|
||||||
if let Err(e) = session.insert::<i32>(SESSION_KEY_USER_ID, user.id) {
|
if let Err(e) = session.insert(SESSION_KEY_USER, user) {
|
||||||
log::error!("{e:?}");
|
log::error!("{e:?}");
|
||||||
return HttpResponse::InternalServerError().finish();
|
return HttpResponse::InternalServerError().finish();
|
||||||
}
|
}
|
||||||
@ -94,7 +95,7 @@ async fn oidc_callback_handler(
|
|||||||
async fn logout_handler(session: Session) -> impl Responder {
|
async fn logout_handler(session: Session) -> impl Responder {
|
||||||
session.remove(SESSION_KEY_AUTH_STATE);
|
session.remove(SESSION_KEY_AUTH_STATE);
|
||||||
session.remove(SESSION_KEY_AUTH_NONCE);
|
session.remove(SESSION_KEY_AUTH_NONCE);
|
||||||
session.remove(SESSION_KEY_USER_ID);
|
session.remove(SESSION_KEY_USER);
|
||||||
HttpResponse::Found()
|
HttpResponse::Found()
|
||||||
.append_header((header::LOCATION, "/"))
|
.append_header((header::LOCATION, "/"))
|
||||||
.finish()
|
.finish()
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
pub const SESSION_KEY_AUTH_STATE: &str = "auth_state";
|
|
||||||
pub const SESSION_KEY_AUTH_NONCE: &str = "auth_nonce";
|
|
||||||
pub const SESSION_KEY_USER_ID: &str = "user_id";
|
|
@ -8,7 +8,7 @@ pub struct ImageRequestDto {
|
|||||||
impl ImageRequestDto {
|
impl ImageRequestDto {
|
||||||
pub fn into_entity(self) -> Image {
|
pub fn into_entity(self) -> Image {
|
||||||
Image {
|
Image {
|
||||||
id: -1,
|
id: None,
|
||||||
mime_type: self.mime_type,
|
mime_type: self.mime_type,
|
||||||
data: self.data,
|
data: self.data,
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::domain::entity::image::Image;
|
use crate::domain::entity::image::Image;
|
||||||
|
|
||||||
pub struct ImageDbMapper {
|
pub struct ImageDbMapper {
|
||||||
pub id: i32,
|
pub id: Option<i32>,
|
||||||
pub mime_type: String,
|
pub mime_type: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
pub struct Image {
|
pub struct Image {
|
||||||
pub id: i32,
|
pub id: Option<i32>,
|
||||||
pub mime_type: String,
|
pub mime_type: String,
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ impl ImageDbService for ImageDbServiceImpl {
|
|||||||
match image_record {
|
match image_record {
|
||||||
Ok(record) => match record {
|
Ok(record) => match record {
|
||||||
Some(record) => Ok(ImageDbMapper {
|
Some(record) => Ok(ImageDbMapper {
|
||||||
id: record.id,
|
id: Some(record.id),
|
||||||
mime_type: record.mime_type,
|
mime_type: record.mime_type,
|
||||||
}),
|
}),
|
||||||
None => Err(ImageError::NotFound),
|
None => Err(ImageError::NotFound),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
CREATE TABLE IF NOT EXISTS "image" (
|
CREATE TABLE "image" (
|
||||||
"id" SERIAL PRIMARY KEY NOT NULL,
|
"id" SERIAL PRIMARY KEY NOT NULL,
|
||||||
"mime_type" VARCHAR(100) NOT NULL,
|
"mime_type" VARCHAR(100) NOT NULL,
|
||||||
"deleted_time" TIMESTAMP,
|
"deleted_time" TIMESTAMP,
|
||||||
@ -6,7 +6,7 @@ CREATE TABLE IF NOT EXISTS "image" (
|
|||||||
"updated_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
"updated_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE OR REPLACE TRIGGER "update_image_updated_time"
|
CREATE TRIGGER "update_image_updated_time"
|
||||||
BEFORE UPDATE ON "image"
|
BEFORE UPDATE ON "image"
|
||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
EXECUTE FUNCTION update_updated_time_column();
|
EXECUTE FUNCTION update_updated_time_column();
|
@ -1,6 +0,0 @@
|
|||||||
CREATE OR REPLACE FUNCTION update_updated_time_column() RETURNS TRIGGER AS $$
|
|
||||||
BEGIN
|
|
||||||
NEW.updated_time = CURRENT_TIMESTAMP;
|
|
||||||
return NEW;
|
|
||||||
END;
|
|
||||||
$$ LANGUAGE 'plpgsql';
|
|
@ -1,16 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS "post" (
|
|
||||||
"id" SERIAL PRIMARY KEY NOT NULL,
|
|
||||||
"title" TEXT NOT NULL,
|
|
||||||
"description" TEXT NOT NULL,
|
|
||||||
"preview_image_url" TEXT NOT NULL,
|
|
||||||
"content" TEXT NOT NULL,
|
|
||||||
"published_time" TIMESTAMP,
|
|
||||||
"deleted_time" TIMESTAMP,
|
|
||||||
"created_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updated_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE OR REPLACE TRIGGER "update_post_updated_time"
|
|
||||||
BEFORE UPDATE ON "post"
|
|
||||||
FOR EACH ROW
|
|
||||||
EXECUTE FUNCTION update_updated_time_column();
|
|
@ -1,13 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS "label" (
|
|
||||||
"id" SERIAL PRIMARY KEY NOT NULL,
|
|
||||||
"name" TEXT NOT NULL,
|
|
||||||
"color" BIGINT NOT NULL CHECK ("color" >= 0 AND "color" <= 4294967295),
|
|
||||||
"deleted_time" TIMESTAMP,
|
|
||||||
"created_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updated_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE OR REPLACE TRIGGER "update_label_updated_time"
|
|
||||||
BEFORE UPDATE ON "label"
|
|
||||||
FOR EACH ROW
|
|
||||||
EXECUTE FUNCTION update_updated_time_column();
|
|
@ -1,7 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS "post_label" (
|
|
||||||
"post_id" INTEGER NOT NULL,
|
|
||||||
"label_id" INTEGER NOT NULL,
|
|
||||||
PRIMARY KEY ("post_id", "label_id"),
|
|
||||||
FOREIGN KEY ("post_id") REFERENCES "post" ("id") ON DELETE CASCADE,
|
|
||||||
FOREIGN KEY ("label_id") REFERENCES "label" ("id") ON DELETE CASCADE
|
|
||||||
);
|
|
@ -1,20 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS "user" (
|
|
||||||
"id" SERIAL PRIMARY KEY NOT NULL,
|
|
||||||
"issuer" VARCHAR(100) NOT NULL,
|
|
||||||
"source_id" VARCHAR(100) NOT NULL,
|
|
||||||
"displayed_name" VARCHAR(100) NOT NULL,
|
|
||||||
"email" VARCHAR(100) NOT NULL,
|
|
||||||
"created_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updated_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX IF NOT EXISTS "idx_user_source_id_issuer"
|
|
||||||
ON "user" ("source_id", "issuer");
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS "idx_user_email"
|
|
||||||
ON "user" ("email");
|
|
||||||
|
|
||||||
CREATE OR REPLACE TRIGGER "update_user_updated_time"
|
|
||||||
BEFORE UPDATE ON "user"
|
|
||||||
FOR EACH ROW
|
|
||||||
EXECUTE FUNCTION update_updated_time_column();
|
|
@ -9,10 +9,7 @@ use auth::{
|
|||||||
exchange_auth_code_use_case::ExchangeAuthCodeUseCaseImpl,
|
exchange_auth_code_use_case::ExchangeAuthCodeUseCaseImpl,
|
||||||
get_auth_url_use_case::LoginUseCaseImpl,
|
get_auth_url_use_case::LoginUseCaseImpl,
|
||||||
},
|
},
|
||||||
framework::{
|
framework::oidc::auth_oidc_service_impl::AuthOidcServiceImpl,
|
||||||
db::user_db_service_impl::UserDbServiceImpl,
|
|
||||||
oidc::auth_oidc_service_impl::AuthOidcServiceImpl,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use image::{
|
use image::{
|
||||||
adapter::{
|
adapter::{
|
||||||
@ -63,8 +60,7 @@ impl Container {
|
|||||||
oidc_configuration.redirect_url.clone(),
|
oidc_configuration.redirect_url.clone(),
|
||||||
http_client,
|
http_client,
|
||||||
));
|
));
|
||||||
let user_db_service = Arc::new(UserDbServiceImpl::new(db_pool.clone()));
|
let auth_repository = Arc::new(AuthRepositoryImpl::new(auth_oidc_service));
|
||||||
let auth_repository = Arc::new(AuthRepositoryImpl::new(user_db_service, auth_oidc_service));
|
|
||||||
let get_auth_url_use_case = Arc::new(LoginUseCaseImpl::new(auth_repository.clone()));
|
let get_auth_url_use_case = Arc::new(LoginUseCaseImpl::new(auth_repository.clone()));
|
||||||
let exchange_auth_code_use_case =
|
let exchange_auth_code_use_case =
|
||||||
Arc::new(ExchangeAuthCodeUseCaseImpl::new(auth_repository.clone()));
|
Arc::new(ExchangeAuthCodeUseCaseImpl::new(auth_repository.clone()));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user