Added Location and location ownership/rights to gamenight.

This commit is contained in:
2025-12-24 14:48:54 +01:00
parent 8a48119c80
commit ff88029a4b
57 changed files with 3034 additions and 995 deletions

View File

@@ -1,19 +1,14 @@
use actix_web::http::header::ContentType;
use actix_web::{get, post, web, HttpResponse, Responder};
use crate::models::{
login::Login, registration::Registration, token::Token, user::User, user_id::UserId,
};
use crate::request::{authorization::get_token, error::ApiError};
use actix_web::{get, http::header::ContentType, post, web, HttpResponse, Responder};
use gamenight_database::user::{count_users_with_email, count_users_with_username};
use gamenight_database::{DbPool, GetConnection};
use serde::{Deserialize, Serialize};
use serde_json;
use uuid::Uuid;
use validator::{Validate, ValidateArgs, ValidationError};
use crate::models::login::Login;
use crate::models::registration::Registration;
use crate::models::token::Token;
use crate::models::user::User;
use crate::models::user_id::UserId;
use crate::request::error::ApiError;
use crate::request::authorization::get_token;
use serde_json;
use gamenight_database::{DbPool, GetConnection};
use super::authorization::AuthUser;
@@ -21,7 +16,7 @@ impl From<Login> for gamenight_database::user::LoginUser {
fn from(val: Login) -> Self {
gamenight_database::user::LoginUser {
username: val.username,
password: val.password
password: val.password,
}
}
}
@@ -31,20 +26,22 @@ impl From<Registration> for gamenight_database::user::Register {
gamenight_database::user::Register {
email: val.email,
username: val.username,
password: val.password
password: val.password,
}
}
}
pub struct RegisterContext<'v_a> {
pub pool: &'v_a DbPool
pub pool: &'v_a DbPool,
}
pub fn unique_username(username: &String, context: &RegisterContext) -> Result<(), ValidationError> {
pub fn unique_username(
username: &String,
context: &RegisterContext,
) -> Result<(), ValidationError> {
let mut conn = context.pool.get_conn();
match count_users_with_username(&mut conn, username)
{
match count_users_with_username(&mut conn, username) {
Ok(0) => Ok(()),
Ok(_) => Err(ValidationError::new("User already exists")),
Err(_) => Err(ValidationError::new("Database error while validating user")),
@@ -54,28 +51,23 @@ pub fn unique_username(username: &String, context: &RegisterContext) -> Result<(
pub fn unique_email(email: &String, context: &RegisterContext) -> Result<(), ValidationError> {
let mut conn = context.pool.get_conn();
match count_users_with_email(&mut conn, email)
{
match count_users_with_email(&mut conn, email) {
Ok(0) => Ok(()),
Ok(_) => Err(ValidationError::new("email already exists")),
Err(_) => Err(ValidationError::new("Database error while validating email"))
Err(_) => Err(ValidationError::new(
"Database error while validating email",
)),
}
}
#[derive(Serialize, Deserialize, Clone, Validate)]
#[validate(context = RegisterContext::<'v_a>)]
pub struct ValidatableRegistration {
#[validate(
length(min = 1),
custom(function = "unique_username", use_context)
)]
#[validate(length(min = 1), custom(function = "unique_username", use_context))]
pub username: String,
#[validate(
email,
custom(function = "unique_email", use_context)
)]
#[validate(email, custom(function = "unique_email", use_context))]
pub email: String,
#[validate(length(min = 10), must_match(other = "password_repeat", ))]
#[validate(length(min = 10), must_match(other = "password_repeat",))]
pub password: String,
pub password_repeat: String,
}
@@ -86,13 +78,16 @@ impl From<Registration> for ValidatableRegistration {
username: value.username,
email: value.email,
password: value.password,
password_repeat: value.password_repeat
password_repeat: value.password_repeat,
}
}
}
#[get("/token")]
pub async fn login(pool: web::Data<DbPool>, login_data: web::Json<Login>) -> Result<impl Responder, ApiError> {
pub async fn login(
pool: web::Data<DbPool>,
login_data: web::Json<Login>,
) -> Result<impl Responder, ApiError> {
let data = login_data.into_inner();
if let Ok(Some(user)) = web::block(move || {
@@ -102,35 +97,45 @@ pub async fn login(pool: web::Data<DbPool>, login_data: web::Json<Login>) -> Res
.await?
{
let token = get_token(&user)?;
let response = Token{ jwt_token: Some(token) };
let response = Token {
jwt_token: Some(token),
};
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&response)?))
}
else {
Err(ApiError{status: 401, message: "User doesn't exist or password doesn't match".to_string()})
} else {
Err(ApiError {
status: 401,
message: "User doesn't exist or password doesn't match".to_string(),
})
}
}
#[post("/token")]
pub async fn refresh(user: AuthUser) -> Result<impl Responder, ApiError> {
let new_token = get_token(&user.0)?;
let response = Token{ jwt_token: Some(new_token) };
let response = Token {
jwt_token: Some(new_token),
};
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&response)?))
}
#[post("/user")]
pub async fn register(pool: web::Data<DbPool>, register_data: web::Json<Registration>) -> Result<impl Responder, ApiError> {
pub async fn register(
pool: web::Data<DbPool>,
register_data: web::Json<Registration>,
) -> Result<impl Responder, ApiError> {
web::block(move || -> Result<(), ApiError> {
let validatable_registration: ValidatableRegistration = register_data.clone().into();
validatable_registration.validate_with_args(&RegisterContext{pool: &pool})?;
validatable_registration.validate_with_args(&RegisterContext { pool: &pool })?;
let register_request = register_data.into_inner().into();
let mut conn = pool.get_conn();
gamenight_database::register(&mut conn, register_request)?;
Ok(())
}).await??;
})
.await??;
Ok(HttpResponse::Ok())
}
@@ -146,20 +151,42 @@ impl From<gamenight_database::user::User> for User {
}
#[get("/user")]
pub async fn get_user(pool: web::Data<DbPool>, _user: AuthUser, user_info: web::Json<UserId>) -> Result<impl Responder, ApiError> {
pub async fn get_user(
pool: web::Data<DbPool>,
_user: AuthUser,
user_info: web::Json<UserId>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let user = gamenight_database::user::get_user(&mut conn, Uuid::parse_str(&user_info.into_inner().user_id)?)?;
let user = gamenight_database::user::get_user(
&mut conn,
Uuid::parse_str(&user_info.into_inner().user_id)?,
)?;
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&user)?))
}
#[get("/user")]
pub async fn get_user_unauthenticated(_path: web::Path<UserId>) -> Result<impl Responder, ApiError> {
pub async fn get_user_unauthenticated(
_path: web::Path<UserId>,
) -> Result<impl Responder, ApiError> {
Ok(HttpResponse::Forbidden())
}
#[get("/users")]
pub async fn get_users(
pool: web::Data<DbPool>,
_user: AuthUser,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let users = gamenight_database::user::get_users(&mut conn)?;
let model: Vec<User> = users.into_iter().map(Into::into).collect();
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&model)?))
}