Skip to content

Commit

Permalink
Merge pull request #78 from shield-auth/develop
Browse files Browse the repository at this point in the history
user creation endpoint moved from auth to users segment
  • Loading branch information
CA-MKSingh authored Nov 12, 2024
2 parents c2a5564 + 7ecbf64 commit 5934748
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 54 deletions.
8 changes: 5 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
version: '3.8'
version: "3.8"

services:
shield:
build: .
container_name: shield
ports:
- "5555:5555" # Adjust the port as needed
- "5555:5555" # Adjust the port as needed
depends_on:
db:
condition: service_healthy
Expand All @@ -21,6 +22,7 @@ services:

db:
image: postgres:17
container_name: shield-db
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
Expand All @@ -36,4 +38,4 @@ services:
retries: 5

volumes:
postgres_data:
postgres_data:
21 changes: 3 additions & 18 deletions src/handlers/auth.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
use axum_extra::either::Either;
use entity::{
sea_orm_active_enums::{ApiUserAccess, ApiUserScope},
session, user,
session,
};

use sea_orm::{prelude::Uuid, ColumnTrait, EntityTrait, QueryFilter, TransactionTrait};
use std::sync::Arc;

use crate::{
mappers::auth::{
CreateUserRequest, Credentials, IntrospectRequest, IntrospectResponse, LoginResponse, LogoutRequest, LogoutResponse, RefreshTokenRequest,
RefreshTokenResponse,
Credentials, IntrospectRequest, IntrospectResponse, LoginResponse, LogoutRequest, LogoutResponse, RefreshTokenRequest, RefreshTokenResponse,
},
middleware::session_info_extractor::SessionInfo,
packages::{
Expand All @@ -26,7 +25,7 @@ use crate::{
get_active_resource_group_by_rcu, get_active_session_by_id, get_active_sessions_by_user_and_client_id, handle_refresh_token,
},
client::get_active_client_by_id,
user::{get_active_user_and_resource_groups, get_active_user_by_id, insert_user},
user::{get_active_user_and_resource_groups, get_active_user_by_id},
},
utils::role_checker::has_access_to_api_cred,
};
Expand Down Expand Up @@ -65,20 +64,6 @@ pub async fn login(
Ok(Json(login_response))
}

pub async fn register(
api_user: ApiUser,
Extension(state): Extension<Arc<AppState>>,
Path((realm_id, client_id)): Path<(Uuid, Uuid)>,
Json(payload): Json<CreateUserRequest>,
) -> Result<Json<user::Model>, Error> {
if api_user.has_access(ApiUserScope::Client, ApiUserAccess::Write) {
let user = insert_user(&state.db, realm_id, client_id, payload).await?;
Ok(Json(user))
} else {
Err(Error::Authenticate(AuthenticateError::ActionForbidden))
}
}

