Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
make users able to access
Browse files Browse the repository at this point in the history
  • Loading branch information
Geometrically committed Sep 27, 2024
1 parent d5f4bab commit 5b63bef
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 188 deletions.
188 changes: 1 addition & 187 deletions src/routes/internal/admin.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use crate::auth::validate::get_user_record_from_bearer_token;
use crate::auth::{get_user_from_headers, AuthenticationError};
use crate::database::redis::RedisPool;
use crate::models::analytics::Download;
use crate::models::ids::ProjectId;
use crate::models::pats::Scopes;
use crate::models::users::UserId;
use crate::queue::analytics::AnalyticsQueue;
use crate::queue::maxmind::MaxMindIndexer;
use crate::queue::session::AuthQueue;
Expand All @@ -23,8 +21,7 @@ pub fn config(cfg: &mut web::ServiceConfig) {
cfg.service(
web::scope("admin")
.service(count_download)
.service(force_reindex)
.service(gdpr_export),
.service(force_reindex),
);
}

Expand Down Expand Up @@ -148,186 +145,3 @@ pub async fn force_reindex(
index_projects(pool.as_ref().clone(), redis.clone(), &config).await?;
Ok(HttpResponse::NoContent().finish())
}

#[derive(Deserialize)]
pub struct GDPRExport {
pub user_id: UserId,
}

