chore: update code to maybe final version

This commit is contained in:
phiresky 2024-12-13 13:59:28 +01:00
parent fcd7c6d0eb
commit 03b850ed75
10 changed files with 52 additions and 133 deletions

View file

@ -1,13 +1,7 @@
use crate::{ use crate::{
newtypes::{CommunityId, TagId}, newtypes::TagId,
schema::{community_post_tag, post_tag, tag}, schema::{post_tag, tag},
source::community_post_tag::{ source::tag::{PostTagInsertForm, Tag, TagInsertForm},
CommunityPostTag,
CommunityPostTagInsertForm,
PostTagInsertForm,
Tag,
TagInsertForm,
},
traits::Crud, traits::Crud,
utils::{get_conn, DbPool}, utils::{get_conn, DbPool},
}; };
@ -45,35 +39,6 @@ impl Crud for Tag {
} }
} }
#[async_trait]
impl Crud for CommunityPostTag {
type InsertForm = CommunityPostTagInsertForm;
type UpdateForm = CommunityPostTagInsertForm;
type IdType = (CommunityId, TagId);
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
let conn = &mut get_conn(pool).await?;
insert_into(community_post_tag::table)
.values(form)
.get_result::<Self>(conn)
.await
}
async fn update(
pool: &mut DbPool<'_>,
pid: (CommunityId, TagId),
form: &Self::UpdateForm,
) -> Result<Self, Error> {
let conn = &mut get_conn(pool).await?;
diesel::update(community_post_tag::table.find(pid))
.set(form)
.get_result::<Self>(conn)
.await
}
}
impl PostTagInsertForm { impl PostTagInsertForm {
pub async fn insert_tag_associations( pub async fn insert_tag_associations(
pool: &mut DbPool<'_>, pool: &mut DbPool<'_>,

View file

@ -263,14 +263,6 @@ diesel::table! {
} }
} }
diesel::table! {
community_post_tag (community_id, tag_id) {
community_id -> Int4,
tag_id -> Int4,
published -> Timestamptz,
}
}
diesel::table! { diesel::table! {
custom_emoji (id) { custom_emoji (id) {
id -> Int4, id -> Int4,
@ -972,9 +964,10 @@ diesel::table! {
id -> Int4, id -> Int4,
ap_id -> Text, ap_id -> Text,
name -> Text, name -> Text,
community_id -> Int4,
published -> Timestamptz, published -> Timestamptz,
updated -> Nullable<Timestamptz>, updated -> Nullable<Timestamptz>,
deleted -> Nullable<Timestamptz>, deleted -> Bool,
} }
} }
@ -1011,8 +1004,6 @@ diesel::joinable!(community_actions -> community (community_id));
diesel::joinable!(community_aggregates -> community (community_id)); diesel::joinable!(community_aggregates -> community (community_id));
diesel::joinable!(community_language -> community (community_id)); diesel::joinable!(community_language -> community (community_id));
diesel::joinable!(community_language -> language (language_id)); diesel::joinable!(community_language -> language (language_id));
diesel::joinable!(community_post_tag -> community (community_id));
diesel::joinable!(community_post_tag -> tag (tag_id));
diesel::joinable!(custom_emoji_keyword -> custom_emoji (custom_emoji_id)); diesel::joinable!(custom_emoji_keyword -> custom_emoji (custom_emoji_id));
diesel::joinable!(email_verification -> local_user (local_user_id)); diesel::joinable!(email_verification -> local_user (local_user_id));
diesel::joinable!(federation_allowlist -> instance (instance_id)); diesel::joinable!(federation_allowlist -> instance (instance_id));
@ -1070,6 +1061,7 @@ diesel::joinable!(site -> instance (instance_id));
diesel::joinable!(site_aggregates -> site (site_id)); diesel::joinable!(site_aggregates -> site (site_id));
diesel::joinable!(site_language -> language (language_id)); diesel::joinable!(site_language -> language (language_id));
diesel::joinable!(site_language -> site (site_id)); diesel::joinable!(site_language -> site (site_id));
diesel::joinable!(tag -> community (community_id));
diesel::allow_tables_to_appear_in_same_query!( diesel::allow_tables_to_appear_in_same_query!(
admin_allow_instance, admin_allow_instance,
@ -1088,7 +1080,6 @@ diesel::allow_tables_to_appear_in_same_query!(
community_actions, community_actions,
community_aggregates, community_aggregates,
community_language, community_language,
community_post_tag,
custom_emoji, custom_emoji,
custom_emoji_keyword, custom_emoji_keyword,
email_verification, email_verification,

View file

@ -10,7 +10,6 @@ pub mod comment_reply;
pub mod comment_report; pub mod comment_report;
pub mod community; pub mod community;
pub mod community_block; pub mod community_block;
pub mod community_post_tag;
pub mod custom_emoji; pub mod custom_emoji;
pub mod custom_emoji_keyword; pub mod custom_emoji_keyword;
pub mod email_verification; pub mod email_verification;
@ -41,6 +40,7 @@ pub mod private_message_report;
pub mod registration_application; pub mod registration_application;
pub mod secret; pub mod secret;
pub mod site; pub mod site;
pub mod tag;
pub mod tagline; pub mod tagline;
/// Default value for columns like [community::Community.inbox_url] which are marked as serde(skip). /// Default value for columns like [community::Community.inbox_url] which are marked as serde(skip).

View file

@ -1,6 +1,6 @@
use crate::newtypes::{CommunityId, DbUrl, PostId, TagId}; use crate::newtypes::{CommunityId, DbUrl, PostId, TagId};
#[cfg(feature = "full")] #[cfg(feature = "full")]
use crate::schema::{community_post_tag, post_tag, tag}; use crate::schema::{post_tag, tag};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none; use serde_with::skip_serializing_none;
@ -10,6 +10,13 @@ use ts_rs::TS;
/// A tag that can be assigned to a post within a community. /// A tag that can be assigned to a post within a community.
/// The tag object is created by the community moderators. /// The tag object is created by the community moderators.
/// The assignment happens by the post creator and can be updated by the community moderators. /// The assignment happens by the post creator and can be updated by the community moderators.
///
/// A tag is a federatable object that gives additional context to another object, which can be
/// displayed and filtered on currently, we only have community post tags, which is a tag that is
/// created by post authors as well as mods of a community, to categorize a post. in the future we
/// may add more tag types, depending on the requirements, this will lead to either expansion of
/// this table (community_id optional, addition of tag_type enum) or split of this table / creation
/// of new tables.
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "full", derive(TS, Queryable, Selectable, Identifiable))] #[cfg_attr(feature = "full", derive(TS, Queryable, Selectable, Identifiable))]
@ -20,22 +27,11 @@ pub struct Tag {
pub id: TagId, pub id: TagId,
pub ap_id: DbUrl, pub ap_id: DbUrl,
pub name: String, pub name: String,
/// the community that owns this tag
pub community_id: CommunityId,
pub published: DateTime<Utc>, pub published: DateTime<Utc>,
pub updated: Option<DateTime<Utc>>, pub updated: Option<DateTime<Utc>>,
pub deleted: Option<DateTime<Utc>>, pub deleted: bool,
}
#[skip_serializing_none]
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "full", derive(TS, Queryable, Selectable, Identifiable))]
#[cfg_attr(feature = "full", diesel(table_name = community_post_tag))]
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
#[cfg_attr(feature = "full", diesel(primary_key(community_id, tag_id)))]
#[cfg_attr(feature = "full", ts(export))]
pub struct CommunityPostTag {
pub community_id: CommunityId,
pub tag_id: TagId,
pub published: DateTime<Utc>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -44,19 +40,11 @@ pub struct CommunityPostTag {
pub struct TagInsertForm { pub struct TagInsertForm {
pub ap_id: DbUrl, pub ap_id: DbUrl,
pub name: String, pub name: String,
pub community_id: CommunityId,
// default now // default now
pub published: Option<DateTime<Utc>>, pub published: Option<DateTime<Utc>>,
pub updated: Option<DateTime<Utc>>, pub updated: Option<DateTime<Utc>>,
pub deleted: Option<DateTime<Utc>>, pub deleted: bool,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
#[cfg_attr(feature = "full", diesel(table_name = community_post_tag))]
pub struct CommunityPostTagInsertForm {
pub community_id: CommunityId,
pub tag_id: TagId,
pub published: Option<DateTime<Utc>>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View file

@ -6,8 +6,6 @@ pub mod comment_report_view;
#[cfg(feature = "full")] #[cfg(feature = "full")]
pub mod comment_view; pub mod comment_view;
#[cfg(feature = "full")] #[cfg(feature = "full")]
pub mod community_post_tags_view;
#[cfg(feature = "full")]
pub mod custom_emoji_view; pub mod custom_emoji_view;
#[cfg(feature = "full")] #[cfg(feature = "full")]
pub mod local_image_view; pub mod local_image_view;
@ -16,6 +14,8 @@ pub mod local_user_view;
#[cfg(feature = "full")] #[cfg(feature = "full")]
pub mod post_report_view; pub mod post_report_view;
#[cfg(feature = "full")] #[cfg(feature = "full")]
pub mod post_tags_view;
#[cfg(feature = "full")]
pub mod post_view; pub mod post_view;
#[cfg(feature = "full")] #[cfg(feature = "full")]
pub mod private_message_report_view; pub mod private_message_report_view;

View file

@ -1,4 +1,5 @@
use crate::structs::PostCommunityPostTags; //! see post_view.rs for the reason for this json decoding
use crate::structs::PostTags;
use diesel::{ use diesel::{
deserialize::FromSql, deserialize::FromSql,
pg::{Pg, PgValue}, pg::{Pg, PgValue},
@ -6,10 +7,10 @@ use diesel::{
sql_types::{self, Nullable}, sql_types::{self, Nullable},
}; };
impl FromSql<Nullable<sql_types::Json>, Pg> for PostCommunityPostTags { impl FromSql<Nullable<sql_types::Json>, Pg> for PostTags {
fn from_sql(bytes: PgValue) -> diesel::deserialize::Result<Self> { fn from_sql(bytes: PgValue) -> diesel::deserialize::Result<Self> {
let value = <serde_json::Value as FromSql<sql_types::Json, Pg>>::from_sql(bytes)?; let value = <serde_json::Value as FromSql<sql_types::Json, Pg>>::from_sql(bytes)?;
Ok(serde_json::from_value::<PostCommunityPostTags>(value)?) Ok(serde_json::from_value::<PostTags>(value)?)
} }
fn from_nullable_sql( fn from_nullable_sql(
bytes: Option<<Pg as diesel::backend::Backend>::RawValue<'_>>, bytes: Option<<Pg as diesel::backend::Backend>::RawValue<'_>>,
@ -21,7 +22,7 @@ impl FromSql<Nullable<sql_types::Json>, Pg> for PostCommunityPostTags {
} }
} }
impl ToSql<Nullable<sql_types::Json>, Pg> for PostCommunityPostTags { impl ToSql<Nullable<sql_types::Json>, Pg> for PostTags {
fn to_sql(&self, out: &mut diesel::serialize::Output<Pg>) -> diesel::serialize::Result { fn to_sql(&self, out: &mut diesel::serialize::Output<Pg>) -> diesel::serialize::Result {
let value = serde_json::to_value(self)?; let value = serde_json::to_value(self)?;
<serde_json::Value as ToSql<sql_types::Json, Pg>>::to_sql(&value, &mut out.reborrow()) <serde_json::Value as ToSql<sql_types::Json, Pg>>::to_sql(&value, &mut out.reborrow())

View file

@ -106,6 +106,7 @@ fn queries<'a>() -> Queries<
"json_agg(tag.*)", "json_agg(tag.*)",
)) ))
.filter(post_tag::post_id.eq(post_aggregates::post_id)) .filter(post_tag::post_id.eq(post_aggregates::post_id))
.filter(tag::deleted.eq(false))
.single_value(), .single_value(),
); );
query query
@ -638,7 +639,7 @@ impl<'a> PostQuery<'a> {
mod tests { mod tests {
use crate::{ use crate::{
post_view::{PaginationCursorData, PostQuery, PostView}, post_view::{PaginationCursorData, PostQuery, PostView},
structs::{LocalUserView, PostCommunityPostTags}, structs::{LocalUserView, PostTags},
}; };
use chrono::Utc; use chrono::Utc;
use diesel_async::SimpleAsyncConnection; use diesel_async::SimpleAsyncConnection;
@ -662,13 +663,6 @@ mod tests {
CommunityUpdateForm, CommunityUpdateForm,
}, },
community_block::{CommunityBlock, CommunityBlockForm}, community_block::{CommunityBlock, CommunityBlockForm},
community_post_tag::{
CommunityPostTag,
CommunityPostTagInsertForm,
PostTagInsertForm,
Tag,
TagInsertForm,
},
instance::Instance, instance::Instance,
instance_block::{InstanceBlock, InstanceBlockForm}, instance_block::{InstanceBlock, InstanceBlockForm},
language::Language, language::Language,
@ -689,6 +683,7 @@ mod tests {
PostUpdateForm, PostUpdateForm,
}, },
site::Site, site::Site,
tag::{PostTagInsertForm, Tag, TagInsertForm},
}, },
traits::{Bannable, Blockable, Crud, Followable, Joinable, Likeable, Saveable}, traits::{Bannable, Blockable, Crud, Followable, Joinable, Likeable, Saveable},
utils::{build_db_pool, get_conn, uplete, ActualDbPool, DbPool, RANK_DEFAULT}, utils::{build_db_pool, get_conn, uplete, ActualDbPool, DbPool, RANK_DEFAULT},
@ -809,18 +804,10 @@ mod tests {
&TagInsertForm { &TagInsertForm {
ap_id: Url::parse(&format!("{}/tags/test_tag1", inserted_community.actor_id))?.into(), ap_id: Url::parse(&format!("{}/tags/test_tag1", inserted_community.actor_id))?.into(),
name: "Test Tag 1".into(), name: "Test Tag 1".into(),
community_id: inserted_community.id,
published: None, published: None,
updated: None, updated: None,
deleted: None, deleted: false,
},
)
.await?;
CommunityPostTag::create(
pool,
&CommunityPostTagInsertForm {
community_id: inserted_community.id,
tag_id: tag_1.id,
published: None,
}, },
) )
.await?; .await?;
@ -829,18 +816,10 @@ mod tests {
&TagInsertForm { &TagInsertForm {
ap_id: Url::parse(&format!("{}/tags/test_tag2", inserted_community.actor_id))?.into(), ap_id: Url::parse(&format!("{}/tags/test_tag2", inserted_community.actor_id))?.into(),
name: "Test Tag 2".into(), name: "Test Tag 2".into(),
community_id: inserted_community.id,
published: None, published: None,
updated: None, updated: None,
deleted: None, deleted: false,
},
)
.await?;
CommunityPostTag::create(
pool,
&CommunityPostTagInsertForm {
community_id: inserted_community.id,
tag_id: tag_2.id,
published: None,
}, },
) )
.await?; .await?;
@ -1921,7 +1900,7 @@ mod tests {
hidden: false, hidden: false,
saved: false, saved: false,
creator_blocked: false, creator_blocked: false,
community_post_tags: PostCommunityPostTags::default(), tags: PostTags::default(),
}) })
} }
@ -2236,14 +2215,14 @@ mod tests {
) )
.await?; .await?;
assert_eq!(2, post_view.community_post_tags.tags.len()); assert_eq!(2, post_view.tags.tags.len());
assert_eq!(data.tag_1.name, post_view.community_post_tags.tags[0].name); assert_eq!(data.tag_1.name, post_view.tags.tags[0].name);
assert_eq!(data.tag_2.name, post_view.community_post_tags.tags[1].name); assert_eq!(data.tag_2.name, post_view.tags.tags[1].name);
let all_posts = data.default_post_query().list(&data.site, pool).await?; let all_posts = data.default_post_query().list(&data.site, pool).await?;
assert_eq!(2, all_posts[0].community_post_tags.tags.len()); // post with tags assert_eq!(2, all_posts[0].tags.tags.len()); // post with tags
assert_eq!(0, all_posts[1].community_post_tags.tags.len()); // bot post assert_eq!(0, all_posts[1].tags.tags.len()); // bot post
assert_eq!(0, all_posts[2].community_post_tags.tags.len()); // normal post assert_eq!(0, all_posts[2].tags.tags.len()); // normal post
Ok(()) Ok(())
} }