pub async fn logout_current_session(user: JwtUser, Extension(state): Extension<Arc<AppState>>) -> Result<Json<LogoutResponse>, Error> {
let result = session::Entity::delete_by_id(user.sid).exec(&state.db).await?;
Ok(Json(LogoutResponse {
Expand Down
19 changes: 18 additions & 1 deletion src/handlers/user.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::sync::Arc;

use crate::mappers::user::{AddResourceRequest, UpdateResourceGroupRequest, UpdateResourceRequest};
use crate::mappers::user::{AddResourceRequest, CreateUserRequest, UpdateResourceGroupRequest, UpdateResourceRequest};
use crate::mappers::DeleteResponse;
use crate::packages::api_token::ApiUser;
use crate::services::user::insert_user;
use crate::utils::default_resource_checker::{is_default_resource, is_default_resource_group, is_default_user};
use axum::extract::Path;
use axum::{Extension, Json};
use chrono::Utc;
use entity::sea_orm_active_enums::{ApiUserAccess, ApiUserScope};
use entity::{resource, resource_group, user};
use futures::future::try_join_all;
use sea_orm::prelude::Uuid;
Expand All @@ -20,6 +23,20 @@ use crate::{
utils::role_checker::{is_current_realm_admin, is_master_realm_admin},
};

pub async fn create_user(
api_user: ApiUser,
Extension(state): Extension<Arc<AppState>>,
Path(realm_id): Path<Uuid>,
Json(payload): Json<CreateUserRequest>,
) -> Result<Json<user::Model>, Error> {
if api_user.has_access(ApiUserScope::Client, ApiUserAccess::Write) {
let user = insert_user(&state.db, realm_id, payload).await?;
Ok(Json(user))
} else {
Err(Error::Authenticate(AuthenticateError::ActionForbidden))
}
}

pub async fn get_users(
user: JwtUser,
Extension(state): Extension<Arc<AppState>>,
Expand Down
18 changes: 0 additions & 18 deletions src/mappers/auth.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use entity::user;
use sea_orm::prelude::Uuid;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Deserialize)]
pub struct Credentials {
Expand All @@ -20,23 +19,6 @@ pub struct LoginResponse {
pub refresh_token: Option<String>,
}

#[derive(Deserialize)]
pub struct ResourceSubset {
pub group_name: String,
pub identifiers: HashMap<String, String>,
}

#[derive(Deserialize)]
pub struct CreateUserRequest {
pub email: String,
pub password: String,
pub first_name: String,
pub last_name: Option<String>,
pub phone: Option<String>,
pub image: Option<String>,
pub resource: ResourceSubset,
}

#[derive(Deserialize)]
pub struct LogoutRequest {
pub access_token: Option<String>,
Expand Down
23 changes: 23 additions & 0 deletions src/mappers/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,29 @@ use std::collections::HashMap;
use sea_orm::prelude::Uuid;
use serde::Deserialize;

#[derive(Deserialize)]
pub struct ResourceGroup {
pub name: String,
pub client_id: Uuid,
}

#[derive(Deserialize)]
pub struct ResourceSubset {
pub group: ResourceGroup,
pub identifiers: HashMap<String, String>,
}

#[derive(Deserialize)]
pub struct CreateUserRequest {
pub email: String,
pub password: String,
pub first_name: String,
pub last_name: Option<String>,
pub phone: Option<String>,
pub image: Option<String>,
pub resource: ResourceSubset,
}

#[derive(Deserialize)]
pub struct AddResourceRequest {
pub group_name: Option<String>,
Expand Down
3 changes: 1 addition & 2 deletions src/routes/auth.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use axum::{middleware, routing::post, Router};

use crate::{
handlers::auth::{introspect, login, logout, logout_all, logout_current_session, logout_my_all_sessions, refresh_token, register},
handlers::auth::{introspect, login, logout, logout_all, logout_current_session, logout_my_all_sessions, refresh_token},
middleware::session_info_extractor::session_info_middleware,
};

Expand All @@ -12,7 +12,6 @@ pub fn create_routes() -> Router {
.route("/logout-current-session", post(logout_current_session))
.route("/logout-my-all-sessions", post(logout_my_all_sessions))
.route("/logout-all", post(logout_all))
.route("/register", post(register))
.route("/refresh-token", post(refresh_token))
.route("/introspect", post(introspect))
.layer(middleware::from_fn(session_info_middleware))
Expand Down
6 changes: 3 additions & 3 deletions src/routes/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ use axum::{
};

use crate::handlers::user::{
add_resources, delete_resource, delete_resource_group, delete_user, get_resource_group, get_resource_groups, get_resources, get_user, get_users,
update_resource, update_resource_group,
add_resources, create_user, delete_resource, delete_resource_group, delete_user, get_resource_group, get_resource_groups, get_resources,
get_user, get_users, update_resource, update_resource_group,
};

pub fn create_routes() -> Router {
Router::new().route("/", get(get_users)).nest(
Router::new().route("/", get(get_users).post(create_user)).nest(
"/:user_id",
Router::new()
.route("/", get(get_user).delete(delete_user))
Expand Down
19 changes: 10 additions & 9 deletions src/services/user.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use crate::{
mappers::auth::CreateUserRequest,
mappers::user::CreateUserRequest,
packages::errors::{AuthenticateError, Error, NotFoundError},
utils::hash::generate_password_hash,
};
use axum_extra::either::Either;
use entity::{resource, resource_group, user};
use futures::future::join_all;
use sea_orm::{prelude::Uuid, ActiveModelTrait, ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter, Set};
use sea_orm::{prelude::Uuid, ActiveModelTrait, ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter, Set, TransactionTrait};
use tracing::debug;

pub async fn insert_user(db: &DatabaseConnection, realm_id: Uuid, client_id: Uuid, payload: CreateUserRequest) -> Result<user::Model, Error> {
pub async fn insert_user(db: &DatabaseConnection, realm_id: Uuid, payload: CreateUserRequest) -> Result<user::Model, Error> {
let txn = db.begin().await?;
let password_hash = generate_password_hash(payload.password).await?;
let user_model = user::ActiveModel {
id: Set(Uuid::now_v7()),
Expand All @@ -23,17 +24,17 @@ pub async fn insert_user(db: &DatabaseConnection, realm_id: Uuid, client_id: Uui
..Default::default()
};

let user = user_model.insert(db).await?;
let user = user_model.insert(&txn).await?;

let resource_group = resource_group::ActiveModel {
id: Set(Uuid::now_v7()),
realm_id: Set(user.realm_id),
client_id: Set(client_id),
client_id: Set(payload.resource.group.client_id),
user_id: Set(user.id),
name: Set(payload.resource.group_name),
name: Set(payload.resource.group.name),
..Default::default()
};
let resource_group = resource_group.insert(db).await?;
let resource_group = resource_group.insert(&txn).await?;

let futures: Vec<_> = payload
.resource
Expand All @@ -47,12 +48,12 @@ pub async fn insert_user(db: &DatabaseConnection, realm_id: Uuid, client_id: Uui
value: Set(value.to_string()),
..Default::default()
};
resource.insert(db)
resource.insert(&txn)
})
.collect();

join_all(futures).await;

txn.commit().await?;
Ok(user)
}

Expand Down

0 comments on commit 5934748

Please sign in to comment.