Converted the Api to a Restful api.

This commit is contained in:
2026-01-22 22:51:03 +01:00
parent 79ba1e1b44
commit 9d3c5afb07
50 changed files with 2194 additions and 1939 deletions

View File

@@ -1,60 +1,24 @@
use gamenight_database::owned_game::OwnedGame;
use crate::game::rename_game;
use crate::owned_game::own_game;
use crate::owned_game::owned_games;
use crate::owned_game::disown_game;
use gamenight_database::game::load_game;
use crate::game::insert_game;
use uuid::Uuid;
use crate::game::remove_game;
use actix_web::{delete, get, http::header::ContentType, post, web, HttpResponse, Responder};
use actix_web::{delete, get, http::header::ContentType, put, web, HttpResponse, Responder};
use gamenight_database::game::{load_game, remove_game, rename_game};
use gamenight_database::{
user::Role,
DbPool, GetConnection,
};
use uuid::Uuid;
use crate::{models, models::{
add_game_request_body::AddGameRequestBody, game::Game, game_id::GameId,
rename_game_request_body::RenameGameRequestBody, own_game_request_body::OwnGameRequestBody
use crate::{models::{
edit_game_request_body::EditGameRequestBody, game::Game
,
}, request::{authorization::AuthUser, error::ApiError}};
#[get("/games")]
pub async fn get_games(
pool: web::Data<DbPool>,
_user: AuthUser,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let games: Vec<gamenight_database::game::Game> = gamenight_database::games(&mut conn)?;
let model: Vec<Game> = games
.iter()
.map(|x| Game {
id: x.id.to_string(),
name: x.name.clone(),
})
.collect();
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&model)?))
}
impl From<AddGameRequestBody> for gamenight_database::game::Game {
fn from(value: AddGameRequestBody) -> Self {
Self {
id: Uuid::new_v4(),
name: value.name,
}
}
}
#[get("/game")]
#[get("/game/{game_id}")]
pub async fn get_game(
pool: web::Data<DbPool>,
_user: AuthUser,
game_id: web::Json<GameId>,
game_id: web::Path<Uuid>
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let db_game = load_game(&mut conn, Uuid::parse_str(&game_id.0.game_id)?)?;
let db_game = load_game(&mut conn, game_id.into_inner())?;
let model = Game {
id: db_game.id.to_string(),
@@ -66,106 +30,35 @@ pub async fn get_game(
.body(serde_json::to_string(&model)?))
}
#[post("/game")]
pub async fn post_game(
pool: web::Data<DbPool>,
_user: AuthUser,
game_data: web::Json<AddGameRequestBody>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let game = game_data.0.into();
insert_game(&mut conn, &game)?;
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&GameId{game_id: game.id.to_string()})?))
}
#[delete("/game")]
#[delete("/game/{game_id}")]
pub async fn delete_game(
pool: web::Data<DbPool>,
user: AuthUser,
game_id: web::Json<GameId>,
game_id: web::Path<Uuid>,
) -> Result<impl Responder, ApiError> {
if user.0.role != Role::Admin {
Ok(HttpResponse::Unauthorized())
} else {
let mut conn = pool.get_conn();
remove_game(&mut conn, Uuid::parse_str(&game_id.0.game_id)?)?;
remove_game(&mut conn, game_id.into_inner())?;
Ok(HttpResponse::Ok())
}
}
#[post("/rename_game")]
pub async fn post_rename_game(
#[put("/game/{gameId}")]
pub async fn put_game(
pool: web::Data<DbPool>,
_user: AuthUser,
game_data: web::Json<RenameGameRequestBody>,
game_id: web::Path<Uuid>,
edit_data: web::Json<EditGameRequestBody>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
rename_game(
&mut conn,
Uuid::parse_str(&game_data.0.id)?,
game_data.0.name,
game_id.into_inner(),
edit_data.name.clone(),
)?;
Ok(HttpResponse::Ok())
}
#[post("/own")]
pub async fn post_own_game(
pool: web::Data<DbPool>,
user: AuthUser,
own_data: web::Json<OwnGameRequestBody>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
own_game(
&mut conn,
OwnedGame {
user_id: user.0.id,
game_id: Uuid::parse_str(&own_data.game_id)?,
location_id: own_data.location_id.clone().map(|x| Uuid::parse_str(&x).unwrap()),
},
)?;
Ok(HttpResponse::Ok())
}
#[post("/disown")]
pub async fn post_disown_game(
pool: web::Data<DbPool>,
user: AuthUser,
game_id: web::Json<GameId>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
disown_game(
&mut conn,
OwnedGame {
user_id: user.0.id,
game_id: Uuid::parse_str(&game_id.0.game_id)?,
location_id: None
},
)?;
Ok(HttpResponse::Ok())
}
#[get("/owned_games")]
pub async fn get_owned_games(
pool: web::Data<DbPool>,
user: AuthUser,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let game_ids = owned_games(&mut conn, user.0.id)?;
let model = game_ids.iter().map(|(u, l)| models::owned_game::OwnedGame {
game_id: u.to_string(),
location_id: l.map(|x| x.to_string())
}).collect::<Vec<models::owned_game::OwnedGame>>();
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&model)?))
}

