Creating a LocalImageView, so that front ends have the Person struct. (#4631)
* Creating a LocalImageView, so that front ends have the Person struct. * Removing local_user from LocalImageView. * Add uploader check.
This commit is contained in:
parent
d075acce43
commit
6efab9aab1
12 changed files with 2089 additions and 1662 deletions
|
@ -6,6 +6,7 @@
|
||||||
"repository": "https://github.com/LemmyNet/lemmy",
|
"repository": "https://github.com/LemmyNet/lemmy",
|
||||||
"author": "Dessalines",
|
"author": "Dessalines",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
|
"packageManager": "pnpm@9.0.1+sha256.46d50ee2afecb42b185ebbd662dc7bdd52ef5be56bf035bb615cab81a75345df",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "tsc --noEmit && eslint --report-unused-disable-directives --ext .js,.ts,.tsx src && prettier --check 'src/**/*.ts'",
|
"lint": "tsc --noEmit && eslint --report-unused-disable-directives --ext .js,.ts,.tsx src && prettier --check 'src/**/*.ts'",
|
||||||
"fix": "prettier --write src && eslint --fix src",
|
"fix": "prettier --write src && eslint --fix src",
|
||||||
|
@ -27,7 +28,7 @@
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.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.19.4-alpha.16",
|
"lemmy-js-client": "0.19.4-alpha.18",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"ts-jest": "^29.1.0",
|
"ts-jest": "^29.1.0",
|
||||||
"typescript": "^5.4.4"
|
"typescript": "^5.4.4"
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -71,9 +71,14 @@ test("Upload image and delete it", async () => {
|
||||||
|
|
||||||
// The deleteUrl is a combination of the endpoint, delete token, and alias
|
// The deleteUrl is a combination of the endpoint, delete token, and alias
|
||||||
let firstImage = listMediaRes.images[0];
|
let firstImage = listMediaRes.images[0];
|
||||||
let deleteUrl = `${alphaUrl}/pictrs/image/delete/${firstImage.pictrs_delete_token}/${firstImage.pictrs_alias}`;
|
let deleteUrl = `${alphaUrl}/pictrs/image/delete/${firstImage.local_image.pictrs_delete_token}/${firstImage.local_image.pictrs_alias}`;
|
||||||
expect(deleteUrl).toBe(upload.delete_url);
|
expect(deleteUrl).toBe(upload.delete_url);
|
||||||
|
|
||||||
|
// Make sure the uploader is correct
|
||||||
|
expect(firstImage.person.actor_id).toBe(
|
||||||
|
`http://lemmy-alpha:8541/u/lemmy_alpha`,
|
||||||
|
);
|
||||||
|
|
||||||
// delete image
|
// delete image
|
||||||
const delete_form: DeleteImage = {
|
const delete_form: DeleteImage = {
|
||||||
token: upload.files![0].delete_token,
|
token: upload.files![0].delete_token,
|
||||||
|
|
|
@ -887,8 +887,8 @@ export async function deleteAllImages(api: LemmyHttp) {
|
||||||
|
|
||||||
for (const image of imagesRes.images) {
|
for (const image of imagesRes.images) {
|
||||||
const form: DeleteImage = {
|
const form: DeleteImage = {
|
||||||
token: image.pictrs_delete_token,
|
token: image.local_image.pictrs_delete_token,
|
||||||
filename: image.pictrs_alias,
|
filename: image.local_image.pictrs_alias,
|
||||||
};
|
};
|
||||||
await api.deleteImage(form);
|
await api.deleteImage(form);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,7 @@ use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
person::{ListMedia, ListMediaResponse},
|
person::{ListMedia, ListMediaResponse},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::images::LocalImage;
|
use lemmy_db_views::structs::{LocalImageView, LocalUserView};
|
||||||
use lemmy_db_views::structs::LocalUserView;
|
|
||||||
use lemmy_utils::error::LemmyResult;
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
|
||||||
#[tracing::instrument(skip(context))]
|
#[tracing::instrument(skip(context))]
|
||||||
|
@ -15,7 +14,7 @@ pub async fn list_media(
|
||||||
) -> LemmyResult<Json<ListMediaResponse>> {
|
) -> LemmyResult<Json<ListMediaResponse>> {
|
||||||
let page = data.page;
|
let page = data.page;
|
||||||
let limit = data.limit;
|
let limit = data.limit;
|
||||||
let images = LocalImage::get_all_paged_by_local_user_id(
|
let images = LocalImageView::get_all_paged_by_local_user_id(
|
||||||
&mut context.pool(),
|
&mut context.pool(),
|
||||||
local_user_view.local_user.id,
|
local_user_view.local_user.id,
|
||||||
page,
|
page,
|
||||||
|
|
|
@ -4,8 +4,7 @@ use lemmy_api_common::{
|
||||||
person::{ListMedia, ListMediaResponse},
|
person::{ListMedia, ListMediaResponse},
|
||||||
utils::is_admin,
|
utils::is_admin,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::images::LocalImage;
|
use lemmy_db_views::structs::{LocalImageView, LocalUserView};
|
||||||
use lemmy_db_views::structs::LocalUserView;
|
|
||||||
use lemmy_utils::error::LemmyResult;
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
|
||||||
#[tracing::instrument(skip(context))]
|
#[tracing::instrument(skip(context))]
|
||||||
|
@ -19,6 +18,6 @@ pub async fn list_all_media(
|
||||||
|
|
||||||
let page = data.page;
|
let page = data.page;
|
||||||
let limit = data.limit;
|
let limit = data.limit;
|
||||||
let images = LocalImage::get_all(&mut context.pool(), page, limit).await?;
|
let images = LocalImageView::get_all(&mut context.pool(), page, limit).await?;
|
||||||
Ok(Json(ListMediaResponse { images }))
|
Ok(Json(ListMediaResponse { images }))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use crate::sensitive::Sensitive;
|
use crate::sensitive::Sensitive;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::{CommentReplyId, CommunityId, LanguageId, PersonId, PersonMentionId},
|
newtypes::{CommentReplyId, CommunityId, LanguageId, PersonId, PersonMentionId},
|
||||||
source::{images::LocalImage, site::Site},
|
source::site::Site,
|
||||||
CommentSortType,
|
CommentSortType,
|
||||||
ListingType,
|
ListingType,
|
||||||
PostListingMode,
|
PostListingMode,
|
||||||
SortType,
|
SortType,
|
||||||
};
|
};
|
||||||
use lemmy_db_views::structs::{CommentView, PostView};
|
use lemmy_db_views::structs::{CommentView, LocalImageView, PostView};
|
||||||
use lemmy_db_views_actor::structs::{
|
use lemmy_db_views_actor::structs::{
|
||||||
CommentReplyView,
|
CommentReplyView,
|
||||||
CommunityModeratorView,
|
CommunityModeratorView,
|
||||||
|
@ -437,5 +437,5 @@ pub struct ListMedia {
|
||||||
#[cfg_attr(feature = "full", derive(TS))]
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
pub struct ListMediaResponse {
|
pub struct ListMediaResponse {
|
||||||
pub images: Vec<LocalImage>,
|
pub images: Vec<LocalImageView>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ use lemmy_db_schema::{
|
||||||
community::{Community, CommunityModerator, CommunityUpdateForm},
|
community::{Community, CommunityModerator, CommunityUpdateForm},
|
||||||
community_block::CommunityBlock,
|
community_block::CommunityBlock,
|
||||||
email_verification::{EmailVerification, EmailVerificationForm},
|
email_verification::{EmailVerification, EmailVerificationForm},
|
||||||
images::{LocalImage, RemoteImage},
|
images::RemoteImage,
|
||||||
instance::Instance,
|
instance::Instance,
|
||||||
instance_block::InstanceBlock,
|
instance_block::InstanceBlock,
|
||||||
local_site::LocalSite,
|
local_site::LocalSite,
|
||||||
|
@ -27,7 +27,10 @@ use lemmy_db_schema::{
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
utils::DbPool,
|
utils::DbPool,
|
||||||
};
|
};
|
||||||
use lemmy_db_views::{comment_view::CommentQuery, structs::LocalUserView};
|
use lemmy_db_views::{
|
||||||
|
comment_view::CommentQuery,
|
||||||
|
structs::{LocalImageView, LocalUserView},
|
||||||
|
};
|
||||||
use lemmy_db_views_actor::structs::{
|
use lemmy_db_views_actor::structs::{
|
||||||
CommunityModeratorView,
|
CommunityModeratorView,
|
||||||
CommunityPersonBanView,
|
CommunityPersonBanView,
|
||||||
|
@ -662,11 +665,16 @@ pub async fn purge_image_posts_for_person(
|
||||||
async fn delete_local_user_images(person_id: PersonId, context: &LemmyContext) -> LemmyResult<()> {
|
async fn delete_local_user_images(person_id: PersonId, context: &LemmyContext) -> LemmyResult<()> {
|
||||||
if let Ok(Some(local_user)) = LocalUserView::read_person(&mut context.pool(), person_id).await {
|
if let Ok(Some(local_user)) = LocalUserView::read_person(&mut context.pool(), person_id).await {
|
||||||
let pictrs_uploads =
|
let pictrs_uploads =
|
||||||
LocalImage::get_all_by_local_user_id(&mut context.pool(), local_user.local_user.id).await?;
|
LocalImageView::get_all_by_local_user_id(&mut context.pool(), local_user.local_user.id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Delete their images
|
// Delete their images
|
||||||
for upload in pictrs_uploads {
|
for upload in pictrs_uploads {
|
||||||
delete_image_from_pictrs(&upload.pictrs_alias, &upload.pictrs_delete_token, context)
|
delete_image_from_pictrs(
|
||||||
|
&upload.local_image.pictrs_alias,
|
||||||
|
&upload.local_image.pictrs_delete_token,
|
||||||
|
context,
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
newtypes::{DbUrl, LocalUserId},
|
newtypes::DbUrl,
|
||||||
schema::{local_image, remote_image},
|
schema::{local_image, remote_image},
|
||||||
source::images::{LocalImage, LocalImageForm, RemoteImage, RemoteImageForm},
|
source::images::{LocalImage, LocalImageForm, RemoteImage, RemoteImageForm},
|
||||||
utils::{get_conn, limit_and_offset, DbPool},
|
utils::{get_conn, DbPool},
|
||||||
};
|
};
|
||||||
use diesel::{
|
use diesel::{
|
||||||
dsl::exists,
|
dsl::exists,
|
||||||
|
@ -25,55 +25,6 @@ impl LocalImage {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_all_paged_by_local_user_id(
|
|
||||||
pool: &mut DbPool<'_>,
|
|
||||||
user_id: LocalUserId,
|
|
||||||
page: Option<i64>,
|
|
||||||
limit: Option<i64>,
|
|
||||||
) -> Result<Vec<Self>, Error> {
|
|
||||||
Self::get_all_helper(pool, Some(user_id), page, limit, false).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_all_by_local_user_id(
|
|
||||||
pool: &mut DbPool<'_>,
|
|
||||||
user_id: LocalUserId,
|
|
||||||
) -> Result<Vec<Self>, Error> {
|
|
||||||
Self::get_all_helper(pool, Some(user_id), None, None, true).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_all(
|
|
||||||
pool: &mut DbPool<'_>,
|
|
||||||
page: Option<i64>,
|
|
||||||
limit: Option<i64>,
|
|
||||||
) -> Result<Vec<Self>, Error> {
|
|
||||||
Self::get_all_helper(pool, None, page, limit, false).await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_helper(
|
|
||||||
pool: &mut DbPool<'_>,
|
|
||||||
user_id: Option<LocalUserId>,
|
|
||||||
page: Option<i64>,
|
|
||||||
limit: Option<i64>,
|
|
||||||
ignore_page_limits: bool,
|
|
||||||
) -> Result<Vec<Self>, Error> {
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
let mut query = local_image::table
|
|
||||||
.select(local_image::all_columns)
|
|
||||||
.order_by(local_image::published.desc())
|
|
||||||
.into_boxed();
|
|
||||||
|
|
||||||
if let Some(user_id) = user_id {
|
|
||||||
query = query.filter(local_image::local_user_id.eq(user_id))
|
|
||||||
}
|
|
||||||
|
|
||||||
if !ignore_page_limits {
|
|
||||||
let (limit, offset) = limit_and_offset(page, limit)?;
|
|
||||||
query = query.limit(limit).offset(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
query.load::<LocalImage>(conn).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn delete_by_alias(pool: &mut DbPool<'_>, alias: &str) -> Result<Self, Error> {
|
pub async fn delete_by_alias(pool: &mut DbPool<'_>, alias: &str) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
diesel::delete(local_image::table.filter(local_image::pictrs_alias.eq(alias)))
|
diesel::delete(local_image::table.filter(local_image::pictrs_alias.eq(alias)))
|
||||||
|
|
|
@ -8,6 +8,8 @@ pub mod comment_view;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod custom_emoji_view;
|
pub mod custom_emoji_view;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
|
pub mod local_image_view;
|
||||||
|
#[cfg(feature = "full")]
|
||||||
pub mod local_user_view;
|
pub mod local_user_view;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod post_report_view;
|
pub mod post_report_view;
|
||||||
|
|
61
crates/db_views/src/local_image_view.rs
Normal file
61
crates/db_views/src/local_image_view.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
use crate::structs::LocalImageView;
|
||||||
|
use diesel::{result::Error, ExpressionMethods, JoinOnDsl, QueryDsl};
|
||||||
|
use diesel_async::RunQueryDsl;
|
||||||
|
use lemmy_db_schema::{
|
||||||
|
newtypes::LocalUserId,
|
||||||
|
schema::{local_image, local_user, person},
|
||||||
|
utils::{get_conn, limit_and_offset, DbPool},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl LocalImageView {
|
||||||
|
async fn get_all_helper(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
user_id: Option<LocalUserId>,
|
||||||
|
page: Option<i64>,
|
||||||
|
limit: Option<i64>,
|
||||||
|
ignore_page_limits: bool,
|
||||||
|
) -> Result<Vec<Self>, Error> {
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
let mut query = local_image::table
|
||||||
|
.inner_join(local_user::table)
|
||||||
|
.inner_join(person::table.on(local_user::person_id.eq(person::id)))
|
||||||
|
.select((local_image::all_columns, person::all_columns))
|
||||||
|
.order_by(local_image::published.desc())
|
||||||
|
.into_boxed();
|
||||||
|
|
||||||
|
if let Some(user_id) = user_id {
|
||||||
|
query = query.filter(local_image::local_user_id.eq(user_id))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ignore_page_limits {
|
||||||
|
let (limit, offset) = limit_and_offset(page, limit)?;
|
||||||
|
query = query.limit(limit).offset(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
query.load::<LocalImageView>(conn).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_all_paged_by_local_user_id(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
user_id: LocalUserId,
|
||||||
|
page: Option<i64>,
|
||||||
|
limit: Option<i64>,
|
||||||
|
) -> Result<Vec<Self>, Error> {
|
||||||
|
Self::get_all_helper(pool, Some(user_id), page, limit, false).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_all_by_local_user_id(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
user_id: LocalUserId,
|
||||||
|
) -> Result<Vec<Self>, Error> {
|
||||||
|
Self::get_all_helper(pool, Some(user_id), None, None, true).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_all(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
page: Option<i64>,
|
||||||
|
limit: Option<i64>,
|
||||||
|
) -> Result<Vec<Self>, Error> {
|
||||||
|
Self::get_all_helper(pool, None, page, limit, false).await
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ use lemmy_db_schema::{
|
||||||
community::Community,
|
community::Community,
|
||||||
custom_emoji::CustomEmoji,
|
custom_emoji::CustomEmoji,
|
||||||
custom_emoji_keyword::CustomEmojiKeyword,
|
custom_emoji_keyword::CustomEmojiKeyword,
|
||||||
|
images::LocalImage,
|
||||||
local_site::LocalSite,
|
local_site::LocalSite,
|
||||||
local_site_rate_limit::LocalSiteRateLimit,
|
local_site_rate_limit::LocalSiteRateLimit,
|
||||||
local_user::LocalUser,
|
local_user::LocalUser,
|
||||||
|
@ -214,3 +215,13 @@ pub struct VoteView {
|
||||||
pub creator_banned_from_community: bool,
|
pub creator_banned_from_community: bool,
|
||||||
pub score: i16,
|
pub score: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// A local image view.
|
||||||
|
pub struct LocalImageView {
|
||||||
|
pub local_image: LocalImage,
|
||||||
|
pub person: Person,
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue