add delete endpoints

This commit is contained in:
Felix Ableitner 2025-01-09 15:23:06 +01:00
parent 961c7f1fcb
commit 705703f539
6 changed files with 166 additions and 40 deletions

View file

@ -28,7 +28,7 @@
"eslint": "^9.14.0", "eslint": "^9.14.0",
"eslint-plugin-prettier": "^5.1.3", "eslint-plugin-prettier": "^5.1.3",
"jest": "^29.5.0", "jest": "^29.5.0",
"lemmy-js-client": "0.20.0-image-api-rework.7", "lemmy-js-client": "0.20.0-image-api-rework.8",
"prettier": "^3.2.5", "prettier": "^3.2.5",
"ts-jest": "^29.1.0", "ts-jest": "^29.1.0",
"typescript": "^5.5.4", "typescript": "^5.5.4",

View file

@ -30,8 +30,8 @@ importers:
specifier: ^29.5.0 specifier: ^29.5.0
version: 29.7.0(@types/node@22.9.0) version: 29.7.0(@types/node@22.9.0)
lemmy-js-client: lemmy-js-client:
specifier: 0.20.0-image-api-rework.7 specifier: 0.20.0-image-api-rework.8
version: 0.20.0-image-api-rework.7 version: 0.20.0-image-api-rework.8
prettier: prettier:
specifier: ^3.2.5 specifier: ^3.2.5
version: 3.3.3 version: 3.3.3
@ -1167,8 +1167,8 @@ packages:
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
engines: {node: '>=6'} engines: {node: '>=6'}
lemmy-js-client@0.20.0-image-api-rework.7: lemmy-js-client@0.20.0-image-api-rework.8:
resolution: {integrity: sha512-zZVOu8l9ctwEof71/DDkg/pwwBercLJIJja7KT1WxYS2pG6Hng9bD0+VDesbdvacCltFDbbEvk8pgJs3ES4OIQ==} resolution: {integrity: sha512-Ns/ayfCSm2lHbdAU1tGIZSx6kJ2ZeS7UiXlPuH0IzHQSi8Yuyzj3srDCyHpE6Td3pmXbQlt9N1ziPE4KeRJ3CA==}
leven@3.1.0: leven@3.1.0:
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
@ -3077,7 +3077,7 @@ snapshots:
kleur@3.0.3: {} kleur@3.0.3: {}
lemmy-js-client@0.20.0-image-api-rework.7: {} lemmy-js-client@0.20.0-image-api-rework.8: {}
leven@3.1.0: {} leven@3.1.0: {}

View file