View File

@@ -0,0 +1,26 @@
use crate::request::authorization::AuthUser;
use crate::request::error::ApiError;
use actix_web::{delete, web, HttpResponse, Responder};
use gamenight_database::owned_game::{disown_game, OwnedGame};
use gamenight_database::{DbPool, GetConnection};
use uuid::Uuid;
#[delete("/game/{gameId}/owner/{ownerId}")]
pub async fn delete_game_owner(
pool: web::Data<DbPool>,
_user: AuthUser,
game_id: web::Path<Uuid>,
owner_id: web::Path<Uuid>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
disown_game(
&mut conn,
OwnedGame {
user_id: owner_id.into_inner(),
game_id: game_id.into_inner(),
location_id: None
},
)?;
Ok(HttpResponse::Ok())
}

View File

@@ -0,0 +1,27 @@
use actix_web::{post, web, HttpResponse, Responder};
use gamenight_database::{DbPool, GetConnection};
use gamenight_database::owned_game::{own_game, OwnedGame};
use uuid::Uuid;
use crate::models::game_id::GameId;
use crate::request::authorization::AuthUser;
use crate::request::error::ApiError;
#[post("/game/{gameId}/owned_games")]
pub async fn post_game_owners(
pool: web::Data<DbPool>,
_user: AuthUser,
game_id: web::Path<GameId>,
own_data: web::Json<OwnedGame>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
own_game(
&mut conn,
OwnedGame {
user_id: own_data.user_id,
game_id: Uuid::parse_str(&game_id.game_id)?,
location_id: own_data.location_id,
},
)?;
Ok(HttpResponse::Ok())
}

View File

@@ -0,0 +1,32 @@
use actix_web::{get, http::header::ContentType, web, HttpResponse, Responder};
use uuid::Uuid;
use gamenight_database::{gamenight, DbPool, GetConnection};
use crate::models::gamenight_id::GamenightId;
use crate::request::error::ApiError;
use crate::{
models::gamenight::Gamenight,
request::authorization::AuthUser,
};
#[get("/gamenight/{gamenightId}")]
pub async fn get_gamenight(
pool: web::Data<DbPool>,
_user: AuthUser,
path: web::Path<GamenightId>
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let gamenight = gamenight::get_gamenight(&mut conn, Uuid::parse_str(&path.gamenight_id)?)?;
let model = Gamenight {
id: gamenight.id.to_string(),
datetime: gamenight.datetime.to_rfc3339(),
location_id: gamenight.location_id.map(|x| x.to_string()),
name: gamenight.name,
owner_id: gamenight.owner_id.to_string(),
};
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&model)?))
}

View File