#[post("/_gdpr-export")]
pub async fn gdpr_export(
req: HttpRequest,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
gdpr_export: web::Json<GDPRExport>,
) -> Result<HttpResponse, ApiError> {
let user = get_user_from_headers(
&req,
&**pool,
&redis,
&*session_queue,
Some(&[Scopes::USER_READ]),
)
.await?
.1;

if !user.role.is_admin() {
return Err(ApiError::Authentication(
AuthenticationError::InvalidCredentials,
));
}

let user = crate::database::models::User::get_id(gdpr_export.user_id.into(), &**pool, &redis)
.await?
.ok_or(ApiError::NotFound)?;
let user_id = user.id;

let user = crate::models::users::User::from_full(user);

let collection_ids = crate::database::models::User::get_collections(user_id, &**pool).await?;
let collections =
crate::database::models::Collection::get_many(&collection_ids, &**pool, &redis)
.await?
.into_iter()
.map(|x| crate::models::collections::Collection::from(x))
.collect::<Vec<_>>();

let follows = crate::database::models::User::get_follows(user_id, &**pool)
.await?
.into_iter()
.map(|x| crate::models::ids::ProjectId::from(x))
.collect::<Vec<_>>();

let projects = crate::database::models::User::get_projects(user_id, &**pool, &redis)
.await?
.into_iter()
.map(|x| crate::models::ids::ProjectId::from(x))
.collect::<Vec<_>>();

let org_ids = crate::database::models::User::get_organizations(user_id, &**pool).await?;
let orgs = crate::database::models::organization_item::Organization::get_many_ids(
&org_ids, &**pool, &redis,
)
.await?
.into_iter()
// TODO: add team members
.map(|x| crate::models::organizations::Organization::from(x, vec![]))
.collect::<Vec<_>>();

let notifs = crate::database::models::notification_item::Notification::get_many_user(
user_id, &**pool, &redis,
)
.await?
.into_iter()
.map(|x| crate::models::notifications::Notification::from(x))
.collect::<Vec<_>>();

let oauth_clients =
crate::database::models::oauth_client_item::OAuthClient::get_all_user_clients(
user_id, &**pool,
)
.await?
.into_iter()
.map(|x| crate::models::oauth_clients::OAuthClient::from(x))
.collect::<Vec<_>>();

let oauth_authorizations = crate::database::models::oauth_client_authorization_item::OAuthClientAuthorization::get_all_for_user(
user_id, &**pool,
)
.await?
.into_iter()
.map(|x| crate::models::oauth_clients::OAuthClientAuthorization::from(x))
.collect::<Vec<_>>();

let pat_ids = crate::database::models::pat_item::PersonalAccessToken::get_user_pats(
user_id, &**pool, &redis,
)
.await?;
let pats = crate::database::models::pat_item::PersonalAccessToken::get_many_ids(
&pat_ids, &**pool, &redis,
)
.await?
.into_iter()
.map(|x| crate::models::pats::PersonalAccessToken::from(x, false))
.collect::<Vec<_>>();

let payout_ids =
crate::database::models::payout_item::Payout::get_all_for_user(user_id, &**pool).await?;

let payouts = crate::database::models::payout_item::Payout::get_many(&payout_ids, &**pool)
.await?
.into_iter()
.map(|x| crate::models::payouts::Payout::from(x))
.collect::<Vec<_>>();

let report_ids =
crate::database::models::user_item::User::get_reports(user_id, &**pool).await?;
let reports = crate::database::models::report_item::Report::get_many(&report_ids, &**pool)
.await?
.into_iter()
.map(|x| crate::models::reports::Report::from(x))
.collect::<Vec<_>>();

let message_ids = sqlx::query!(
"
SELECT id FROM threads_messages WHERE author_id = $1 AND hide_identity = FALSE
",
user_id.0
)
.fetch_all(pool.as_ref())
.await?
.into_iter()
.map(|x| crate::database::models::ids::ThreadMessageId(x.id))
.collect::<Vec<_>>();

let messages =
crate::database::models::thread_item::ThreadMessage::get_many(&message_ids, &**pool)
.await?
.into_iter()
.map(|x| crate::models::threads::ThreadMessage::from(x, &user))
.collect::<Vec<_>>();

let uploaded_images_ids = sqlx::query!(
"SELECT id FROM uploaded_images WHERE owner_id = $1",
user_id.0
)
.fetch_all(pool.as_ref())
.await?
.into_iter()
.map(|x| crate::database::models::ids::ImageId(x.id))
.collect::<Vec<_>>();

let uploaded_images =
crate::database::models::image_item::Image::get_many(&uploaded_images_ids, &**pool, &redis)
.await?
.into_iter()
.map(|x| crate::models::images::Image::from(x))
.collect::<Vec<_>>();

let subscriptions =
crate::database::models::user_subscription_item::UserSubscriptionItem::get_all_user(
user_id, &**pool,
)
.await?
.into_iter()
.map(|x| crate::models::billing::UserSubscription::from(x))
.collect::<Vec<_>>();

Ok(HttpResponse::Ok().json(serde_json::json!({
"user": user,
"collections": collections,
"follows": follows,
"projects": projects,
"orgs": orgs,
"notifs": notifs,
"oauth_clients": oauth_clients,
"oauth_authorizations": oauth_authorizations,
"pats": pats,
"payouts": payouts,
"reports": reports,
"messages": messages,
"uploaded_images": uploaded_images,
"subscriptions": subscriptions,
})))
}
177 changes: 177 additions & 0 deletions src/routes/internal/gdpr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
use crate::auth::get_user_from_headers;
use crate::database::redis::RedisPool;
use crate::models::pats::Scopes;
use crate::queue::session::AuthQueue;
use crate::routes::ApiError;
use actix_web::{post, web, HttpRequest, HttpResponse};
use sqlx::PgPool;

pub fn config(cfg: &mut web::ServiceConfig) {
cfg.service(web::scope("gdpr").service(export));
}