@ -0,0 +1,142 @@
use super::utils::{delete_old_image, PICTRS_CLIENT};
use actix_web::web::*;
use lemmy_api_common::{
context::LemmyContext,
image::{CommunityIdQuery, DeleteImageParams},
utils::{is_admin, is_mod_or_admin},
SuccessResponse,
};
use lemmy_db_schema::{
source::{
community::{Community, CommunityUpdateForm},
images::LocalImage,
person::{Person, PersonUpdateForm},
site::{Site, SiteUpdateForm},
},
traits::Crud,
};
use lemmy_db_views::structs::LocalUserView;
use lemmy_utils::error::LemmyResult;
pub async fn delete_site_icon(
context: Data<LemmyContext>,
local_user_view: LocalUserView,
) -> LemmyResult<Json<SuccessResponse>> {
let site = Site::read_local(&mut context.pool()).await?;
is_admin(&local_user_view)?;
delete_old_image(&site.icon, &context).await?;
let form = SiteUpdateForm {
icon: Some(None),
..Default::default()
};
Site::update(&mut context.pool(), site.id, &form).await?;
Ok(Json(SuccessResponse::default()))
}
pub async fn delete_site_banner(
context: Data<LemmyContext>,
local_user_view: LocalUserView,
) -> LemmyResult<Json<SuccessResponse>> {
let site = Site::read_local(&mut context.pool()).await?;
is_admin(&local_user_view)?;
delete_old_image(&site.banner, &context).await?;
let form = SiteUpdateForm {
banner: Some(None),
..Default::default()
};
Site::update(&mut context.pool(), site.id, &form).await?;
Ok(Json(SuccessResponse::default()))
}
pub async fn delete_community_icon(
data: Json<CommunityIdQuery>,
context: Data<LemmyContext>,
local_user_view: LocalUserView,
) -> LemmyResult<Json<SuccessResponse>> {
let community = Community::read(&mut context.pool(), data.id).await?;
is_mod_or_admin(&mut context.pool(), &local_user_view.person, community.id).await?;
delete_old_image(&community.icon, &context).await?;
let form = CommunityUpdateForm {
icon: Some(None),
..Default::default()
};
Community::update(&mut context.pool(), community.id, &form).await?;
Ok(Json(SuccessResponse::default()))
}
pub async fn delete_community_banner(
data: Json<CommunityIdQuery>,
context: Data<LemmyContext>,
local_user_view: LocalUserView,
) -> LemmyResult<Json<SuccessResponse>> {
let community = Community::read(&mut context.pool(), data.id).await?;
is_mod_or_admin(&mut context.pool(), &local_user_view.person, community.id).await?;
delete_old_image(&community.icon, &context).await?;
let form = CommunityUpdateForm {
icon: Some(None),
..Default::default()
};
Community::update(&mut context.pool(), community.id, &form).await?;
Ok(Json(SuccessResponse::default()))
}
pub async fn delete_user_avatar(
context: Data<LemmyContext>,
local_user_view: LocalUserView,
) -> LemmyResult<Json<SuccessResponse>> {
delete_old_image(&local_user_view.person.avatar, &context).await?;
let form = PersonUpdateForm {
avatar: Some(None),
..Default::default()
};
Person::update(&mut context.pool(), local_user_view.person.id, &form).await?;
Ok(Json(SuccessResponse::default()))
}
pub async fn delete_user_banner(
context: Data<LemmyContext>,
local_user_view: LocalUserView,
) -> LemmyResult<Json<SuccessResponse>> {
delete_old_image(&local_user_view.person.banner, &context).await?;
let form = PersonUpdateForm {
banner: Some(None),
..Default::default()
};
Person::update(&mut context.pool(), local_user_view.person.id, &form).await?;
Ok(Json(SuccessResponse::default()))
}
// TODO: get rid of delete tokens and allow deletion by admin or uploader
pub async fn delete_image(
data: Json<DeleteImageParams>,
context: Data<LemmyContext>,
// require login
_local_user_view: LocalUserView,
) -> LemmyResult<Json<SuccessResponse>> {
let pictrs_config = context.settings().pictrs()?;
let url = format!(
"{}image/delete/{}/{}",
pictrs_config.url, &data.token, &data.filename
);
PICTRS_CLIENT.delete(url).send().await?.error_for_status()?;
LocalImage::delete_by_alias(&mut context.pool(), &data.filename).await?;
Ok(Json(SuccessResponse::default()))
}

View file