@@ -0,0 +1,28 @@
use actix_web::{delete, web, HttpResponse, Responder};
use gamenight_database::{DbPool, GetConnection};
use gamenight_database::gamenight_participants::GamenightParticipant;
use uuid::Uuid;
use crate::request::authorization::AuthUser;
use crate::request::error::ApiError;
#[delete("/gamenight/{gamenightId}/participant/{userId}")]
pub async fn delete_gamenight_participant(
pool: web::Data<DbPool>,
_user: AuthUser,
gamenight_id: web::Path<Uuid>,
user_id: web::Path<Uuid>
) -> Result<impl Responder, ApiError> {
web::block(move || -> Result<usize, ApiError> {
let mut conn = pool.get_conn();
let participant = GamenightParticipant {
gamenight_id: gamenight_id.into_inner(),
user_id: user_id.into_inner(),
};
let x = gamenight_database::gamenight_participants::delete_gamenight_participant(&mut conn, participant)?;
Ok(x)
})
.await??;
Ok(HttpResponse::Ok())
}

View File

@@ -0,0 +1,54 @@
use crate::models::participants::Participants;
use crate::models::user_id::UserId;
use crate::request::authorization::AuthUser;
use crate::request::error::ApiError;
use actix_web::http::header::ContentType;
use actix_web::{get, post, web, HttpResponse, Responder};
use gamenight_database::gamenight_participants::{insert_gamenight_participant, GamenightParticipant};
use gamenight_database::{DbPool, GetConnection};
use uuid::Uuid;
#[get("/gamenight/{gamenightId}/participants")]
pub async fn get_gamenight_participants(
pool: web::Data<DbPool>,
_user: AuthUser,
gamenight_id: web::Path<Uuid>
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let users = gamenight_database::get_participants(
&mut conn,
&gamenight_id.into_inner(),
)?
.iter()
.map(|x| x.to_string())
.collect();
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&Participants {
participants: users,
})?))
}
#[post("/gamenight/{gamenightId}/participants")]
pub async fn post_gamenight_participants(
pool: web::Data<DbPool>,
_user: AuthUser,
gamenight_id: web::Path<Uuid>,
user_id: web::Json<UserId>,
) -> Result<impl Responder, ApiError> {
web::block(move || -> Result<usize, ApiError> {
let mut conn = pool.get_conn();
Ok(insert_gamenight_participant(
&mut conn,
GamenightParticipant {
gamenight_id: gamenight_id.into_inner(),
user_id: Uuid::parse_str(&user_id.user_id)?,
},
)?)
})
.await??;
Ok(HttpResponse::Ok())
}

View File

@@ -1,17 +1,12 @@
use actix_web::{get, http::header::ContentType, post, web, HttpResponse, Responder};
use actix_web::{get, post, web, HttpResponse, Responder};
use actix_web::http::header::ContentType;
use chrono::{DateTime, ParseError};
use uuid::Uuid;
use gamenight_database::{gamenight, DbPool, GetConnection};
use uuid::Uuid;
use crate::models::add_gamenight_request_body::AddGamenightRequestBody;
use crate::models::gamenight::Gamenight;
use crate::request::authorization::AuthUser;
use crate::request::error::ApiError;
use crate::{
models::{
add_gamenight_request_body::AddGamenightRequestBody, gamenight::Gamenight,
get_gamenight_request_body::GetGamenightRequestBody,
},
request::authorization::AuthUser,
};
impl AddGamenightRequestBody {
pub fn into_with_user(&self, user: AuthUser) -> Result<gamenight::Gamenight, ParseError> {
@@ -25,14 +20,8 @@ impl AddGamenightRequestBody {
}
}
impl From<GetGamenightRequestBody> for Uuid {
fn from(value: GetGamenightRequestBody) -> Self {
Uuid::parse_str(value.id.unwrap().as_str()).unwrap()
}
}
#[get("/gamenights")]
pub async fn gamenights(
pub async fn get_gamenights(
pool: web::Data<DbPool>,
_user: AuthUser,
) -> Result<impl Responder, ApiError> {
@@ -54,8 +43,8 @@ pub async fn gamenights(
.body(serde_json::to_string(&model)?))
}
#[post("/gamenight")]
pub async fn gamenight_post(
#[post("/gamenights")]
pub async fn post_gamenights(
pool: web::Data<DbPool>,
user: AuthUser,
gamenight_data: web::Json<AddGamenightRequestBody>,
@@ -65,25 +54,4 @@ pub async fn gamenight_post(
gamenight::add_gamenight(&mut conn, gamenight_data.into_with_user(user)?)?;
Ok(HttpResponse::Ok())
}
#[get("/gamenight")]
pub async fn gamenight_get(
pool: web::Data<DbPool>,
_user: AuthUser,
gamenight_data: web::Json<GetGamenightRequestBody>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let gamenight = gamenight::get_gamenight(&mut conn, gamenight_data.into_inner().into())?;
let model = Gamenight {
id: gamenight.id.to_string(),
datetime: gamenight.datetime.to_rfc3339(),
location_id: gamenight.location_id.map(|x| x.to_string()),
name: gamenight.name,
owner_id: gamenight.owner_id.to_string(),
};
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&model)?))
}
}

