feat: apply env
This commit is contained in:
+6
-1
@@ -1,4 +1,9 @@
|
||||
PORT=
|
||||
DATABASE_URL=
|
||||
SURREALDB_URL=
|
||||
SURREALDB_USERNAME=
|
||||
SURREALDB_PASSWORD=
|
||||
SURREALDB_NAMESPACE=
|
||||
SURREALDB_DBNAME=
|
||||
REDISDB_URL=
|
||||
ACCESS_TOKEN_SECRET=
|
||||
REFRESH_TOKEN_SECRET=
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
function Set-TempEnvFromDotEnv {
|
||||
param (
|
||||
[string]$envFilePath
|
||||
)
|
||||
|
||||
if (-Not (Test-Path $envFilePath)) {
|
||||
Write-Error "The .env file at path '$envFilePath' does not exist."
|
||||
return
|
||||
}
|
||||
|
||||
$envContent = Get-Content $envFilePath
|
||||
|
||||
foreach ($line in $envContent) {
|
||||
$trimmedLine = $line.Trim()
|
||||
|
||||
if (-Not [string]::IsNullOrWhiteSpace($trimmedLine) -and -Not $trimmedLine.StartsWith("#")) {
|
||||
$keyValue = $trimmedLine -split "=", 2
|
||||
if ($keyValue.Length -eq 2) {
|
||||
$key = $keyValue[0].Trim()
|
||||
$value = $keyValue[1].Trim()
|
||||
[System.Environment]::SetEnvironmentVariable($key, $value, [System.EnvironmentVariableTarget]::Process)
|
||||
Write-Host "Set temporary environment variable: $key=$value"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "All environment variables from '$envFilePath' have been set temporarily."
|
||||
}
|
||||
|
||||
Set-TempEnvFromDotEnv -envFilePath ".env"
|
||||
@@ -1,9 +1,6 @@
|
||||
use crate::{common_response, decode_access_token, AppState};
|
||||
use crate::{common_response, extract_email, AppState};
|
||||
use axum::{
|
||||
extract::Request,
|
||||
http::{header::AUTHORIZATION, StatusCode},
|
||||
middleware::Next,
|
||||
response::Response,
|
||||
extract::Request, http::StatusCode, middleware::Next, response::Response,
|
||||
Extension,
|
||||
};
|
||||
use std::convert::Infallible;
|
||||
@@ -15,34 +12,22 @@ pub async fn auth_middleware(
|
||||
mut req: Request,
|
||||
next: Next,
|
||||
) -> Result<Response, Infallible> {
|
||||
let auth_header = match req.headers().get(AUTHORIZATION) {
|
||||
Some(h) => h.to_str().unwrap_or_default(),
|
||||
let headers = req.headers();
|
||||
|
||||
let email = match extract_email(headers) {
|
||||
Some(email) => email,
|
||||
None => {
|
||||
return Ok(common_response(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
"You are not authorized",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let token = auth_header.strip_prefix("Bearer ").unwrap_or("");
|
||||
|
||||
let token_data = match decode_access_token(token) {
|
||||
Ok(data) => data,
|
||||
Err(_) => {
|
||||
return Ok(common_response(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
&format!("Invalid or expired token"),
|
||||
"Invalid or expired token",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let repository = AuthRepository::new(&state);
|
||||
|
||||
let user: Option<AuthQueryByEmailResponse> = match repository
|
||||
.query_user_by_email(token_data.claims.sub.clone())
|
||||
.await
|
||||
{
|
||||
let user: Option<AuthQueryByEmailResponse> =
|
||||
match repository.query_user_by_email(email).await {
|
||||
Ok(user) => Some(user),
|
||||
Err(err) => {
|
||||
return Ok(common_response(
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
use super::{GachaRequestDto, GachaService};
|
||||
use super::{GachaClaimRequestDto, GachaService};
|
||||
use crate::{v1::GachaCreateItemRequestDto, AppState, MessageResponseDto};
|
||||
use axum::{response::IntoResponse, Extension, Json};
|
||||
use axum::{http::HeaderMap, response::IntoResponse, Extension, Json};
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/v1/gacha/create",
|
||||
request_body = GachaRequestDto,
|
||||
path = "/v1/gacha/create/claims",
|
||||
request_body = GachaClaimRequestDto,
|
||||
responses(
|
||||
(status = 200, description = "Create gacha successful", body = MessageResponseDto),
|
||||
(status = 401, description = "Create gacha failed", body = MessageResponseDto)
|
||||
(status = 200, description = "Create gacha claims successful", body = MessageResponseDto),
|
||||
(status = 401, description = "Create gacha claims failed", body = MessageResponseDto)
|
||||
),
|
||||
tag = "Gacha"
|
||||
)]
|
||||
pub async fn post_create_gacha(
|
||||
pub async fn post_create_gacha_claims(
|
||||
header: HeaderMap,
|
||||
Extension(state): Extension<AppState>,
|
||||
Json(payload): Json<GachaRequestDto>,
|
||||
Json(payload): Json<GachaClaimRequestDto>,
|
||||
) -> impl IntoResponse {
|
||||
GachaService::mutation_create_gacha(payload, &state).await
|
||||
GachaService::mutation_create_gacha_claims(payload, &state, header).await
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
|
||||
@@ -4,9 +4,7 @@ use utoipa::ToSchema;
|
||||
use crate::v1::UsersItemDto;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct GachaRequestDto {
|
||||
pub email: String,
|
||||
pub fullname: String,
|
||||
pub struct GachaClaimRequestDto {
|
||||
pub transaction_number: String,
|
||||
}
|
||||
|
||||
@@ -16,6 +14,12 @@ pub struct GachaCreateItemRequestDto {
|
||||
pub item_image: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct GachaCreateRollRequestDto {
|
||||
pub item_id: String,
|
||||
pub weight: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct GachaItemResponseDto {
|
||||
pub item_name: String,
|
||||
@@ -23,7 +27,7 @@ pub struct GachaItemResponseDto {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct GachaResponseDto {
|
||||
pub struct GachaClaimResponseDto {
|
||||
pub transaction_number: String,
|
||||
pub user: UsersItemDto,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::{
|
||||
GachaCreateItemRequestDto, GachaItemSchema, GachaRequestDto, GachaResponseDto,
|
||||
GachaSchema,
|
||||
GachaClaimRequestDto, GachaClaimResponseDto, GachaCreateItemRequestDto,
|
||||
GachaItemSchema, GachaSchema,
|
||||
};
|
||||
use crate::{v1::AuthRepository, AppState, ResourceEnum};
|
||||
use anyhow::{bail, Result};
|
||||
@@ -18,7 +18,7 @@ impl<'a> GachaRepository<'a> {
|
||||
pub async fn query_gacha_by_transaction_number(
|
||||
&self,
|
||||
transaction_number: String,
|
||||
) -> Result<GachaResponseDto> {
|
||||
) -> Result<GachaClaimResponseDto> {
|
||||
let db = &self.state.surrealdb;
|
||||
|
||||
let result = db
|
||||
@@ -31,13 +31,15 @@ impl<'a> GachaRepository<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn query_create_gacha(&self, data: GachaRequestDto) -> Result<String> {
|
||||
pub async fn query_create_gacha_claims(
|
||||
&self,
|
||||
data: GachaClaimRequestDto,
|
||||
email: String,
|
||||
) -> Result<String> {
|
||||
let auth_repository = AuthRepository::new(self.state);
|
||||
let db = &self.state.surrealdb;
|
||||
|
||||
let user = auth_repository
|
||||
.query_user_by_email(data.email.clone())
|
||||
.await?;
|
||||
let user = auth_repository.query_user_by_email(email).await?;
|
||||
|
||||
let user_thing =
|
||||
Thing::from((ResourceEnum::Users.to_string(), Id::String(user.email)));
|
||||
@@ -54,8 +56,8 @@ impl<'a> GachaRepository<'a> {
|
||||
.await?;
|
||||
|
||||
match record {
|
||||
Some(_) => Ok("Gacha successfully created".to_string()),
|
||||
None => bail!("Failed to create gacha record"),
|
||||
Some(_) => Ok("Gacha claims successfully created".to_string()),
|
||||
None => bail!("Failed to create gacha claims"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,4 +80,24 @@ impl<'a> GachaRepository<'a> {
|
||||
None => bail!("Failed to create gacha item record"),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn query_create_gacha_roll(
|
||||
&self,
|
||||
data: GachaCreateItemRequestDto,
|
||||
) -> Result<String> {
|
||||
let db = &self.state.surrealdb;
|
||||
|
||||
let record: Option<GachaItemSchema> = db
|
||||
.create((ResourceEnum::Gacha.to_string(), data.item_name.clone()))
|
||||
.content(GachaItemSchema {
|
||||
item_name: data.item_name.clone(),
|
||||
item_image: data.item_image.clone(),
|
||||
})
|
||||
.await?;
|
||||
|
||||
match record {
|
||||
Some(_) => Ok("Gacha item successfully created".to_string()),
|
||||
None => bail!("Failed to create gacha item record"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,31 @@
|
||||
use super::{GachaCreateItemRequestDto, GachaRepository, GachaRequestDto};
|
||||
use crate::{common_response, AppState};
|
||||
use axum::{http::StatusCode, response::Response};
|
||||
use super::{GachaClaimRequestDto, GachaCreateItemRequestDto, GachaRepository};
|
||||
use crate::{common_response, extract_email, AppState};
|
||||
use axum::{
|
||||
http::{HeaderMap, StatusCode},
|
||||
response::Response,
|
||||
};
|
||||
|
||||
pub struct GachaService;
|
||||
|
||||
impl GachaService {
|
||||
pub async fn mutation_create_gacha(
|
||||
payload: GachaRequestDto,
|
||||
pub async fn mutation_create_gacha_claims(
|
||||
payload: GachaClaimRequestDto,
|
||||
state: &AppState,
|
||||
header: HeaderMap,
|
||||
) -> Response {
|
||||
let repository = GachaRepository::new(state);
|
||||
|
||||
match repository.query_create_gacha(payload).await {
|
||||
let email = match extract_email(&header) {
|
||||
Some(email) => email,
|
||||
None => {
|
||||
return common_response(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
"Invalid or expired token",
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
match repository.query_create_gacha_claims(payload, email).await {
|
||||
Ok(msg) => common_response(StatusCode::CREATED, &msg),
|
||||
Err(err) => common_response(StatusCode::BAD_REQUEST, &err.to_string()),
|
||||
}
|
||||
|
||||
@@ -13,7 +13,10 @@ pub use gacha_service::*;
|
||||
|
||||
pub fn gacha_router() -> Router {
|
||||
Router::new()
|
||||
.route("/create", post(gacha_controller::post_create_gacha))
|
||||
.route(
|
||||
"/create/claims",
|
||||
post(gacha_controller::post_create_gacha_claims),
|
||||
)
|
||||
.route(
|
||||
"/create/item",
|
||||
post(gacha_controller::post_create_gacha_item),
|
||||
|
||||
+36
-28
@@ -4,14 +4,16 @@ pub struct Env {
|
||||
pub port: u16,
|
||||
pub access_token_secret: String,
|
||||
pub refresh_token_secret: String,
|
||||
pub database_url: String,
|
||||
pub database_schema: String,
|
||||
pub surrealdb_url: String,
|
||||
pub surrealdb_username: String,
|
||||
pub surrealdb_password: String,
|
||||
pub surrealdb_namespace: String,
|
||||
pub surrealdb_dbname: String,
|
||||
pub smtp_email: String,
|
||||
pub smtp_password: String,
|
||||
pub smtp_name: String,
|
||||
pub smpt_host: String,
|
||||
pub redis_hostname: String,
|
||||
pub redis_port: u16,
|
||||
pub smtp_host: String,
|
||||
pub redisdb_url: String,
|
||||
pub fe_url: String,
|
||||
pub rust_env: String,
|
||||
pub minio_endpoint: String,
|
||||
@@ -24,39 +26,45 @@ impl Env {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
port: env::var("PORT")
|
||||
.unwrap_or("3000".to_string())
|
||||
.unwrap_or_else(|_| "3000".to_string())
|
||||
.parse()
|
||||
.unwrap_or(3000),
|
||||
redis_port: env::var("REDIS_PORT")
|
||||
.unwrap_or("5436".to_string())
|
||||
.parse()
|
||||
.unwrap_or(5436),
|
||||
access_token_secret: env::var("ACCESS_TOKEN_SECRET")
|
||||
.unwrap_or("default_access_secret".to_string()),
|
||||
.unwrap_or_else(|_| "default_access_secret".to_string()),
|
||||
refresh_token_secret: env::var("REFRESH_TOKEN_SECRET")
|
||||
.unwrap_or("default_refresh_secret".to_string()),
|
||||
database_url: env::var("DATABASE_URL")
|
||||
.unwrap_or("postgres://localhost".to_string()),
|
||||
database_schema: env::var("DATABASE_SCHEMA")
|
||||
.unwrap_or("public".to_string()),
|
||||
.unwrap_or_else(|_| "default_refresh_secret".to_string()),
|
||||
surrealdb_url: env::var("SURREALDB_URL")
|
||||
.unwrap_or_else(|_| "http://localhost:8000".to_string()),
|
||||
surrealdb_username: env::var("SURREALDB_USERNAME")
|
||||
.unwrap_or_else(|_| "root".to_string()),
|
||||
surrealdb_password: env::var("SURREALDB_PASSWORD")
|
||||
.unwrap_or_else(|_| "password".to_string()),
|
||||
surrealdb_namespace: env::var("SURREALDB_NAMESPACE")
|
||||
.unwrap_or_else(|_| "namespace".to_string()),
|
||||
surrealdb_dbname: env::var("SURREALDB_DBNAME")
|
||||
.unwrap_or_else(|_| "database".to_string()),
|
||||
smtp_email: env::var("SMTP_EMAIL")
|
||||
.unwrap_or("no-reply@example.com".to_string()),
|
||||
.unwrap_or_else(|_| "no-reply@example.com".to_string()),
|
||||
smtp_password: env::var("SMTP_PASSWORD")
|
||||
.unwrap_or("default_smtp_password".to_string()),
|
||||
smtp_name: env::var("SMTP_NAME").unwrap_or("MyApp SMTP".to_string()),
|
||||
smpt_host: env::var("SMPT_HOST").unwrap_or("smpt.gmail.com".to_string()),
|
||||
redis_hostname: env::var("REDIS_HOSTNAME")
|
||||
.unwrap_or("localhost".to_string()),
|
||||
fe_url: env::var("FE_URL").unwrap_or("http://localhost".to_string()),
|
||||
rust_env: env::var("RUST_ENV").unwrap_or("development".to_string()),
|
||||
.unwrap_or_else(|_| "default_smtp_password".to_string()),
|
||||
smtp_name: env::var("SMTP_NAME")
|
||||
.unwrap_or_else(|_| "MyApp SMTP".to_string()),
|
||||
smtp_host: env::var("SMTP_HOST")
|
||||
.unwrap_or_else(|_| "smtp.gmail.com".to_string()),
|
||||
redisdb_url: env::var("REDISDB_URL")
|
||||
.unwrap_or_else(|_| "localhost".to_string()),
|
||||
fe_url: env::var("FE_URL")
|
||||
.unwrap_or_else(|_| "http://localhost".to_string()),
|
||||
rust_env: env::var("RUST_ENV")
|
||||
.unwrap_or_else(|_| "development".to_string()),
|
||||
minio_endpoint: env::var("MINIO_ENDPOINT")
|
||||
.unwrap_or("http://localhost:9000".to_string()),
|
||||
.unwrap_or_else(|_| "http://localhost:9000".to_string()),
|
||||
minio_bucket_name: env::var("MINIO_BUCKET_NAME")
|
||||
.unwrap_or("default_bucket".to_string()),
|
||||
.unwrap_or_else(|_| "default_bucket".to_string()),
|
||||
minio_access_key: env::var("MINIO_ACCESS_KEY")
|
||||
.unwrap_or("minio_access".to_string()),
|
||||
.unwrap_or_else(|_| "minio_access".to_string()),
|
||||
minio_secret_key: env::var("MINIO_SECRET_KEY")
|
||||
.unwrap_or("minio_secret".to_string()),
|
||||
.unwrap_or_else(|_| "minio_secret".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ pub fn send_email(
|
||||
body: &str,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let env = Env::new();
|
||||
let host = env.smpt_host;
|
||||
let host = env.smtp_host;
|
||||
let sender_email = env.smtp_email;
|
||||
let sender_name = env.smtp_name;
|
||||
let sender_password = env.smtp_password;
|
||||
|
||||
@@ -7,8 +7,7 @@ pub use key::*;
|
||||
|
||||
pub async fn redisdb_init() -> RedisResult<Client> {
|
||||
let env = Env::new();
|
||||
let host_name = env.redis_hostname;
|
||||
let url = format!("redis://{}", host_name);
|
||||
let url = format!("redis://{}", env.redisdb_url);
|
||||
let client = Client::open(url)?;
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
use super::Env;
|
||||
use crate::SurrealClient;
|
||||
use surrealdb::engine::remote::http::{Client, Http};
|
||||
use surrealdb::opt::auth::Root;
|
||||
use surrealdb::{Result, Surreal};
|
||||
|
||||
pub mod resource;
|
||||
pub use resource::*;
|
||||
|
||||
pub async fn surrealdb_init() -> Result<SurrealClient> {
|
||||
let env = Env::new();
|
||||
let db = Surreal::<Client>::init();
|
||||
db.connect::<Http>("localhost:8000").await?;
|
||||
db.signin(surrealdb::opt::auth::Root {
|
||||
username: "root",
|
||||
password: "root",
|
||||
db.connect::<Http>(env.surrealdb_url).await?;
|
||||
db.signin(Root {
|
||||
username: &env.surrealdb_username,
|
||||
password: &env.surrealdb_password,
|
||||
})
|
||||
.await?;
|
||||
db.use_ns("test").use_db("test").await?;
|
||||
db.use_ns(env.surrealdb_namespace)
|
||||
.use_db(env.surrealdb_dbname)
|
||||
.await?;
|
||||
Ok(db)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
use crate::decode_access_token;
|
||||
use axum::http::{header::AUTHORIZATION, HeaderMap};
|
||||
|
||||
pub fn extract_email(headers: &HeaderMap) -> Option<String> {
|
||||
let auth_header = headers.get(AUTHORIZATION)?.to_str().ok()?;
|
||||
let token = auth_header.strip_prefix("Bearer ")?;
|
||||
let token_data = decode_access_token(token).ok()?;
|
||||
Some(token_data.claims.sub)
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
pub mod extract_email;
|
||||
pub mod response_format;
|
||||
|
||||
pub use extract_email::*;
|
||||
pub use response_format::*;
|
||||
|
||||
Reference in New Issue
Block a user