diff --git a/src/auth/mod.rs b/src/auth/mod.rs index 83d3936b..ee06aa95 100644 --- a/src/auth/mod.rs +++ b/src/auth/mod.rs @@ -53,13 +53,12 @@ where { let github_user = get_github_user_from_token(access_token).await?; - let res = - models::User::get_from_github_id(models::UserId(github_user.id as i64), executor).await?; + let res = models::User::get_from_github_id(github_user.id, executor).await?; match res { Some(result) => Ok(User { id: UserId::from(result.id), - github_id: UserId::from(result.github_id), + github_id: result.github_id as u64, username: result.username, name: result.name, email: result.email, diff --git a/src/database/models/user_item.rs b/src/database/models/user_item.rs index 42a0ea5a..0e222876 100644 --- a/src/database/models/user_item.rs +++ b/src/database/models/user_item.rs @@ -2,7 +2,7 @@ use super::ids::UserId; pub struct User { pub id: UserId, - pub github_id: UserId, + pub github_id: i64, pub username: String, pub name: String, pub email: Option, @@ -29,7 +29,7 @@ impl User { ) ", self.id as UserId, - self.github_id as UserId, + self.github_id, &self.username, &self.name, self.email.as_ref(), @@ -62,7 +62,7 @@ impl User { if let Some(row) = result { Ok(Some(User { id, - github_id: UserId(row.github_id), + github_id: row.github_id, name: row.name, email: row.email, avatar_url: row.avatar_url, @@ -77,7 +77,7 @@ impl User { } pub async fn get_from_github_id<'a, 'b, E>( - github_id: UserId, + github_id: u64, executor: E, ) -> Result, sqlx::error::Error> where @@ -91,7 +91,7 @@ impl User { FROM users u WHERE u.github_id = $1 ", - github_id as UserId, + github_id as i64, ) .fetch_optional(executor) .await?; @@ -99,7 +99,7 @@ impl User { if let Some(row) = result { Ok(Some(User { id: UserId(row.id), - github_id, + github_id: github_id as i64, name: row.name, email: row.email, avatar_url: row.avatar_url, diff --git a/src/main.rs b/src/main.rs index 2172a3d0..e3004bb9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -196,7 +196,8 @@ async fn main() -> std::io::Result<()> { web::scope("/api/v1/") .configure(routes::auth_config) .configure(routes::tags_config) - .configure(routes::mods_config), + .configure(routes::mods_config) + .configure(routes::users_config), ) .default_service(web::get().to(routes::not_found)) }) diff --git a/src/models/users.rs b/src/models/users.rs index 6e70234c..12451cee 100644 --- a/src/models/users.rs +++ b/src/models/users.rs @@ -9,7 +9,7 @@ pub struct UserId(pub u64); #[derive(Serialize, Deserialize)] pub struct User { pub id: UserId, - pub github_id: UserId, + pub github_id: u64, pub username: String, pub name: String, pub email: Option, diff --git a/src/routes/auth.rs b/src/routes/auth.rs index 727ee2b3..3396622e 100644 --- a/src/routes/auth.rs +++ b/src/routes/auth.rs @@ -1,5 +1,5 @@ use crate::auth::get_github_user_from_token; -use crate::database::models::{generate_state_id, User, UserId}; +use crate::database::models::{generate_state_id, User}; use crate::models::error::ApiError; use crate::models::ids::base62_impl::{parse_base62, to_base62}; use crate::models::ids::DecodingError; @@ -174,16 +174,15 @@ pub async fn auth_callback( let user = get_github_user_from_token(&*token.access_token).await?; - let user_result = User::get_from_github_id(UserId(user.id as i64), &mut *transaction).await?; + let user_result = User::get_from_github_id(user.id, &mut *transaction).await?; match user_result { Some(x) => info!("{:?}", x.id), None => { - let user_id = crate::database::models::generate_user_id(&mut transaction) - .await?; + let user_id = crate::database::models::generate_user_id(&mut transaction).await?; User { id: user_id, - github_id: UserId(user.id as i64), + github_id: user.id as i64, username: user.login, name: user.name, email: user.email, diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 3812293c..79fb6566 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -6,6 +6,7 @@ mod mod_creation; mod mods; mod not_found; mod tags; +mod users; mod version_creation; mod versions; @@ -40,6 +41,16 @@ pub fn versions_config(cfg: &mut web::ServiceConfig) { ); } +pub fn users_config(cfg: &mut web::ServiceConfig) { + cfg.service(users::user_auth_get); + + cfg.service( + web::scope("user") + .service(users::user_get) + .service(users::user_delete), + ); +} + #[derive(thiserror::Error, Debug)] pub enum ApiError { #[error("Internal server error")] diff --git a/src/routes/tags.rs b/src/routes/tags.rs index 3aa668b5..8a6e75be 100644 --- a/src/routes/tags.rs +++ b/src/routes/tags.rs @@ -1,7 +1,7 @@ use super::ApiError; use crate::auth::check_is_admin_from_headers; use crate::database::models; -use actix_web::{delete, get, put, web, HttpResponse, HttpRequest}; +use actix_web::{delete, get, put, web, HttpRequest, HttpResponse}; use models::categories::{Category, GameVersion, Loader}; use sqlx::PgPool; diff --git a/src/routes/users.rs b/src/routes/users.rs new file mode 100644 index 00000000..9a313546 --- /dev/null +++ b/src/routes/users.rs @@ -0,0 +1,78 @@ +use crate::auth::{check_is_moderator_from_headers, get_user_from_headers}; +use crate::models::users::{Role, UserId}; +use crate::routes::ApiError; +use actix_web::{delete, get, post, web, HttpRequest, HttpResponse}; +use sqlx::PgPool; + +#[post("mod")] +pub async fn user_auth_get( + req: HttpRequest, + pool: web::Data, +) -> Result { + Ok(HttpResponse::Ok().json( + get_user_from_headers( + req.headers(), + &mut *pool + .acquire() + .await + .map_err(|e| ApiError::DatabaseError(e.into()))?, + ) + .await + .map_err(|_| ApiError::AuthenticationError)?, + )) +} + +#[get("{id}")] +pub async fn user_get( + info: web::Path<(UserId,)>, + pool: web::Data, +) -> Result { + let id = info.0; + let user_data = crate::database::models::User::get(id.into(), &**pool) + .await + .map_err(|e| ApiError::DatabaseError(e.into()))?; + + if let Some(data) = user_data { + let response = crate::models::users::User { + id: data.id.into(), + github_id: data.github_id as u64, + username: data.username, + name: data.name, + email: None, + avatar_url: data.avatar_url, + bio: data.bio, + created: data.created, + role: Role::from_string(&*data.role), + }; + Ok(HttpResponse::Ok().json(response)) + } else { + Ok(HttpResponse::NotFound().body("")) + } +} + +// TODO: Make this actually do stuff +#[delete("{id}")] +pub async fn user_delete( + req: HttpRequest, + info: web::Path<(UserId,)>, + pool: web::Data, +) -> Result { + check_is_moderator_from_headers( + req.headers(), + &mut *pool + .acquire() + .await + .map_err(|e| ApiError::DatabaseError(e.into()))?, + ) + .await + .map_err(|_| ApiError::AuthenticationError)?; + + let _id = info.0; + let result = Some(()); + + if result.is_some() { + Ok(HttpResponse::Ok().body("")) + } else { + Ok(HttpResponse::NotFound().body("")) + } +} diff --git a/src/routes/version_creation.rs b/src/routes/version_creation.rs index 1482ec00..b6c1548a 100644 --- a/src/routes/version_creation.rs +++ b/src/routes/version_creation.rs @@ -136,22 +136,19 @@ async fn version_create_inner( "SELECT team_id FROM mods WHERE id=$1", mod_id as models::ModId, ) - .fetch_one(&mut *transaction) - .await?.team_id; + .fetch_one(&mut *transaction) + .await? + .team_id; - let member_ids_rows = sqlx::query!( - "SELECT user_id FROM team_members WHERE team_id=$1", - team_id, - ) - .fetch_all(&mut *transaction) - .await?; + let member_ids_rows = + sqlx::query!("SELECT user_id FROM team_members WHERE team_id=$1", team_id,) + .fetch_all(&mut *transaction) + .await?; - let member_ids : Vec = member_ids_rows.iter() - .map(|m| m.user_id) - .collect(); + let member_ids: Vec = member_ids_rows.iter().map(|m| m.user_id).collect(); if !member_ids.contains(&(user.id.0 as i64)) { - return Err(CreateError::InvalidInput("Unauthorized".to_string())) + return Err(CreateError::InvalidInput("Unauthorized".to_string())); } let version_id: VersionId = models::generate_version_id(transaction).await?.into(); @@ -395,9 +392,7 @@ async fn upload_file_to_version_inner( } if version.author_id as u64 != user.id.0 { - return Err(CreateError::InvalidInput( - "Unauthorized".to_string(), - )); + return Err(CreateError::InvalidInput("Unauthorized".to_string())); } let mod_id = ModId(version.mod_id as u64);