View File

@@ -0,0 +1,54 @@
use actix_web::{get, post, web, HttpResponse, Responder};
use actix_web::http::header::ContentType;
use gamenight_database::{DbPool, GetConnection};
use gamenight_database::game::insert_game;
use uuid::Uuid;
use crate::models::add_game_request_body::AddGameRequestBody;
use crate::models::game::Game;
use crate::models::game_id::GameId;
use crate::request::authorization::AuthUser;
use crate::request::error::ApiError;
impl From<AddGameRequestBody> for gamenight_database::game::Game {
fn from(value: AddGameRequestBody) -> Self {
Self {
id: Uuid::new_v4(),
name: value.name,
}
}
}
#[get("/games")]
pub async fn get_games(
pool: web::Data<DbPool>,
_user: AuthUser,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let games: Vec<gamenight_database::game::Game> = gamenight_database::games(&mut conn)?;
let model: Vec<Game> = games
.iter()
.map(|x| Game {
id: x.id.to_string(),
name: x.name.clone(),
})
.collect();
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&model)?))
}
#[post("/games")]
pub async fn post_games(
pool: web::Data<DbPool>,
_user: AuthUser,
game_data: web::Json<AddGameRequestBody>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let game = game_data.0.into();
insert_game(&mut conn, &game)?;
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&GameId{game_id: game.id.to_string()})?))
}

View File

@@ -1,55 +0,0 @@
use actix_web::{post, web, HttpResponse, Responder};
use gamenight_database::{
gamenight_participants::{
delete_gamenight_participant, insert_gamenight_participant, GamenightParticipant,
},
DbPool, GetConnection,
};
use uuid::Uuid;
use crate::{
models::gamenight_id::GamenightId,
request::{authorization::AuthUser, error::ApiError},
};
#[post("/join")]
pub async fn post_join_gamenight(
pool: web::Data<DbPool>,
user: AuthUser,
gamenight_id: web::Json<GamenightId>,
) -> Result<impl Responder, ApiError> {
web::block(move || -> Result<usize, ApiError> {
let mut conn = pool.get_conn();
Ok(insert_gamenight_participant(
&mut conn,
GamenightParticipant {
gamenight_id: Uuid::parse_str(&gamenight_id.gamenight_id)?,
user_id: user.0.id,
},
)?)
})
.await??;
Ok(HttpResponse::Ok())
}
#[post("/leave")]
pub async fn post_leave_gamenight(
pool: web::Data<DbPool>,
user: AuthUser,
gamenight_id: web::Json<GamenightId>,
) -> Result<impl Responder, ApiError> {
web::block(move || -> Result<usize, ApiError> {
let mut conn = pool.get_conn();
let participant = GamenightParticipant {
gamenight_id: Uuid::parse_str(&gamenight_id.gamenight_id)?,
user_id: user.0.id,
};
let x = delete_gamenight_participant(&mut conn, participant)?;
Ok(x)
})
.await??;
Ok(HttpResponse::Ok())
}

