User retrieval routes

This commit is contained in:
Jai A
2020-09-28 22:30:13 -07:00
parent 3d32c30d2d
commit 2e514735ec
9 changed files with 115 additions and 32 deletions

View File

@@ -53,13 +53,12 @@ where
{ {
let github_user = get_github_user_from_token(access_token).await?; let github_user = get_github_user_from_token(access_token).await?;
let res = let res = models::User::get_from_github_id(github_user.id, executor).await?;
models::User::get_from_github_id(models::UserId(github_user.id as i64), executor).await?;
match res { match res {
Some(result) => Ok(User { Some(result) => Ok(User {
id: UserId::from(result.id), id: UserId::from(result.id),
github_id: UserId::from(result.github_id), github_id: result.github_id as u64,
username: result.username, username: result.username,
name: result.name, name: result.name,
email: result.email, email: result.email,

View File

@@ -2,7 +2,7 @@ use super::ids::UserId;
pub struct User { pub struct User {
pub id: UserId, pub id: UserId,
pub github_id: UserId, pub github_id: i64,
pub username: String, pub username: String,
pub name: String, pub name: String,
pub email: Option<String>, pub email: Option<String>,
@@ -29,7 +29,7 @@ impl User {
) )
", ",
self.id as UserId, self.id as UserId,
self.github_id as UserId, self.github_id,
&self.username, &self.username,
&self.name, &self.name,
self.email.as_ref(), self.email.as_ref(),
@@ -62,7 +62,7 @@ impl User {
if let Some(row) = result { if let Some(row) = result {
Ok(Some(User { Ok(Some(User {
id, id,
github_id: UserId(row.github_id), github_id: row.github_id,
name: row.name, name: row.name,
email: row.email, email: row.email,
avatar_url: row.avatar_url, avatar_url: row.avatar_url,
@@ -77,7 +77,7 @@ impl User {
} }
pub async fn get_from_github_id<'a, 'b, E>( pub async fn get_from_github_id<'a, 'b, E>(
github_id: UserId, github_id: u64,
executor: E, executor: E,
) -> Result<Option<Self>, sqlx::error::Error> ) -> Result<Option<Self>, sqlx::error::Error>
where where
@@ -91,7 +91,7 @@ impl User {
FROM users u FROM users u
WHERE u.github_id = $1 WHERE u.github_id = $1
", ",
github_id as UserId, github_id as i64,
) )
.fetch_optional(executor) .fetch_optional(executor)
.await?; .await?;
@@ -99,7 +99,7 @@ impl User {
if let Some(row) = result { if let Some(row) = result {
Ok(Some(User { Ok(Some(User {
id: UserId(row.id), id: UserId(row.id),
github_id, github_id: github_id as i64,
name: row.name, name: row.name,
email: row.email, email: row.email,
avatar_url: row.avatar_url, avatar_url: row.avatar_url,

View File

@@ -196,7 +196,8 @@ async fn main() -> std::io::Result<()> {
web::scope("/api/v1/") web::scope("/api/v1/")
.configure(routes::auth_config) .configure(routes::auth_config)
.configure(routes::tags_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)) .default_service(web::get().to(routes::not_found))
}) })

View File

@@ -9,7 +9,7 @@ pub struct UserId(pub u64);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct User { pub struct User {
pub id: UserId, pub id: UserId,
pub github_id: UserId, pub github_id: u64,
pub username: String, pub username: String,
pub name: String, pub name: String,
pub email: Option<String>, pub email: Option<String>,

View File

@@ -1,5 +1,5 @@
use crate::auth::get_github_user_from_token; 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::error::ApiError;
use crate::models::ids::base62_impl::{parse_base62, to_base62}; use crate::models::ids::base62_impl::{parse_base62, to_base62};
use crate::models::ids::DecodingError; 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 = 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 { match user_result {
Some(x) => info!("{:?}", x.id), Some(x) => info!("{:?}", x.id),
None => { None => {
let user_id = crate::database::models::generate_user_id(&mut transaction) let user_id = crate::database::models::generate_user_id(&mut transaction).await?;
.await?;
User { User {
id: user_id, id: user_id,
github_id: UserId(user.id as i64), github_id: user.id as i64,
username: user.login, username: user.login,
name: user.name, name: user.name,
email: user.email, email: user.email,

View File

@@ -6,6 +6,7 @@ mod mod_creation;
mod mods; mod mods;
mod not_found; mod not_found;
mod tags; mod tags;
mod users;
mod version_creation; mod version_creation;
mod versions; 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)] #[derive(thiserror::Error, Debug)]
pub enum ApiError { pub enum ApiError {
#[error("Internal server error")] #[error("Internal server error")]

View File

@@ -1,7 +1,7 @@
use super::ApiError; use super::ApiError;
use crate::auth::check_is_admin_from_headers; use crate::auth::check_is_admin_from_headers;
use crate::database::models; 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 models::categories::{Category, GameVersion, Loader};
use sqlx::PgPool; use sqlx::PgPool;

78
src/routes/users.rs Normal file
View File

@@ -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<PgPool>,
) -> Result<HttpResponse, ApiError> {
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<PgPool>,
) -> Result<HttpResponse, ApiError> {
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<PgPool>,
) -> Result<HttpResponse, ApiError> {
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(""))
}
}

View File

@@ -136,22 +136,19 @@ async fn version_create_inner(
"SELECT team_id FROM mods WHERE id=$1", "SELECT team_id FROM mods WHERE id=$1",
mod_id as models::ModId, mod_id as models::ModId,
) )
.fetch_one(&mut *transaction) .fetch_one(&mut *transaction)
.await?.team_id; .await?
.team_id;
let member_ids_rows = sqlx::query!( let member_ids_rows =
"SELECT user_id FROM team_members WHERE team_id=$1", sqlx::query!("SELECT user_id FROM team_members WHERE team_id=$1", team_id,)
team_id, .fetch_all(&mut *transaction)
) .await?;
.fetch_all(&mut *transaction)
.await?;
let member_ids : Vec<i64> = member_ids_rows.iter() let member_ids: Vec<i64> = member_ids_rows.iter().map(|m| m.user_id).collect();
.map(|m| m.user_id)
.collect();
if !member_ids.contains(&(user.id.0 as i64)) { 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(); 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 { if version.author_id as u64 != user.id.0 {
return Err(CreateError::InvalidInput( return Err(CreateError::InvalidInput("Unauthorized".to_string()));
"Unauthorized".to_string(),
));
} }
let mod_id = ModId(version.mod_id as u64); let mod_id = ModId(version.mod_id as u64);