You've already forked AstralRinth
forked from didirus/AstralRinth
User retrieval routes
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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>,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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")]
|
||||||
|
|||||||
@@ -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
78
src/routes/users.rs
Normal 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(""))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user