#[post("/export")]
pub async fn export(
req: HttpRequest,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
let user = get_user_from_headers(
&req,
&**pool,
&redis,
&*session_queue,

Check warning on line 24 in src/routes/internal/gdpr.rs

View workflow job for this annotation

GitHub Actions / clippy

deref which would be done by auto-deref

warning: deref which would be done by auto-deref --> src/routes/internal/gdpr.rs:24:9 | 24 | &*session_queue, | ^^^^^^^^^^^^^^^ help: try: `&session_queue` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#explicit_auto_deref = note: `#[warn(clippy::explicit_auto_deref)]` on by default
Some(&[Scopes::SESSION_ACCESS]),
)
.await?
.1;

let user_id = user.id.into();

let collection_ids = crate::database::models::User::get_collections(user_id, &**pool).await?;
let collections =
crate::database::models::Collection::get_many(&collection_ids, &**pool, &redis)
.await?
.into_iter()
.map(|x| crate::models::collections::Collection::from(x))

Check warning on line 37 in src/routes/internal/gdpr.rs

View workflow job for this annotation

GitHub Actions / clippy

redundant closure

warning: redundant closure --> src/routes/internal/gdpr.rs:37:18 | 37 | .map(|x| crate::models::collections::Collection::from(x)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `crate::models::collections::Collection::from` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure = note: `#[warn(clippy::redundant_closure)]` on by default
.collect::<Vec<_>>();

let follows = crate::database::models::User::get_follows(user_id, &**pool)
.await?
.into_iter()
.map(|x| crate::models::ids::ProjectId::from(x))

Check warning on line 43 in src/routes/internal/gdpr.rs

View workflow job for this annotation

GitHub Actions / clippy

redundant closure

warning: redundant closure --> src/routes/internal/gdpr.rs:43:14 | 43 | .map(|x| crate::models::ids::ProjectId::from(x)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `crate::models::ids::ProjectId::from` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
.collect::<Vec<_>>();

let projects = crate::database::models::User::get_projects(user_id, &**pool, &redis)
.await?
.into_iter()
.map(|x| crate::models::ids::ProjectId::from(x))

Check warning on line 49 in src/routes/internal/gdpr.rs

View workflow job for this annotation

GitHub Actions / clippy

redundant closure

warning: redundant closure --> src/routes/internal/gdpr.rs:49:14 | 49 | .map(|x| crate::models::ids::ProjectId::from(x)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `crate::models::ids::ProjectId::from` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
.collect::<Vec<_>>();

let org_ids = crate::database::models::User::get_organizations(user_id, &**pool).await?;
let orgs = crate::database::models::organization_item::Organization::get_many_ids(
&org_ids, &**pool, &redis,
)
.await?
.into_iter()
// TODO: add team members
.map(|x| crate::models::organizations::Organization::from(x, vec![]))
.collect::<Vec<_>>();

let notifs = crate::database::models::notification_item::Notification::get_many_user(
user_id, &**pool, &redis,
)
.await?
.into_iter()
.map(|x| crate::models::notifications::Notification::from(x))

Check warning on line 67 in src/routes/internal/gdpr.rs

View workflow job for this annotation

GitHub Actions / clippy

redundant closure

warning: redundant closure --> src/routes/internal/gdpr.rs:67:10 | 67 | .map(|x| crate::models::notifications::Notification::from(x)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `crate::models::notifications::Notification::from` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
.collect::<Vec<_>>();

let oauth_clients =
crate::database::models::oauth_client_item::OAuthClient::get_all_user_clients(
user_id, &**pool,
)
.await?
.into_iter()
.map(|x| crate::models::oauth_clients::OAuthClient::from(x))

Check warning on line 76 in src/routes/internal/gdpr.rs

View workflow job for this annotation

GitHub Actions / clippy

redundant closure

warning: redundant closure --> src/routes/internal/gdpr.rs:76:14 | 76 | .map(|x| crate::models::oauth_clients::OAuthClient::from(x)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `crate::models::oauth_clients::OAuthClient::from` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
.collect::<Vec<_>>();

let oauth_authorizations = crate::database::models::oauth_client_authorization_item::OAuthClientAuthorization::get_all_for_user(
user_id, &**pool,
)
.await?
.into_iter()
.map(|x| crate::models::oauth_clients::OAuthClientAuthorization::from(x))

Check warning on line 84 in src/routes/internal/gdpr.rs

View workflow job for this annotation

GitHub Actions / clippy

redundant closure

warning: redundant closure --> src/routes/internal/gdpr.rs:84:14 | 84 | .map(|x| crate::models::oauth_clients::OAuthClientAuthorization::from(x)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `crate::models::oauth_clients::OAuthClientAuthorization::from` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
.collect::<Vec<_>>();

let pat_ids = crate::database::models::pat_item::PersonalAccessToken::get_user_pats(
user_id, &**pool, &redis,
)
.await?;
let pats = crate::database::models::pat_item::PersonalAccessToken::get_many_ids(
&pat_ids, &**pool, &redis,
)
.await?
.into_iter()
.map(|x| crate::models::pats::PersonalAccessToken::from(x, false))
.collect::<Vec<_>>();

let payout_ids =
crate::database::models::payout_item::Payout::get_all_for_user(user_id, &**pool).await?;

let payouts = crate::database::models::payout_item::Payout::get_many(&payout_ids, &**pool)
.await?
.into_iter()
.map(|x| crate::models::payouts::Payout::from(x))

Check warning on line 105 in src/routes/internal/gdpr.rs

View workflow job for this annotation

GitHub Actions / clippy

redundant closure

warning: redundant closure --> src/routes/internal/gdpr.rs:105:14 | 105 | .map(|x| crate::models::payouts::Payout::from(x)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `crate::models::payouts::Payout::from` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
.collect::<Vec<_>>();

let report_ids =
crate::database::models::user_item::User::get_reports(user_id, &**pool).await?;
let reports = crate::database::models::report_item::Report::get_many(&report_ids, &**pool)
.await?
.into_iter()
.map(|x| crate::models::reports::Report::from(x))

Check warning on line 113 in src/routes/internal/gdpr.rs

View workflow job for this annotation

GitHub Actions / clippy

redundant closure

warning: redundant closure --> src/routes/internal/gdpr.rs:113:14 | 113 | .map(|x| crate::models::reports::Report::from(x)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `crate::models::reports::Report::from` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
.collect::<Vec<_>>();

let message_ids = sqlx::query!(
"
SELECT id FROM threads_messages WHERE author_id = $1 AND hide_identity = FALSE
",
user_id.0
)
.fetch_all(pool.as_ref())
.await?
.into_iter()
.map(|x| crate::database::models::ids::ThreadMessageId(x.id))
.collect::<Vec<_>>();

let messages =
crate::database::models::thread_item::ThreadMessage::get_many(&message_ids, &**pool)
.await?
.into_iter()
.map(|x| crate::models::threads::ThreadMessage::from(x, &user))
.collect::<Vec<_>>();

let uploaded_images_ids = sqlx::query!(
"SELECT id FROM uploaded_images WHERE owner_id = $1",
user_id.0
)
.fetch_all(pool.as_ref())
.await?
.into_iter()
.map(|x| crate::database::models::ids::ImageId(x.id))
.collect::<Vec<_>>();

let uploaded_images =
crate::database::models::image_item::Image::get_many(&uploaded_images_ids, &**pool, &redis)
.await?
.into_iter()
.map(|x| crate::models::images::Image::from(x))

Check warning on line 149 in src/routes/internal/gdpr.rs

View workflow job for this annotation

GitHub Actions / clippy

redundant closure

warning: redundant closure --> src/routes/internal/gdpr.rs:149:18 | 149 | .map(|x| crate::models::images::Image::from(x)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `crate::models::images::Image::from` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
.collect::<Vec<_>>();

let subscriptions =
crate::database::models::user_subscription_item::UserSubscriptionItem::get_all_user(
user_id, &**pool,
)
.await?
.into_iter()
.map(|x| crate::models::billing::UserSubscription::from(x))

Check warning on line 158 in src/routes/internal/gdpr.rs

View workflow job for this annotation

GitHub Actions / clippy

redundant closure

warning: redundant closure --> src/routes/internal/gdpr.rs:158:14 | 158 | .map(|x| crate::models::billing::UserSubscription::from(x)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `crate::models::billing::UserSubscription::from` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
.collect::<Vec<_>>();

Ok(HttpResponse::Ok().json(serde_json::json!({
"user": user,
"collections": collections,
"follows": follows,
"projects": projects,
"orgs": orgs,
"notifs": notifs,
"oauth_clients": oauth_clients,
"oauth_authorizations": oauth_authorizations,
"pats": pats,
"payouts": payouts,
"reports": reports,
"messages": messages,
"uploaded_images": uploaded_images,
"subscriptions": subscriptions,
})))
}
Loading

0 comments on commit 5b63bef

Please sign in to comment.