View File

@@ -1,65 +1,28 @@
use actix_web::{get, http::header::ContentType, post, web, HttpResponse, Responder};
use gamenight_database::{
location::{insert_location, locations},
DbPool, GetConnection,
};
use crate::models::location::Location;
use crate::request::authorization::AuthUser;
use crate::request::error::ApiError;
use actix_web::http::header::ContentType;
use actix_web::{get, web, HttpResponse, Responder};
use gamenight_database::{DbPool, GetConnection};
use uuid::Uuid;
use crate::{
models::{
add_location_request_body::AddLocationRequestBody, location::Location,
location_id::LocationId,
},
request::{authorization::AuthUser, error::ApiError},
};
impl From<AddLocationRequestBody> for gamenight_database::location::Location {
fn from(value: AddLocationRequestBody) -> Self {
Self {
id: Uuid::new_v4(),
name: value.name,
address: value.address,
note: value.note,
}
}
}
#[get("/locations")]
#[get("/location/{locationId}")]
pub async fn get_locations(
pool: web::Data<DbPool>,
_user: AuthUser,
location_id: web::Path<Uuid>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let games: Vec<gamenight_database::location::Location> = locations(&mut conn)?;
let model: Vec<Location> = games
.iter()
.map(|x| Location {
id: x.id.to_string(),
name: x.name.clone(),
address: x.address.clone(),
note: x.note.clone(),
})
.collect();
let location = gamenight_database::location::load_location(&mut conn, location_id.into_inner())?;
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&model)?))
}
#[post("/location")]
pub async fn post_location(
pool: web::Data<DbPool>,
_user: AuthUser,
game_data: web::Json<AddLocationRequestBody>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let uuid = insert_location(&mut conn, game_data.0.into())?;
let model = LocationId {
location_id: uuid.to_string(),
let model = Location {
id: location.id.to_string(),
name: location.name.clone(),
note: location.note.clone(),
address: location.address.clone(),
};
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&model)?))
}
}

View File

@@ -0,0 +1,23 @@
use crate::request::authorization::AuthUser;
use crate::request::error::ApiError;
use actix_web::{delete, web, HttpResponse, Responder};
use gamenight_database::location_owner::{revoke_permission, LocationOwner};
use gamenight_database::{DbPool, GetConnection};
use uuid::Uuid;
#[delete("/location/{location_id}/authorized_users/{user_id}")]
pub async fn delete_location_authorized_user(
pool: web::Data<DbPool>,
_user: AuthUser,
location_id: web::Path<Uuid>,
user_id: web::Path<Uuid>
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
revoke_permission(&mut conn, LocationOwner {
user_id: user_id.into_inner(),
location_id: location_id.into_inner()
})?;
Ok(HttpResponse::Ok())
}

View File

@@ -0,0 +1,60 @@
use actix_web::{get, post, web, HttpResponse, Responder};
use actix_web::http::header::ContentType;
use gamenight_database::{DbPool, GetConnection};
use gamenight_database::location_owner::{grant_permission, location_permissions, LocationOwner};
use gamenight_database::user::Role;
use uuid::Uuid;
use crate::models::location_id::LocationId;
use crate::models::user_id::UserId;
use crate::request::authorization::AuthUser;
use crate::request::error::ApiError;
impl From<Uuid> for UserId {
fn from(uuid: Uuid) -> Self {
Self {
user_id: uuid.into(),
}
}
}
#[get("/location/{locationId}/authorized_users/")]
pub async fn get_location_authorized_users(
pool: web::Data<DbPool>,
_user: AuthUser,
location_id: web::Path<Uuid>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let permissions =
location_permissions(&mut conn, location_id.into_inner())?;
let model: Vec<UserId> = permissions.into_iter().map(Into::into).collect();
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&model)?))
}
#[post("/location/{locationId}/authorized_users/")]
pub async fn post_location_authorized_users(
pool: web::Data<DbPool>,
user: AuthUser,
location_id1: web::Path<LocationId>,
user_id: web::Json<UserId>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let location_uuid = Uuid::parse_str(&location_id1.location_id)?;
let user_uuid = Uuid::parse_str(&user_id.user_id)?;
let authorized = location_permissions(&mut conn, location_uuid)?;
if user.0.role != Role::Admin && !authorized.contains(&user.0.id) {
Ok(HttpResponse::Unauthorized())
} else {
grant_permission(&mut conn, LocationOwner {
location_id: location_uuid,
user_id: user_uuid,
})?;
Ok(HttpResponse::Ok())
}
}