View file

@ -8,7 +8,6 @@ use lemmy_db_schema::{
comment::Comment, comment::Comment,
comment_report::CommentReport, comment_report::CommentReport,
community::Community, community::Community,
community_post_tag::Tag,
custom_emoji::CustomEmoji, custom_emoji::CustomEmoji,
custom_emoji_keyword::CustomEmojiKeyword, custom_emoji_keyword::CustomEmojiKeyword,
images::{ImageDetails, LocalImage}, images::{ImageDetails, LocalImage},
@ -23,6 +22,7 @@ use lemmy_db_schema::{
private_message_report::PrivateMessageReport, private_message_report::PrivateMessageReport,
registration_application::RegistrationApplication, registration_application::RegistrationApplication,
site::Site, site::Site,
tag::Tag,
}, },
SubscribedType, SubscribedType,
}; };
@ -154,7 +154,7 @@ pub struct PostView {
#[cfg_attr(feature = "full", ts(optional))] #[cfg_attr(feature = "full", ts(optional))]
pub my_vote: Option<i16>, pub my_vote: Option<i16>,
pub unread_comments: i64, pub unread_comments: i64,
pub community_post_tags: PostCommunityPostTags, pub tags: PostTags,
} }
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)] #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
@ -246,6 +246,7 @@ pub struct LocalImageView {
#[cfg_attr(feature = "full", derive(TS, FromSqlRow, AsExpression))] #[cfg_attr(feature = "full", derive(TS, FromSqlRow, AsExpression))]
#[serde(transparent)] #[serde(transparent)]
#[cfg_attr(feature = "full", diesel(sql_type = Nullable<sql_types::Json>))] #[cfg_attr(feature = "full", diesel(sql_type = Nullable<sql_types::Json>))]
pub struct PostCommunityPostTags { /// we wrap this in a struct so we can implement FromSqlRow<Json> for it
pub struct PostTags {
pub tags: Vec<Tag>, pub tags: Vec<Tag>,
} }

View file

@ -1,7 +1,4 @@
-- This file should undo anything in `up.sql`
DROP TABLE post_tag; DROP TABLE post_tag;
DROP TABLE community_post_tag;
DROP TABLE tag; DROP TABLE tag;

View file

@ -1,19 +1,16 @@
-- a tag for a post, valid in a community. created by mods of a community -- a tag is a federatable object that gives additional context to another object, which can be displayed and filtered on
-- currently, we only have community post tags, which is a tag that is created by post authors as well as mods of a community,
-- to categorize a post. in the future we may add more tag types, depending on the requirements,
-- this will lead to either expansion of this table (community_id optional, addition of tag_type enum)
-- or split of this table / creation of new tables.
CREATE TABLE tag ( CREATE TABLE tag (
id serial PRIMARY KEY, id serial PRIMARY KEY,
ap_id text NOT NULL UNIQUE, ap_id text NOT NULL UNIQUE,
name text NOT NULL, name text NOT NULL,
community_id int NOT NULL REFERENCES community (id) ON UPDATE CASCADE ON DELETE CASCADE,
published timestamptz NOT NULL DEFAULT now(), published timestamptz NOT NULL DEFAULT now(),
updated timestamptz, updated timestamptz,
deleted timestamptz deleted boolean NOT NULL DEFAULT FALSE
);
-- indicates this tag was created by the mod of a community and can be applied to posts in this community
CREATE TABLE community_post_tag (
community_id int NOT NULL REFERENCES community (id) ON UPDATE CASCADE ON DELETE CASCADE,
tag_id int NOT NULL REFERENCES tag (id) ON UPDATE CASCADE ON DELETE CASCADE,
published timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (community_id, tag_id)
); );
-- an association between a post and a tag. created/updated by the post author or mods of a community -- an association between a post and a tag. created/updated by the post author or mods of a community