@ -1,42 +1,13 @@
use actix_web::web::*; use actix_web::web::*;
use lemmy_api_common::{context::LemmyContext, image::DeleteImageParams, SuccessResponse}; use lemmy_api_common::{context::LemmyContext, SuccessResponse};
use lemmy_db_schema::source::images::LocalImage;
use lemmy_db_views::structs::LocalUserView;
use lemmy_utils::error::LemmyResult; use lemmy_utils::error::LemmyResult;
use utils::PICTRS_CLIENT; use utils::PICTRS_CLIENT;
pub mod delete;
pub mod download; pub mod download;
pub mod upload; pub mod upload;
mod utils; mod utils;
pub async fn delete_community_icon(
data: Json<DeleteImageParams>,
context: Data<LemmyContext>,
local_user_view: LocalUserView,
) -> LemmyResult<Json<SuccessResponse>> {
todo!()
}
// TODO: get rid of delete tokens and allow deletion by admin or uploader
pub async fn delete_image(
data: Json<DeleteImageParams>,
context: Data<LemmyContext>,
// require login
_local_user_view: LocalUserView,
) -> LemmyResult<Json<SuccessResponse>> {
let pictrs_config = context.settings().pictrs()?;
let url = format!(
"{}image/delete/{}/{}",
pictrs_config.url, &data.token, &data.filename
);
PICTRS_CLIENT.delete(url).send().await?.error_for_status()?;
LocalImage::delete_by_alias(&mut context.pool(), &data.filename).await?;
Ok(Json(SuccessResponse::default()))
}
pub async fn pictrs_health(context: Data<LemmyContext>) -> LemmyResult<Json<SuccessResponse>> { pub async fn pictrs_health(context: Data<LemmyContext>) -> LemmyResult<Json<SuccessResponse>> {
let pictrs_config = context.settings().pictrs()?; let pictrs_config = context.settings().pictrs()?;
let url = format!("{}healthz", pictrs_config.url); let url = format!("{}healthz", pictrs_config.url);

View file

@ -124,7 +124,7 @@ use lemmy_apub::api::{
user_settings_backup::{export_settings, import_settings}, user_settings_backup::{export_settings, import_settings},
}; };
use lemmy_routes::images::{ use lemmy_routes::images::{
delete_image, delete::delete_image,
download::{get_image, image_proxy}, download::{get_image, image_proxy},
pictrs_health, pictrs_health,
upload::upload_image, upload::upload_image,

View file

@ -150,7 +150,15 @@ use lemmy_apub::api::{
user_settings_backup::{export_settings, import_settings}, user_settings_backup::{export_settings, import_settings},
}; };
use lemmy_routes::images::{ use lemmy_routes::images::{
delete_image, delete::{
delete_community_banner,
delete_community_icon,
delete_image,
delete_site_banner,
delete_site_icon,
delete_user_avatar,
delete_user_banner,
},
download::{get_image, image_proxy}, download::{get_image, image_proxy},
pictrs_health, pictrs_health,
upload::{ upload::{
@ -176,7 +184,9 @@ pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) {
.route("", post().to(create_site)) .route("", post().to(create_site))
.route("", put().to(update_site)) .route("", put().to(update_site))
.route("/icon", post().to(upload_site_icon)) .route("/icon", post().to(upload_site_icon))
.route("/banner", post().to(upload_site_banner)), .route("/icon", delete().to(delete_site_icon))
.route("/banner", post().to(upload_site_banner))
.route("/banner", delete().to(delete_site_banner)),
) )
.route("/modlog", get().to(get_mod_log)) .route("/modlog", get().to(get_mod_log))
.service( .service(
@ -209,6 +219,7 @@ pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) {
.route("/icon", post().to(upload_community_icon)) .route("/icon", post().to(upload_community_icon))
.route("/icon", delete().to(delete_community_icon)) .route("/icon", delete().to(delete_community_icon))
.route("/banner", post().to(upload_community_banner)) .route("/banner", post().to(upload_community_banner))
.route("/banner", delete().to(delete_community_banner))
.service( .service(
scope("/pending_follows") scope("/pending_follows")
.route("/count", get().to(get_pending_follows_count)) .route("/count", get().to(get_pending_follows_count))
@ -327,7 +338,9 @@ pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) {
.route("/list_logins", get().to(list_logins)) .route("/list_logins", get().to(list_logins))
.route("/validate_auth", get().to(validate_auth)) .route("/validate_auth", get().to(validate_auth))
.route("/avatar", post().to(upload_user_avatar)) .route("/avatar", post().to(upload_user_avatar))
.route("/avatar", delete().to(delete_user_avatar))
.route("/banner", post().to(upload_user_banner)) .route("/banner", post().to(upload_user_banner))
.route("/banner", delete().to(delete_user_banner))
.service( .service(
scope("/block") scope("/block")
.route("/person", post().to(user_block_person)) .route("/person", post().to(user_block_person))