View File

@@ -1,79 +0,0 @@
use actix_web::{get, http::header::ContentType, post, web, HttpResponse, Responder};
use gamenight_database::{
location_owner::{grant_permission, location_permissions, revoke_permission, LocationOwner},
user::Role,
DbPool, GetConnection,
};
use uuid::Uuid;
use crate::{
models::{
authorize_location_request_body::{
AuthorizeLocationRequestBody,
Op::{Grant, Revoke},
},
location_id::LocationId,
user_id::UserId,
},
request::{authorization::AuthUser, error::ApiError},
};
impl<'a> TryFrom<&'a AuthorizeLocationRequestBody> for LocationOwner {
type Error = ApiError;
fn try_from(value: &'a AuthorizeLocationRequestBody) -> Result<Self, Self::Error> {
Ok(LocationOwner {
location_id: Uuid::parse_str(&value.location_id)?,
user_id: Uuid::parse_str(&value.user_id)?,
})
}
}
#[post("/location_authorize")]
pub async fn post_location_authorize(
pool: web::Data<DbPool>,
user: AuthUser,
auth_data: web::Json<AuthorizeLocationRequestBody>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let inner_auth_data = &auth_data.into_inner();
let location_owner: LocationOwner = inner_auth_data.try_into()?;
let authorized = location_permissions(&mut conn, location_owner.location_id)?;
if user.0.role != Role::Admin && !authorized.contains(&user.0.id) {
Ok(HttpResponse::Unauthorized())
} else {
match inner_auth_data.op {
Grant => grant_permission(&mut conn, location_owner)?,
Revoke => revoke_permission(&mut conn, location_owner)?,
};
Ok(HttpResponse::Ok())
}
}
impl From<Uuid> for UserId {
fn from(value: Uuid) -> Self {
Self {
user_id: value.to_string(),
}
}
}
#[get("/authorized_location_user_ids")]
pub async fn get_authorized_location_user_ids(
pool: web::Data<DbPool>,
_user: AuthUser,
location_id: web::Json<LocationId>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let permissions =
location_permissions(&mut conn, Uuid::parse_str(&location_id.0.location_id)?)?;
let model: Vec<UserId> = permissions.into_iter().map(Into::into).collect();
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&model)?))
}

View File

@@ -0,0 +1,62 @@
use actix_web::{get, post, web, HttpResponse, Responder};
use actix_web::http::header::ContentType;
use gamenight_database::{DbPool, GetConnection};
use gamenight_database::location::{insert_location, locations};
use uuid::Uuid;
use crate::models::add_location_request_body::AddLocationRequestBody;
use crate::models::location::Location;
use crate::models::location_id::LocationId;
use crate::request::authorization::AuthUser;
use crate::request::error::ApiError;
impl From<AddLocationRequestBody> for gamenight_database::location::Location {
fn from(value: AddLocationRequestBody) -> Self {
Self {
id: Uuid::new_v4(),
name: value.name,
address: value.address,
note: value.note,
}
}
}
#[get("/locations")]
pub async fn get_locations(
pool: web::Data<DbPool>,
_user: AuthUser,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let games: Vec<gamenight_database::location::Location> = locations(&mut conn)?;
let model: Vec<Location> = games
.iter()
.map(|x| Location {
id: x.id.to_string(),
name: x.name.clone(),
address: x.address.clone(),
note: x.note.clone(),
})
.collect();
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&model)?))
}
#[post("/locations")]
pub async fn post_locations(
pool: web::Data<DbPool>,
_user: AuthUser,
game_data: web::Json<AddLocationRequestBody>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let uuid = insert_location(&mut conn, game_data.0.into())?;
let model = LocationId {
location_id: uuid.to_string(),
};
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&model)?))
}

