Skip to content

Commit

Permalink
GDPR export route (#969)
Browse files Browse the repository at this point in the history
* GDPR export route

* make users able to access
  • Loading branch information
Geometrically authored Sep 27, 2024
1 parent f7d1cd2 commit 28b6bf8
Show file tree
Hide file tree
Showing 20 changed files with 417 additions and 163 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 2 additions & 46 deletions src/auth/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ use crate::auth::AuthenticationError;
use crate::database::models::user_item;
use crate::database::redis::RedisPool;
use crate::models::pats::Scopes;
use crate::models::users::{Role, User, UserId, UserPayoutData};
use crate::models::users::User;
use crate::queue::session::AuthQueue;
use crate::routes::internal::session::get_session_metadata;
use actix_web::http::header::{HeaderValue, AUTHORIZATION};
use actix_web::HttpRequest;
use chrono::Utc;
use rust_decimal::Decimal;

pub async fn get_user_from_headers<'a, E>(
req: &HttpRequest,
Expand All @@ -26,51 +25,8 @@ where
get_user_record_from_bearer_token(req, None, executor, redis, session_queue)
.await?
.ok_or_else(|| AuthenticationError::InvalidCredentials)?;
let mut auth_providers = Vec::new();
if db_user.github_id.is_some() {
auth_providers.push(AuthProvider::GitHub)
}
if db_user.gitlab_id.is_some() {
auth_providers.push(AuthProvider::GitLab)
}
if db_user.discord_id.is_some() {
auth_providers.push(AuthProvider::Discord)
}
if db_user.google_id.is_some() {
auth_providers.push(AuthProvider::Google)
}
if db_user.microsoft_id.is_some() {
auth_providers.push(AuthProvider::Microsoft)
}
if db_user.steam_id.is_some() {
auth_providers.push(AuthProvider::Steam)
}
if db_user.paypal_id.is_some() {
auth_providers.push(AuthProvider::PayPal)
}

let user = User {
id: UserId::from(db_user.id),
username: db_user.username,
email: db_user.email,
email_verified: Some(db_user.email_verified),
avatar_url: db_user.avatar_url,
bio: db_user.bio,
created: db_user.created,
role: Role::from_string(&db_user.role),
badges: db_user.badges,
auth_providers: Some(auth_providers),
has_password: Some(db_user.password.is_some()),
has_totp: Some(db_user.totp_secret.is_some()),
github_id: None,
payout_data: Some(UserPayoutData {
paypal_address: db_user.paypal_email,
paypal_country: db_user.paypal_country,
venmo_handle: db_user.venmo_handle,
balance: Decimal::ZERO,
}),
stripe_customer_id: db_user.stripe_customer_id,
};
let user = User::from_full(db_user);

if let Some(required_scopes) = required_scopes {
for scope in required_scopes {
Expand Down
23 changes: 2 additions & 21 deletions src/database/models/project_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,31 +355,12 @@ impl Project {
.execute(&mut **transaction)
.await?;

// Notably joins with report id and not thread.mod_id directly, as
// this is set to null for threads that are reports.
let report_threads = sqlx::query!(
"
SELECT t.id
FROM threads t
INNER JOIN reports r ON t.report_id = r.id
WHERE r.mod_id = $1 AND report_id IS NOT NULL
",
id as ProjectId,
)
.fetch(&mut **transaction)
.map_ok(|x| ThreadId(x.id))
.try_collect::<Vec<_>>()
.await?;

for thread_id in report_threads {
models::Thread::remove_full(thread_id, transaction).await?;
}

models::Thread::remove_full(project.thread_id, transaction).await?;

sqlx::query!(
"
DELETE FROM reports
UPDATE reports
SET mod_id = NULL
WHERE mod_id = $1
",
id as ProjectId,
Expand Down
44 changes: 43 additions & 1 deletion src/database/models/user_item.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::ids::{ProjectId, UserId};
use super::{CollectionId, ThreadId};
use super::{CollectionId, ReportId, ThreadId};
use crate::database::models;
use crate::database::models::{DatabaseError, OrganizationId};
use crate::database::redis::RedisPool;
Expand Down Expand Up @@ -323,6 +323,48 @@ impl User {
Ok(projects)
}

pub async fn get_follows<'a, E>(user_id: UserId, exec: E) -> Result<Vec<ProjectId>, sqlx::Error>
where
E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy,
{
use futures::stream::TryStreamExt;

let projects = sqlx::query!(
"
SELECT mf.mod_id FROM mod_follows mf
WHERE mf.follower_id = $1
",
user_id as UserId,
)
.fetch(exec)
.map_ok(|m| ProjectId(m.mod_id))
.try_collect::<Vec<ProjectId>>()
.await?;

Ok(projects)
}

pub async fn get_reports<'a, E>(user_id: UserId, exec: E) -> Result<Vec<ReportId>, sqlx::Error>
where
E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy,
{
use futures::stream::TryStreamExt;

let reports = sqlx::query!(
"
SELECT r.id FROM reports r
WHERE r.user_id = $1
",
user_id as UserId,
)
.fetch(exec)
.map_ok(|m| ReportId(m.id))
.try_collect::<Vec<ReportId>>()
.await?;

Ok(reports)
}

pub async fn get_backup_codes<'a, E>(
user_id: UserId,
exec: E,
Expand Down
3 changes: 2 additions & 1 deletion src/database/models/version_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,8 @@ impl Version {

sqlx::query!(
"
DELETE FROM reports
UPDATE reports
SET version_id = NULL
WHERE version_id = $1
",
id as VersionId,
Expand Down
17 changes: 17 additions & 0 deletions src/models/v3/billing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,23 @@ pub struct UserSubscription {
pub last_charge: Option<DateTime<Utc>>,
}

impl From<crate::database::models::user_subscription_item::UserSubscriptionItem>
for UserSubscription
{
fn from(x: crate::database::models::user_subscription_item::UserSubscriptionItem) -> Self {
Self {
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,
}
}
}

#[derive(Serialize, Deserialize, Eq, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub enum SubscriptionStatus {
Expand Down
28 changes: 17 additions & 11 deletions src/models/v3/threads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,19 +113,25 @@ impl Thread {
true
}
})
.map(|x| ThreadMessage {
id: x.id.into(),
author_id: if x.hide_identity && !user.role.is_mod() {
None
} else {
x.author_id.map(|x| x.into())
},
body: x.body,
created: x.created,
hide_identity: x.hide_identity,
})
.map(|x| ThreadMessage::from(x, user))
.collect(),
members: users,
}
}
}

impl ThreadMessage {
pub fn from(data: crate::database::models::ThreadMessage, user: &User) -> Self {
Self {
id: data.id.into(),
author_id: if data.hide_identity && !user.role.is_mod() {
None
} else {
data.author_id.map(|x| x.into())
},
body: data.body,
created: data.created,
hide_identity: data.hide_identity,
}
}
}
Loading

0 comments on commit 28b6bf8

Please sign in to comment.