feat: microservice ready
This commit is contained in:
Generated
+114
@@ -1849,6 +1849,31 @@ checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
|
||||
[[package]]
|
||||
name = "imphnen-backend-service"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
"axum-test",
|
||||
"chrono",
|
||||
"imphnen-entities",
|
||||
"imphnen-gateway-service",
|
||||
"imphnen-libs",
|
||||
"imphnen-utils",
|
||||
"lazy_static",
|
||||
"rand 0.9.0",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"surrealdb",
|
||||
"tokio",
|
||||
"tower-http",
|
||||
"utoipa",
|
||||
"utoipa-swagger-ui",
|
||||
"validator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imphnen-dimentorin-service"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -1881,6 +1906,79 @@ dependencies = [
|
||||
"utoipa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imphnen-gacha-service"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
"axum-test",
|
||||
"chrono",
|
||||
"imphnen-entities",
|
||||
"imphnen-libs",
|
||||
"imphnen-utils",
|
||||
"lazy_static",
|
||||
"rand 0.9.0",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"surrealdb",
|
||||
"tokio",
|
||||
"tower-http",
|
||||
"utoipa",
|
||||
"utoipa-swagger-ui",
|
||||
"validator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imphnen-gateway-service"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
"axum-test",
|
||||
"chrono",
|
||||
"imphnen-entities",
|
||||
"imphnen-iam-service",
|
||||
"imphnen-libs",
|
||||
"imphnen-utils",
|
||||
"lazy_static",
|
||||
"rand 0.9.0",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"surrealdb",
|
||||
"tokio",
|
||||
"tower-http",
|
||||
"utoipa",
|
||||
"utoipa-swagger-ui",
|
||||
"validator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imphnen-iam-service"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
"axum-test",
|
||||
"chrono",
|
||||
"imphnen-entities",
|
||||
"imphnen-libs",
|
||||
"imphnen-utils",
|
||||
"lazy_static",
|
||||
"rand 0.9.0",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"surrealdb",
|
||||
"tokio",
|
||||
"tower-http",
|
||||
"utoipa",
|
||||
"utoipa-swagger-ui",
|
||||
"validator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imphnen-libs"
|
||||
version = "0.1.0"
|
||||
@@ -4159,6 +4257,22 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum-test",
|
||||
"chrono",
|
||||
"imphnen-entities",
|
||||
"imphnen-iam-service",
|
||||
"imphnen-libs",
|
||||
"imphnen-utils",
|
||||
"serde_json",
|
||||
"surrealdb",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
|
||||
+2
-4
@@ -1,10 +1,8 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
"imphnen-apis",
|
||||
"imphnen-utils",
|
||||
"imphnen-libs",
|
||||
"imphnen-entities",
|
||||
"imphnen-*",
|
||||
"tests",
|
||||
]
|
||||
|
||||
[workspace.dependencies]
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
use crate::{AppState, Env, SurrealMemClient, SurrealWsClient};
|
||||
use axum::{
|
||||
http::{header, HeaderValue, Method},
|
||||
response::Redirect,
|
||||
routing::get,
|
||||
Extension, Router,
|
||||
};
|
||||
use tower_http::cors::CorsLayer;
|
||||
use utoipa_swagger_ui::SwaggerUi;
|
||||
|
||||
pub mod v1;
|
||||
pub mod v2;
|
||||
|
||||
pub use v1::*;
|
||||
|
||||
pub async fn apps(
|
||||
surrealdb_ws: SurrealWsClient,
|
||||
surrealdb_mem: SurrealMemClient,
|
||||
) -> Router {
|
||||
let state = AppState {
|
||||
surrealdb_ws,
|
||||
surrealdb_mem,
|
||||
};
|
||||
let env = Env::new();
|
||||
let cors_origins = match env.rust_env.as_str() {
|
||||
"development" => vec!["http://localhost:3000"],
|
||||
"production" => {
|
||||
vec!["https://gacha.imphnen.dev", "https://imphnen.dev"]
|
||||
}
|
||||
_ => vec![
|
||||
"http://localhost:3000",
|
||||
"https://gacha.imphnen.dev",
|
||||
"https://imphnen.dev",
|
||||
],
|
||||
};
|
||||
|
||||
let allowed_origins: Vec<HeaderValue> = cors_origins
|
||||
.into_iter()
|
||||
.filter_map(|origin| origin.parse::<HeaderValue>().ok())
|
||||
.collect();
|
||||
|
||||
let cors_middleware = CorsLayer::new()
|
||||
.allow_origin(allowed_origins)
|
||||
.allow_methods([Method::GET, Method::POST, Method::PUT, Method::DELETE])
|
||||
.allow_headers([header::AUTHORIZATION, header::CONTENT_TYPE])
|
||||
.allow_credentials(true);
|
||||
|
||||
Router::new()
|
||||
.route("/", get(Redirect::to("/docs")))
|
||||
.nest("/v1", v1::routes().await)
|
||||
.nest("/v2", v2::routes().await)
|
||||
.merge(SwaggerUi::new("/docs").url("/openapi.json", v1::docs_router()))
|
||||
.layer(cors_middleware)
|
||||
.layer(Extension(state))
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
use crate::{
|
||||
common_response, extract_email, AppState, UsersItemDtoRaw, UsersRepository,
|
||||
};
|
||||
use axum::{
|
||||
extract::Request, http::StatusCode, middleware::Next, response::Response,
|
||||
Extension,
|
||||
};
|
||||
use std::convert::Infallible;
|
||||
|
||||
pub async fn auth_middleware(
|
||||
Extension(state): Extension<AppState>,
|
||||
mut req: Request,
|
||||
next: Next,
|
||||
) -> Result<Response, Infallible> {
|
||||
let headers = req.headers();
|
||||
|
||||
let email = match extract_email(headers) {
|
||||
Some(email) => email,
|
||||
None => {
|
||||
return Ok(common_response(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
"Invalid or expired token",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let repository = UsersRepository::new(&state);
|
||||
|
||||
let user: Option<UsersItemDtoRaw> =
|
||||
match repository.query_user_by_email(email).await {
|
||||
Ok(user) => Some(user),
|
||||
Err(err) => {
|
||||
return Ok(common_response(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
&err.to_string(),
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
if user.is_none() {
|
||||
return Ok(common_response(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
"Unauthorized user",
|
||||
));
|
||||
}
|
||||
|
||||
req.extensions_mut().insert(user.unwrap());
|
||||
|
||||
Ok(next.run(req).await)
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
use utoipa::OpenApi;
|
||||
|
||||
pub mod docs_controller;
|
||||
pub use docs_controller::*;
|
||||
|
||||
pub fn docs_router() -> utoipa::openapi::OpenApi {
|
||||
ApiDoc::openapi()
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
use axum::{middleware::from_fn, Router};
|
||||
pub mod auth;
|
||||
pub mod docs;
|
||||
pub mod gacha;
|
||||
pub mod permissions;
|
||||
pub mod roles;
|
||||
pub mod users;
|
||||
|
||||
pub use auth::*;
|
||||
pub use docs::*;
|
||||
pub use permissions::*;
|
||||
pub use roles::*;
|
||||
pub use users::*;
|
||||
|
||||
pub async fn routes() -> Router {
|
||||
let public_routes = Router::new().nest("/auth", auth_router());
|
||||
let protected_routes = Router::new()
|
||||
.nest("/users", users_router())
|
||||
.nest("/roles", roles_router())
|
||||
.nest("/permissions", permissions_router())
|
||||
.layer(from_fn(auth::auth_middleware::auth_middleware));
|
||||
Router::new().merge(public_routes).merge(protected_routes)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
use axum::{response::IntoResponse, routing::post, Router};
|
||||
|
||||
async fn dummy_login() -> impl IntoResponse {
|
||||
"Logged in successfully"
|
||||
}
|
||||
|
||||
pub fn auth_router() -> Router {
|
||||
Router::new().route("/login", post(dummy_login))
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
use axum::Router;
|
||||
|
||||
pub mod auth;
|
||||
pub use auth::*;
|
||||
|
||||
pub async fn routes() -> Router {
|
||||
let public_routes = Router::new().nest("/auth", auth::auth_router());
|
||||
Router::new().merge(public_routes)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
use imphnen_backend_service::{apps, axum_init};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
axum_init(|surrealdb_ws, surrealdb_mem| async {
|
||||
apps(surrealdb_ws, surrealdb_mem).await
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
use imphnen_backend_service::{apps, axum_init};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
axum_init(|surrealdb_ws, surrealdb_mem| async {
|
||||
apps(surrealdb_ws, surrealdb_mem).await
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
[package]
|
||||
name = "imphnen-backend-service"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
imphnen-entities = { version = "0.1.0", path = "../imphnen-entities" }
|
||||
imphnen-libs = { version = "0.1.0", path = "../imphnen-libs" }
|
||||
imphnen-utils = { version = "0.1.0", path = "../imphnen-utils" }
|
||||
axum.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
utoipa.workspace = true
|
||||
lazy_static.workspace = true
|
||||
regex.workspace = true
|
||||
validator.workspace = true
|
||||
axum-test.workspace = true
|
||||
surrealdb.workspace = true
|
||||
rand.workspace = true
|
||||
tokio.workspace = true
|
||||
chrono.workspace = true
|
||||
anyhow.workspace = true
|
||||
tower-http.workspace = true
|
||||
utoipa-swagger-ui.workspace = true
|
||||
imphnen-gateway-service = { version = "0.1.0", path = "../imphnen-gateway-service" }
|
||||
@@ -0,0 +1,10 @@
|
||||
use imphnen_gateway_service::gateway_service;
|
||||
use imphnen_libs::axum_init;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
axum_init(|surrealdb_ws, surrealdb_mem| async {
|
||||
gateway_service(surrealdb_ws, surrealdb_mem).await
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
use imphnen_gateway_service::gateway_service;
|
||||
use imphnen_libs::axum_init;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
axum_init(|surrealdb_ws, surrealdb_mem| async {
|
||||
gateway_service(surrealdb_ws, surrealdb_mem).await
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
[package]
|
||||
name = "imphnen-dimentorin-service"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
imphnen-entities = { version = "0.1.0", path = "../imphnen-entities" }
|
||||
imphnen-libs = { version = "0.1.0", path = "../imphnen-libs" }
|
||||
imphnen-utils = { version = "0.1.0", path = "../imphnen-utils" }
|
||||
axum.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
utoipa.workspace = true
|
||||
lazy_static.workspace = true
|
||||
regex.workspace = true
|
||||
validator.workspace = true
|
||||
axum-test.workspace = true
|
||||
surrealdb.workspace = true
|
||||
rand.workspace = true
|
||||
tokio.workspace = true
|
||||
chrono.workspace = true
|
||||
anyhow.workspace = true
|
||||
tower-http.workspace = true
|
||||
utoipa-swagger-ui.workspace = true
|
||||
@@ -0,0 +1,14 @@
|
||||
pub fn add(left: u64, right: u64) -> u64 {
|
||||
left + right
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "imphnen-backend-service"
|
||||
name = "imphnen-gacha-service"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
imphnen-entities = { version = "0.1.0", path = "../imphnen-entities" }
|
||||
@@ -0,0 +1,9 @@
|
||||
use imphnen_entities::*;
|
||||
use imphnen_libs::*;
|
||||
use imphnen_utils::*;
|
||||
|
||||
pub mod v1;
|
||||
pub use imphnen_entities::*;
|
||||
pub use imphnen_libs::*;
|
||||
pub use imphnen_utils::*;
|
||||
pub use v1::*;
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
use super::{GachaClaimSchema, GachaItemSchema, GachaRollSchema};
|
||||
use crate::{
|
||||
get_id, make_thing, query_list_with_meta, AppState, MetaRequestDto, ResourceEnum,
|
||||
ResponseListSuccessDto,
|
||||
AppState, MetaRequestDto, ResourceEnum, ResponseListSuccessDto, get_id,
|
||||
make_thing, query_list_with_meta,
|
||||
};
|
||||
use anyhow::{bail, Result};
|
||||
use anyhow::{Result, bail};
|
||||
|
||||
pub struct GachaRepository<'a> {
|
||||
state: &'a AppState,
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod gacha;
|
||||
pub use gacha::*;
|
||||
@@ -0,0 +1,25 @@
|
||||
[package]
|
||||
name = "imphnen-gateway-service"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
imphnen-iam-service = { version = "0.1.0", path = "../imphnen-iam-service" }
|
||||
imphnen-entities = { version = "0.1.0", path = "../imphnen-entities" }
|
||||
imphnen-libs = { version = "0.1.0", path = "../imphnen-libs" }
|
||||
imphnen-utils = { version = "0.1.0", path = "../imphnen-utils" }
|
||||
axum.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
utoipa.workspace = true
|
||||
lazy_static.workspace = true
|
||||
regex.workspace = true
|
||||
validator.workspace = true
|
||||
axum-test.workspace = true
|
||||
surrealdb.workspace = true
|
||||
rand.workspace = true
|
||||
tokio.workspace = true
|
||||
chrono.workspace = true
|
||||
anyhow.workspace = true
|
||||
tower-http.workspace = true
|
||||
utoipa-swagger-ui.workspace = true
|
||||
+7
-5
@@ -1,9 +1,7 @@
|
||||
use crate::{
|
||||
v1::{
|
||||
auth, permissions, roles, users, AuthLoginRequestDto, AuthLoginResponsetDto, AuthResendOtpRequestDto, AuthVerifyEmailRequestDto
|
||||
}, AuthNewPasswordRequestDto, AuthRefreshTokenRequestDto, MessageResponseDto, MetaRequestDto, MetaResponseDto, PermissionsItemDto, PermissionsRequestDto, ResponseListSuccessDto, ResponseSuccessDto, RolesItemDto, RolesRequestCreateDto, RolesRequestUpdateDto, TokenDto, UsersCreateRequestDto, UsersDetailItemDto, UsersItemDto, UsersListItemDto, UsersUpdateRequestDto
|
||||
use imphnen_iam_service::{
|
||||
auth, permissions, roles, users, AuthLoginRequestDto, AuthLoginResponsetDto, AuthResendOtpRequestDto, AuthVerifyEmailRequestDto,
|
||||
AuthNewPasswordRequestDto, AuthRefreshTokenRequestDto, MessageResponseDto, MetaRequestDto, MetaResponseDto, PermissionsItemDto, PermissionsRequestDto, ResponseListSuccessDto, ResponseSuccessDto, RolesItemDto, RolesRequestCreateDto, RolesRequestUpdateDto, TokenDto, UsersCreateRequestDto, UsersDetailItemDto, UsersItemDto, UsersListItemDto, UsersUpdateRequestDto
|
||||
};
|
||||
|
||||
use utoipa::{
|
||||
openapi::security::{Http, HttpAuthScheme, SecurityScheme},
|
||||
Modify, OpenApi,
|
||||
@@ -101,3 +99,7 @@ impl Modify for SecurityAddon {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn docs_router() -> utoipa::openapi::OpenApi {
|
||||
ApiDoc::openapi()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
use axum::{
|
||||
Extension, Router, middleware::from_fn, response::Redirect, routing::get,
|
||||
};
|
||||
use imphnen_entities::{AppState, SurrealMemClient, SurrealWsClient};
|
||||
use imphnen_iam_service::{iam_protected_routes, iam_public_routes};
|
||||
|
||||
pub mod docs;
|
||||
pub mod middleware;
|
||||
|
||||
pub use docs::*;
|
||||
pub use middleware::*;
|
||||
use utoipa_swagger_ui::SwaggerUi;
|
||||
|
||||
pub async fn gateway_service(
|
||||
surrealdb_ws: SurrealWsClient,
|
||||
surrealdb_mem: SurrealMemClient,
|
||||
) -> Router {
|
||||
let state = AppState {
|
||||
surrealdb_ws,
|
||||
surrealdb_mem,
|
||||
};
|
||||
|
||||
let public_routes = iam_public_routes();
|
||||
let protected_routes = iam_protected_routes().layer(from_fn(auth_middleware));
|
||||
|
||||
Router::new()
|
||||
.route("/", get(Redirect::to("/docs")))
|
||||
.nest("/v1", public_routes.merge(protected_routes))
|
||||
.merge(SwaggerUi::new("/docs").url("/openapi.json", docs_router()))
|
||||
.layer(cors_middleware())
|
||||
.layer(Extension(state.clone()))
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
use axum::{
|
||||
Extension,
|
||||
extract::Request,
|
||||
http::{HeaderValue, Method, StatusCode, header},
|
||||
middleware::Next,
|
||||
response::Response,
|
||||
};
|
||||
use imphnen_iam_service::{UsersItemDtoRaw, UsersRepository};
|
||||
use imphnen_libs::{AppState, Env};
|
||||
use imphnen_utils::{common_response, extract_email};
|
||||
use std::convert::Infallible;
|
||||
use tower_http::cors::CorsLayer;
|
||||
|
||||
pub async fn auth_middleware(
|
||||
Extension(state): Extension<AppState>,
|
||||
mut req: Request,
|
||||
next: Next,
|
||||
) -> Result<Response, Infallible> {
|
||||
let headers = req.headers();
|
||||
let email = match extract_email(headers) {
|
||||
Some(email) => email,
|
||||
None => {
|
||||
return Ok(common_response(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
"Invalid or expired token",
|
||||
));
|
||||
}
|
||||
};
|
||||
let repository = UsersRepository::new(&state);
|
||||
let user: Option<UsersItemDtoRaw> =
|
||||
match repository.query_user_by_email(email).await {
|
||||
Ok(user) => Some(user),
|
||||
Err(err) => {
|
||||
return Ok(common_response(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
&err.to_string(),
|
||||
));
|
||||
}
|
||||
};
|
||||
if user.is_none() {
|
||||
return Ok(common_response(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
"Unauthorized user",
|
||||
));
|
||||
}
|
||||
req.extensions_mut().insert(user.unwrap());
|
||||
Ok(next.run(req).await)
|
||||
}
|
||||
|
||||
pub fn cors_middleware() -> CorsLayer {
|
||||
let env = Env::new();
|
||||
let cors_origins = match env.rust_env.as_str() {
|
||||
"development" => vec!["http://localhost:3000"],
|
||||
"production" => {
|
||||
vec!["https://gacha.imphnen.dev", "https://imphnen.dev"]
|
||||
}
|
||||
_ => vec![
|
||||
"http://localhost:3000",
|
||||
"https://gacha.imphnen.dev",
|
||||
"https://imphnen.dev",
|
||||
],
|
||||
};
|
||||
let allowed_origins: Vec<HeaderValue> = cors_origins
|
||||
.into_iter()
|
||||
.filter_map(|origin| origin.parse::<HeaderValue>().ok())
|
||||
.collect();
|
||||
|
||||
CorsLayer::new()
|
||||
.allow_origin(allowed_origins)
|
||||
.allow_methods([Method::GET, Method::POST, Method::PUT, Method::DELETE])
|
||||
.allow_headers([header::AUTHORIZATION, header::CONTENT_TYPE])
|
||||
.allow_credentials(true)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
[package]
|
||||
name = "imphnen-iam-service"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
imphnen-entities = { version = "0.1.0", path = "../imphnen-entities" }
|
||||
imphnen-libs = { version = "0.1.0", path = "../imphnen-libs" }
|
||||
imphnen-utils = { version = "0.1.0", path = "../imphnen-utils" }
|
||||
axum.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
utoipa.workspace = true
|
||||
lazy_static.workspace = true
|
||||
regex.workspace = true
|
||||
validator.workspace = true
|
||||
axum-test.workspace = true
|
||||
surrealdb.workspace = true
|
||||
rand.workspace = true
|
||||
tokio.workspace = true
|
||||
chrono.workspace = true
|
||||
anyhow.workspace = true
|
||||
tower-http.workspace = true
|
||||
utoipa-swagger-ui.workspace = true
|
||||
@@ -3,11 +3,11 @@ use imphnen_entities::*;
|
||||
use imphnen_libs::*;
|
||||
use imphnen_utils::*;
|
||||
|
||||
pub mod apps;
|
||||
pub mod v1;
|
||||
|
||||
pub use apps::*;
|
||||
pub use imphnen_entities::*;
|
||||
pub use imphnen_libs::*;
|
||||
pub use v1::*;
|
||||
|
||||
pub fn create_test_user(
|
||||
email: &str,
|
||||
@@ -1,17 +1,11 @@
|
||||
use axum::{routing::post, Router};
|
||||
use axum::{Router, routing::post};
|
||||
|
||||
pub mod auth_controller;
|
||||
pub mod auth_dto;
|
||||
pub mod auth_middleware;
|
||||
pub mod auth_repository;
|
||||
pub mod auth_schema;
|
||||
pub mod auth_service;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod auth_controller_test;
|
||||
#[cfg(test)]
|
||||
pub mod auth_repository_test;
|
||||
|
||||
pub use auth_dto::*;
|
||||
pub use auth_repository::*;
|
||||
pub use auth_schema::*;
|
||||
@@ -0,0 +1,22 @@
|
||||
use axum::Router;
|
||||
|
||||
pub mod auth;
|
||||
pub mod permissions;
|
||||
pub mod roles;
|
||||
pub mod users;
|
||||
|
||||
pub use auth::*;
|
||||
pub use permissions::*;
|
||||
pub use roles::*;
|
||||
pub use users::*;
|
||||
|
||||
pub fn iam_public_routes() -> Router {
|
||||
Router::new().nest("/auth", auth_router())
|
||||
}
|
||||
|
||||
pub fn iam_protected_routes() -> Router {
|
||||
Router::new()
|
||||
.nest("/users", users_router())
|
||||
.nest("/roles", roles_router())
|
||||
.nest("/permissions", permissions_router())
|
||||
}
|
||||
+1
-6
@@ -1,6 +1,6 @@
|
||||
use axum::{
|
||||
routing::{delete, get, post, put},
|
||||
Router,
|
||||
routing::{delete, get, post, put},
|
||||
};
|
||||
pub mod permissions_controller;
|
||||
pub mod permissions_dto;
|
||||
@@ -10,11 +10,6 @@ pub mod permissions_repository;
|
||||
pub mod permissions_schema;
|
||||
pub mod permissions_service;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod permissions_controller_test;
|
||||
#[cfg(test)]
|
||||
pub mod permissions_repository_test;
|
||||
|
||||
pub use permissions_controller::*;
|
||||
pub use permissions_dto::*;
|
||||
pub use permissions_enum::*;
|
||||
@@ -1,6 +1,6 @@
|
||||
use axum::{
|
||||
routing::{delete, get, post, put},
|
||||
Router,
|
||||
routing::{delete, get, post, put},
|
||||
};
|
||||
|
||||
pub mod roles_controller;
|
||||
@@ -10,11 +10,6 @@ pub mod roles_repository;
|
||||
pub mod roles_schema;
|
||||
pub mod roles_service;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod roles_controller_test;
|
||||
#[cfg(test)]
|
||||
pub mod roles_repository_test;
|
||||
|
||||
pub use roles_controller::*;
|
||||
pub use roles_dto::*;
|
||||
pub use roles_enum::*;
|
||||
@@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "tests"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
imphnen-libs = { version = "0.1.0", path = "../imphnen-libs" }
|
||||
imphnen-utils = { version = "0.1.0", path = "../imphnen-utils" }
|
||||
imphnen-entities = { version = "0.1.0", path = "../imphnen-entities" }
|
||||
imphnen-iam-service = { version = "0.1.0", path = "../imphnen-iam-service" }
|
||||
axum.workspace = true
|
||||
axum-test.workspace = true
|
||||
chrono.workspace = true
|
||||
surrealdb.workspace = true
|
||||
tokio.workspace = true
|
||||
serde_json.workspace = true
|
||||
+16
-15
@@ -1,8 +1,9 @@
|
||||
use crate::{
|
||||
apps::v1::auth::auth_router, create_mock_app_state, create_test_user,
|
||||
encode_refresh_token, AuthOtpSchema, OtpManager, ResourceEnum, RolesRepository,
|
||||
AuthOtpSchema, AuthRepository, OtpManager, ResourceEnum, RolesRepository,
|
||||
UsersRepository, auth::auth_router, create_mock_app_state, create_test_user,
|
||||
encode_refresh_token,
|
||||
};
|
||||
use axum::{http::StatusCode, Extension};
|
||||
use axum::{Extension, http::StatusCode};
|
||||
use axum_test::TestServer;
|
||||
use serde_json::json;
|
||||
use surrealdb::Uuid;
|
||||
@@ -31,7 +32,7 @@ async fn test_login_should_fail_with_wrong_password() {
|
||||
.nest("/v1/auth", auth_router())
|
||||
.layer(Extension(state.clone()));
|
||||
let server = TestServer::new(app).unwrap();
|
||||
let repo = crate::apps::v1::users::UsersRepository::new(&state);
|
||||
let repo = UsersRepository::new(&state);
|
||||
let role_repo = RolesRepository::new(&state);
|
||||
let role_id = role_repo
|
||||
.query_role_by_name("Student".to_string())
|
||||
@@ -58,7 +59,7 @@ async fn test_login_should_fail_if_user_not_active() {
|
||||
.nest("/v1/auth", auth_router())
|
||||
.layer(Extension(state.clone()));
|
||||
let server = TestServer::new(app).unwrap();
|
||||
let repo = crate::apps::v1::users::UsersRepository::new(&state);
|
||||
let repo = UsersRepository::new(&state);
|
||||
let role_repo = RolesRepository::new(&state);
|
||||
let role_id = role_repo
|
||||
.query_role_by_name("Student".to_string())
|
||||
@@ -91,7 +92,7 @@ async fn test_login_should_succeed() {
|
||||
.nest("/v1/auth", auth_router())
|
||||
.layer(Extension(state.clone()));
|
||||
let server = TestServer::new(app).unwrap();
|
||||
let repo = crate::apps::v1::users::UsersRepository::new(&state);
|
||||
let repo = UsersRepository::new(&state);
|
||||
let role_repo = RolesRepository::new(&state);
|
||||
let role_id = role_repo
|
||||
.query_role_by_name("Student".to_string())
|
||||
@@ -183,7 +184,7 @@ async fn test_register_should_fail_if_email_already_taken() {
|
||||
.nest("/v1/auth", auth_router())
|
||||
.layer(Extension(state.clone()));
|
||||
let server = TestServer::new(app).unwrap();
|
||||
let repo = crate::apps::v1::users::UsersRepository::new(&state);
|
||||
let repo = UsersRepository::new(&state);
|
||||
let role_repo = RolesRepository::new(&state);
|
||||
let role_id = role_repo
|
||||
.query_role_by_name("Student".to_string())
|
||||
@@ -353,7 +354,7 @@ async fn test_forgot_password_should_succeed() {
|
||||
let mut user =
|
||||
create_test_user("forgot@example.com", "Forgot User", true, &role_id);
|
||||
user.password = crate::hash_password("secret").unwrap();
|
||||
let user_repo = crate::apps::v1::users::UsersRepository::new(&state);
|
||||
let user_repo = UsersRepository::new(&state);
|
||||
user_repo.query_create_user(user).await.unwrap();
|
||||
let payload = json!({ "email": "forgot@example.com" });
|
||||
let res = server.post("/v1/auth/forgot").json(&payload).await;
|
||||
@@ -463,8 +464,8 @@ async fn test_verify_email_should_succeed() {
|
||||
.id;
|
||||
let user = create_test_user("verify@example.com", "Verify User", false, &role_id);
|
||||
let otp = OtpManager::generate_otp();
|
||||
let user_repo = crate::apps::v1::users::UsersRepository::new(&state);
|
||||
let auth_repo = crate::apps::v1::auth::AuthRepository::new(&state);
|
||||
let user_repo = UsersRepository::new(&state);
|
||||
let auth_repo = AuthRepository::new(&state);
|
||||
user_repo.query_create_user(user.clone()).await.unwrap();
|
||||
auth_repo
|
||||
.query_store_otp(user.email.clone(), otp)
|
||||
@@ -497,8 +498,8 @@ async fn test_verify_email_should_fail_with_wrong_otp() {
|
||||
.id;
|
||||
let user = create_test_user("wrongotp@example.com", "Wrong OTP", false, &role_id);
|
||||
let otp = OtpManager::generate_otp();
|
||||
let user_repo = crate::apps::v1::users::UsersRepository::new(&state);
|
||||
let auth_repo = crate::apps::v1::auth::AuthRepository::new(&state);
|
||||
let user_repo = UsersRepository::new(&state);
|
||||
let auth_repo = AuthRepository::new(&state);
|
||||
user_repo.query_create_user(user.clone()).await.unwrap();
|
||||
auth_repo
|
||||
.query_store_otp(user.email.clone(), otp)
|
||||
@@ -530,10 +531,10 @@ async fn test_verify_email_should_fail_if_otp_expired() {
|
||||
.unwrap()
|
||||
.id;
|
||||
let user = create_test_user("expired@example.com", "Expired OTP", false, &role_id);
|
||||
let user_repo = crate::apps::v1::users::UsersRepository::new(&state);
|
||||
let user_repo = UsersRepository::new(&state);
|
||||
user_repo.query_create_user(user.clone()).await.unwrap();
|
||||
use chrono::{Duration, Utc};
|
||||
let expired_otp = crate::apps::v1::auth::AuthOtpSchema {
|
||||
let expired_otp = AuthOtpSchema {
|
||||
otp: 123456,
|
||||
expires_at: Utc::now() - Duration::minutes(1),
|
||||
};
|
||||
@@ -576,7 +577,7 @@ async fn test_new_password_should_succeed() {
|
||||
)
|
||||
.unwrap();
|
||||
let email = "resetme@example.com";
|
||||
let repo = crate::apps::v1::users::UsersRepository::new(&state);
|
||||
let repo = UsersRepository::new(&state);
|
||||
let role_repo = RolesRepository::new(&state);
|
||||
let role_id = role_repo
|
||||
.query_role_by_name("Student".to_string())
|
||||
@@ -0,0 +1,4 @@
|
||||
#[cfg(test)]
|
||||
pub mod auth_controller_test;
|
||||
#[cfg(test)]
|
||||
pub mod auth_repository_test;
|
||||
@@ -0,0 +1,4 @@
|
||||
pub mod auth;
|
||||
pub mod permissions;
|
||||
pub mod roles;
|
||||
pub mod users;
|
||||
@@ -0,0 +1,4 @@
|
||||
#[cfg(test)]
|
||||
pub mod permissions_controller_test;
|
||||
#[cfg(test)]
|
||||
pub mod permissions_repository_test;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
apps::v1::permissions::{PermissionsRepository, PermissionsSchema},
|
||||
create_mock_app_state,
|
||||
permissions::{PermissionsRepository, PermissionsSchema},
|
||||
};
|
||||
use chrono::Utc;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#[cfg(test)]
|
||||
pub mod roles_controller_test;
|
||||
#[cfg(test)]
|
||||
pub mod roles_repository_test;
|
||||
+11
-13
@@ -1,18 +1,16 @@
|
||||
use crate::{
|
||||
apps::v1::{
|
||||
permissions::{
|
||||
permissions_repository::PermissionsRepository,
|
||||
permissions_schema::PermissionsSchema,
|
||||
},
|
||||
roles::{
|
||||
roles_dto::{RolesRequestCreateDto, RolesRequestUpdateDto},
|
||||
roles_repository::RolesRepository,
|
||||
},
|
||||
ResourceEnum, create_mock_app_state, get_iso_date, make_thing,
|
||||
permissions::{
|
||||
permissions_repository::PermissionsRepository,
|
||||
permissions_schema::PermissionsSchema,
|
||||
},
|
||||
roles::{
|
||||
roles_dto::{RolesRequestCreateDto, RolesRequestUpdateDto},
|
||||
roles_repository::RolesRepository,
|
||||
},
|
||||
create_mock_app_state, get_iso_date, make_thing, ResourceEnum,
|
||||
};
|
||||
use surrealdb::sql::Thing;
|
||||
use surrealdb::Uuid;
|
||||
use surrealdb::sql::Thing;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_query_create_role_should_succeed() {
|
||||
@@ -133,8 +131,8 @@ async fn test_query_delete_role_should_soft_delete() {
|
||||
assert!(deleted.is_err());
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn test_query_update_role_should_fallback_to_existing_permissions_if_none_provided(
|
||||
) {
|
||||
async fn test_query_update_role_should_fallback_to_existing_permissions_if_none_provided()
|
||||
{
|
||||
let state = create_mock_app_state().await;
|
||||
let repo = RolesRepository::new(&state);
|
||||
let perm_repo = PermissionsRepository::new(&state);
|
||||
@@ -0,0 +1,4 @@
|
||||
#[cfg(test)]
|
||||
pub mod users_controller_test;
|
||||
#[cfg(test)]
|
||||
pub mod users_repository_test;
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
use crate::{
|
||||
apps::v1::users_router, create_mock_app_state, RolesEnum, RolesRepository,
|
||||
UsersActiveInactiveRequestDto, UsersCreateRequestDto, UsersRepository,
|
||||
UsersUpdateRequestDto,
|
||||
RolesEnum, RolesRepository, UsersActiveInactiveRequestDto, UsersCreateRequestDto,
|
||||
UsersRepository, UsersUpdateRequestDto, users_router,
|
||||
};
|
||||
use axum::{http::StatusCode, Extension};
|
||||
use axum::{Extension, http::StatusCode};
|
||||
use axum_test::TestServer;
|
||||
use imphnen_utils::create_mock_app_state;
|
||||
use surrealdb::Uuid;
|
||||
|
||||
#[tokio::test]
|
||||
@@ -0,0 +1,6 @@
|
||||
pub use imphnen_entities::*;
|
||||
pub use imphnen_iam_service::*;
|
||||
pub use imphnen_utils::*;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod iam_service;
|
||||
Reference in New Issue
Block a user