View File

@@ -1,34 +1,20 @@
mod authorization;
mod error;
mod game;
mod gamenight_handlers;
mod join_gamenight;
mod location;
mod location_owner;
mod participant_handlers;
mod user_handlers;
pub use game::get_game;
pub use game::get_games;
pub use game::get_owned_games;
pub use game::post_disown_game;
pub use game::post_game;
pub use game::post_own_game;
pub use game::post_rename_game;
pub use game::delete_game;
pub use gamenight_handlers::gamenight_get;
pub use gamenight_handlers::gamenight_post;
pub use gamenight_handlers::gamenights;
pub use join_gamenight::post_join_gamenight;
pub use join_gamenight::post_leave_gamenight;
pub use location::get_locations;
pub use location::post_location;
pub use location_owner::get_authorized_location_user_ids;
pub use location_owner::post_location_authorize;
pub use participant_handlers::get_get_participants;
pub use user_handlers::get_user;
pub use user_handlers::get_user_unauthenticated;
pub use user_handlers::get_users;
pub use user_handlers::login;
pub use user_handlers::refresh;
pub use user_handlers::register;
pub mod token;
pub mod users;
pub mod user;
pub mod user_owned_games;
pub mod gamenights;
pub mod gamenight;
pub mod gamenight_participants;
pub mod gamenight_participant;
pub mod games;
pub mod game;
pub mod game_owners;
pub mod game_owner;
pub mod locations;
pub mod location;
pub mod location_authorized_users;
pub mod location_authorized_user;

View File

@@ -1,31 +0,0 @@
use actix_web::{get, http::header::ContentType, web, HttpResponse, Responder};
use gamenight_database::{DbPool, GetConnection};
use uuid::Uuid;
use crate::{
models::{gamenight_id::GamenightId, participants::Participants},
request::{authorization::AuthUser, error::ApiError},
};
#[get("/participants")]
pub async fn get_get_participants(
pool: web::Data<DbPool>,
_user: AuthUser,
gamenight_info: web::Json<GamenightId>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let users = gamenight_database::get_participants(
&mut conn,
&Uuid::parse_str(&gamenight_info.into_inner().gamenight_id)?,
)?
.iter()
.map(|x| x.to_string())
.collect();
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&Participants {
participants: users,
})?))
}

View File

@@ -0,0 +1,54 @@
use crate::models::login::Login;
use crate::models::token::Token;
use crate::request::authorization::{get_token, AuthUser};
use crate::request::error::ApiError;
use actix_web::http::header::ContentType;
use actix_web::{post, web, HttpResponse, Responder};
use gamenight_database::{DbPool, GetConnection};
impl From<Login> for gamenight_database::user::LoginUser {
fn from(val: Login) -> Self {
gamenight_database::user::LoginUser {
username: val.username,
password: val.password,
}
}
}
#[post("/token")]
pub async fn post_token(
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 || {
let mut conn = pool.get_conn();
gamenight_database::login(&mut conn, data.into())
})
.await?
{
let token = get_token(&user)?;
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(),
})
}
}
#[post("/refresh_token")]
pub async fn post_refresh_token(user: AuthUser) -> Result<impl Responder, ApiError> {
let new_token = get_token(&user.0)?;
let response = Token {
jwt_token: Some(new_token),
};
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&response)?))
}

View File

