Compare commits
2
Commits
b87a6ff297
...
535d940857
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
535d940857 | ||
|
|
33df619c8d |
Generated
+4
@@ -2777,6 +2777,10 @@ dependencies = [
|
|||||||
"syn 2.0.117",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ticketsystem"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.47"
|
version = "0.3.47"
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "ticketsystem"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
readme = "README.md"
|
||||||
|
description = "A ticket system with backend and frontend components"
|
||||||
|
publish = false
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["backend", "frontend"]
|
members = ["backend", "frontend"]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|||||||
@@ -1,2 +1,8 @@
|
|||||||
# Ticketsystem
|
# Ticketsystem
|
||||||
|
|
||||||
|
A ticket system with backend and frontend components.
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
- **[Backend](../backend/index.html)** - The server-side API and business logic
|
||||||
|
- **[Frontend](../frontend/index.html)** - The client-side user interface
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use axum::{Json, http::StatusCode};
|
use axum::{Json, http::StatusCode};
|
||||||
use jsonwebtoken::{DecodingKey, EncodingKey, Header, Validation, decode, encode};
|
use jsonwebtoken::{DecodingKey, EncodingKey, Header, decode, encode};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::models::Claims;
|
use crate::models::Claims;
|
||||||
|
|||||||
@@ -12,12 +12,7 @@ use axum_extra::extract::CookieJar;
|
|||||||
use jsonwebtoken::DecodingKey;
|
use jsonwebtoken::DecodingKey;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::{
|
use crate::{AppState, cookie::jwt::decode_token, handlers::auth::filter_user, models::User};
|
||||||
AppState,
|
|
||||||
cookie::jwt::decode_token,
|
|
||||||
handlers::auth::filter_user,
|
|
||||||
models::{LoginScheme, User},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Axum middleware to validate a JWT token present in cookies or Authorization header.
|
/// Axum middleware to validate a JWT token present in cookies or Authorization header.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::{sync::Arc, usize};
|
use std::sync::Arc;
|
||||||
|
|
||||||
use argon2::{
|
use argon2::{
|
||||||
Argon2, PasswordHash, PasswordHasher, PasswordVerifier,
|
Argon2, PasswordHash, PasswordHasher, PasswordVerifier,
|
||||||
@@ -11,7 +11,6 @@ use axum::{
|
|||||||
response::IntoResponse,
|
response::IntoResponse,
|
||||||
};
|
};
|
||||||
use axum_extra::extract::cookie::{Cookie, SameSite};
|
use axum_extra::extract::cookie::{Cookie, SameSite};
|
||||||
use chrono::format;
|
|
||||||
use jsonwebtoken::{EncodingKey, Header};
|
use jsonwebtoken::{EncodingKey, Header};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
@@ -485,15 +484,16 @@ pub async fn update_user(
|
|||||||
pub async fn check_admin_exists(
|
pub async fn check_admin_exists(
|
||||||
State(data): State<Arc<AppState>>,
|
State(data): State<Arc<AppState>>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
|
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
|
||||||
let admin_count = sqlx::query_scalar::<_, i64>(r#"SELECT COUNT(*) FROM users WHERE is_admin = true"#)
|
let admin_count =
|
||||||
.fetch_one(&data.db)
|
sqlx::query_scalar::<_, i64>(r#"SELECT COUNT(*) FROM users WHERE is_admin = true"#)
|
||||||
.await
|
.fetch_one(&data.db)
|
||||||
.map_err(|e| {
|
.await
|
||||||
(
|
.map_err(|e| {
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
(
|
||||||
Json(json!({"status": "error", "message": format!("{:?}", e)})),
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
)
|
Json(json!({"status": "error", "message": format!("{:?}", e)})),
|
||||||
})?;
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
let has_admin = admin_count > 0;
|
let has_admin = admin_count > 0;
|
||||||
Ok(Json(json!({"has_admin": has_admin})))
|
Ok(Json(json!({"has_admin": has_admin})))
|
||||||
@@ -528,15 +528,16 @@ pub async fn setup_initial_admin(
|
|||||||
Json(request): Json<UserCreateScheme>,
|
Json(request): Json<UserCreateScheme>,
|
||||||
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
|
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
|
||||||
// Check if any admin already exists
|
// Check if any admin already exists
|
||||||
let admin_count = sqlx::query_scalar::<_, i64>(r#"SELECT COUNT(*) FROM users WHERE is_admin = true"#)
|
let admin_count =
|
||||||
.fetch_one(&data.db)
|
sqlx::query_scalar::<_, i64>(r#"SELECT COUNT(*) FROM users WHERE is_admin = true"#)
|
||||||
.await
|
.fetch_one(&data.db)
|
||||||
.map_err(|e| {
|
.await
|
||||||
(
|
.map_err(|e| {
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
(
|
||||||
Json(json!({"status": "error", "message": format!("{:?}", e)})),
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
)
|
Json(json!({"status": "error", "message": format!("{:?}", e)})),
|
||||||
})?;
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
if admin_count > 0 {
|
if admin_count > 0 {
|
||||||
return Err((
|
return Err((
|
||||||
@@ -580,7 +581,9 @@ pub async fn setup_initial_admin(
|
|||||||
Json(json!({"status": "error", "message": "Error creating admin user"})),
|
Json(json!({"status": "error", "message": "Error creating admin user"})),
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
Ok(Json(json!({"status": "success", "result": "Admin user created"})))
|
Ok(Json(
|
||||||
|
json!({"status": "success", "result": "Admin user created"}),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-11
@@ -1,5 +1,3 @@
|
|||||||
#![allow(unused_imports)]
|
|
||||||
|
|
||||||
/// Cookie and JWT authentication utilities
|
/// Cookie and JWT authentication utilities
|
||||||
mod cookie;
|
mod cookie;
|
||||||
/// Environment configuration loading
|
/// Environment configuration loading
|
||||||
@@ -13,18 +11,12 @@ mod router;
|
|||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use axum::{
|
use axum::http::{
|
||||||
Router,
|
HeaderValue, Method,
|
||||||
http::{
|
header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE},
|
||||||
HeaderValue, Method,
|
|
||||||
header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE},
|
|
||||||
},
|
|
||||||
routing,
|
|
||||||
};
|
};
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
use models::*;
|
|
||||||
use router::create_router;
|
use router::create_router;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use sqlx::{PgPool, postgres::PgPoolOptions};
|
use sqlx::{PgPool, postgres::PgPoolOptions};
|
||||||
use tower_http::cors::CorsLayer;
|
use tower_http::cors::CorsLayer;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
use std::fmt::Display;
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::{Decode, prelude::Type};
|
|
||||||
|
|
||||||
/// API response for a ticket with user information.
|
/// API response for a ticket with user information.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
#![doc = include_str!("../README.md")]
|
||||||
Reference in New Issue
Block a user