Make delete-profile command update counters and clean files

This commit is contained in:
silverpill 2021-09-26 00:11:37 +00:00
parent 7fbd889946
commit def4ac69dc
2 changed files with 54 additions and 7 deletions

View file

@ -8,7 +8,7 @@ use mitra::database::migrate::apply_migrations;
use mitra::ethereum::utils::generate_ethereum_address; use mitra::ethereum::utils::generate_ethereum_address;
use mitra::logger::configure_logger; use mitra::logger::configure_logger;
use mitra::models::posts::queries::delete_post; use mitra::models::posts::queries::delete_post;
use mitra::models::profiles::queries as profiles; use mitra::models::profiles::queries::delete_profile;
use mitra::models::users::queries::{ use mitra::models::users::queries::{
generate_invite_code, generate_invite_code,
get_invite_codes, get_invite_codes,
@ -68,7 +68,8 @@ async fn main() {
match opts.subcmd { match opts.subcmd {
SubCommand::DeleteProfile(subopts) => { SubCommand::DeleteProfile(subopts) => {
profiles::delete_profile(db_client, &subopts.id).await.unwrap(); let orphaned_files = delete_profile(db_client, &subopts.id).await.unwrap();
remove_files(orphaned_files, &config.media_dir());
println!("profile deleted"); println!("profile deleted");
}, },
SubCommand::DeletePost(subopts) => { SubCommand::DeletePost(subopts) => {

View file

@ -2,6 +2,7 @@ use tokio_postgres::GenericClient;
use uuid::Uuid; use uuid::Uuid;
use crate::errors::DatabaseError; use crate::errors::DatabaseError;
use crate::models::attachments::queries::find_orphaned_files;
use super::types::{ use super::types::{
ExtraFields, ExtraFields,
DbActorProfile, DbActorProfile,
@ -179,18 +180,63 @@ pub async fn get_followers(
Ok(profiles) Ok(profiles)
} }
/// Deletes profile from database and returns list of orphaned files.
pub async fn delete_profile( pub async fn delete_profile(
db_client: &impl GenericClient, db_client: &mut impl GenericClient,
profile_id: &Uuid, profile_id: &Uuid,
) -> Result<(), DatabaseError> { ) -> Result<Vec<String>, DatabaseError> {
let deleted_count = db_client.execute( let transaction = db_client.transaction().await?;
"DELETE FROM actor_profile WHERE id = $1", // Get list of media files owned by actor
let files_rows = transaction.query(
"
SELECT file_name
FROM media_attachment WHERE owner_id = $1
UNION ALL
SELECT unnest(array_remove(ARRAY[avatar_file_name, banner_file_name], NULL))
FROM actor_profile WHERE id = $1
",
&[&profile_id],
).await?;
let files: Vec<String> = files_rows.iter()
.map(|row| row.try_get("file_name"))
.collect::<Result<_, _>>()?;
// Update counters
transaction.execute(
"
UPDATE actor_profile
SET follower_count = follower_count - 1
FROM relationship
WHERE
actor_profile.id = relationship.target_id
AND relationship.source_id = $1
",
&[&profile_id],
).await?;
transaction.execute(
"
UPDATE actor_profile
SET following_count = following_count - 1
FROM relationship
WHERE
actor_profile.id = relationship.source_id
AND relationship.target_id = $1
",
&[&profile_id],
).await?;
// Delete profile
let deleted_count = transaction.execute(
"
DELETE FROM actor_profile WHERE id = $1
RETURNING actor_profile
",
&[&profile_id], &[&profile_id],
).await?; ).await?;
if deleted_count == 0 { if deleted_count == 0 {
return Err(DatabaseError::NotFound("profile")); return Err(DatabaseError::NotFound("profile"));
} }
Ok(()) let orphaned_files = find_orphaned_files(&transaction, files).await?;
transaction.commit().await?;
Ok(orphaned_files)
} }
pub async fn search_profile( pub async fn search_profile(