1
0

GDPR export route (#969)

* GDPR export route

* make users able to access
This commit is contained in:
Geometrically
2024-09-27 12:43:17 -07:00
committed by GitHub
parent f7d1cd2a4f
commit 28b6bf8603
20 changed files with 417 additions and 163 deletions

View File

@@ -95,16 +95,7 @@ pub async fn subscriptions(
user_subscription_item::UserSubscriptionItem::get_all_user(user.id.into(), &**pool)
.await?
.into_iter()
.map(|x| UserSubscription {
id: x.id.into(),
user_id: x.user_id.into(),
price_id: x.price_id.into(),
interval: x.interval,
status: x.status,
created: x.created,
expires: x.expires,
last_charge: x.last_charge,
})
.map(UserSubscription::from)
.collect::<Vec<_>>();
Ok(HttpResponse::Ok().json(subscriptions))

View File

@@ -1641,14 +1641,13 @@ async fn validate_2fa_code(
}
if input == token {
conn
.set(
TOTP_NAMESPACE,
&format!("{}-{}", token, user_id.0),
"",
Some(60),
)
.await?;
conn.set(
TOTP_NAMESPACE,
&format!("{}-{}", token, user_id.0),
"",
Some(60),
)
.await?;
Ok(true)
} else if allow_backup {

177
src/routes/internal/gdpr.rs Normal file
View File

@@ -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,
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))
.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,
})))
}

View File

@@ -1,6 +1,7 @@
pub(crate) mod admin;
pub mod billing;
pub mod flows;
pub mod gdpr;
pub mod moderation;
pub mod pats;
pub mod session;
@@ -19,6 +20,7 @@ pub fn config(cfg: &mut actix_web::web::ServiceConfig) {
.configure(flows::config)
.configure(pats::config)
.configure(moderation::config)
.configure(billing::config),
.configure(billing::config)
.configure(gdpr::config),
);
}

View File

@@ -571,20 +571,7 @@ pub async fn user_follows(
));
}
use futures::TryStreamExt;
let project_ids = sqlx::query!(
"
SELECT mf.mod_id FROM mod_follows mf
WHERE mf.follower_id = $1
",
id as crate::database::models::ids::UserId,
)
.fetch(&**pool)
.map_ok(|m| crate::database::models::ProjectId(m.mod_id))
.try_collect::<Vec<crate::database::models::ProjectId>>()
.await?;
let project_ids = User::get_follows(id, &**pool).await?;
let projects: Vec<_> =
crate::database::Project::get_many_ids(&project_ids, &**pool, &redis)
.await?