@@ -0,0 +1,37 @@
use crate::models::user::User;
use crate::request::error::ApiError;
use actix_web::{get, http::header::ContentType, web, HttpResponse, Responder};
use gamenight_database::{DbPool, GetConnection};
use serde_json;
use uuid::Uuid;
use super::authorization::AuthUser;
impl From<gamenight_database::user::User> for User {
fn from(value: gamenight_database::user::User) -> Self {
Self {
id: value.id.to_string(),
username: value.username,
email: None,
}
}
}
#[get("/user/{userId}")]
pub async fn get_user(
pool: web::Data<DbPool>,
_user: AuthUser,
user_id: web::Path<Uuid>,
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let user = gamenight_database::user::get_user(
&mut conn,
user_id.into_inner()
)?;
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&user)?))
}

View File

@@ -0,0 +1,28 @@
use actix_web::{get, web, HttpResponse, Responder};
use actix_web::http::header::ContentType;
use gamenight_database::{DbPool, GetConnection};
use gamenight_database::owned_game::owned_games;
use uuid::Uuid;
use crate::models;
use crate::request::authorization::AuthUser;
use crate::request::error::ApiError;
#[get("/user/{userId}/owned_games")]
pub async fn get_user_owned_games(
pool: web::Data<DbPool>,
_user: AuthUser,
user_id: web::Path<Uuid>
) -> Result<impl Responder, ApiError> {
let mut conn = pool.get_conn();
let game_ids = owned_games(&mut conn, user_id.into_inner())?;
let model = game_ids.iter().map(|(u,g , l)| models::owned_game::OwnedGame {
user_id: u.to_string(),
game_id: g.to_string(),
location_id: l.map(|x| x.to_string())
}).collect::<Vec<models::owned_game::OwnedGame>>();
Ok(HttpResponse::Ok()
.content_type(ContentType::json())
.body(serde_json::to_string(&model)?))
}

View File

@@ -1,25 +1,13 @@
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 actix_web::{get, post, web, HttpResponse, Responder};
use actix_web::http::header::ContentType;
use gamenight_database::{DbPool, GetConnection};
use gamenight_database::user::{count_users_with_email, count_users_with_username};
use serde::{Deserialize, Serialize};
use serde_json;
use uuid::Uuid;
use validator::{Validate, ValidateArgs, ValidationError};
use super::authorization::AuthUser;
impl From<Login> for gamenight_database::user::LoginUser {
fn from(val: Login) -> Self {
gamenight_database::user::LoginUser {
username: val.username,
password: val.password,
}
}
}
use crate::models::registration::Registration;
use crate::models::user::User;
use crate::request::authorization::AuthUser;
use crate::request::error::ApiError;
impl From<Registration> for gamenight_database::user::Register {
fn from(val: Registration) -> Self {
@@ -35,6 +23,7 @@ pub struct RegisterContext<'v_a> {
pub pool: &'v_a DbPool,
}
pub fn unique_username(
username: &String,
context: &RegisterContext,
@@ -83,100 +72,7 @@ impl From<Registration> for ValidatableRegistration {
}
}
#[get("/token")]
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 || {
let mut conn = pool.get_conn();
gamenight_database::login(&mut conn, data.into())
})
.await?
{
let token = get_token(&user)?;
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(),
})
}
}
#[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),
};
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> {
web::block(move || -> Result<(), ApiError> {
let validatable_registration: ValidatableRegistration = register_data.clone().into();
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??;
Ok(HttpResponse::Ok())
}
impl From<gamenight_database::user::User> for User {
fn from(value: gamenight_database::user::User) -> Self {
Self {
id: value.id.to_string(),
username: value.username,
email: None,
}
}
}
#[get("/user")]
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)?,
)?;
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> {
Ok(HttpResponse::Forbidden())
}
#[get("/users")]
pub async fn get_users(
pool: web::Data<DbPool>,
_user: AuthUser,
@@ -190,3 +86,21 @@ pub async fn get_users(
.content_type(ContentType::json())
.body(serde_json::to_string(&model)?))
}
#[post("/users")]
pub async fn post_users(
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 })?;
let register_request = register_data.into_inner().into();
let mut conn = pool.get_conn();
gamenight_database::register(&mut conn, register_request)?;
Ok(())
})
.await??;
Ok(HttpResponse::Ok())
}