Feature/custom emoji and tagline views (#4580)
* Add custom_emoji list route * Add tagline list route * Apply linting * Remove unecessary TaglineView * Add category filter for custom emoji * Add create tagline endpoint * Add update tagline endpoint * Add delete tagline endpoint * Format through lint.sh * Remove custom_emojis and taglines from site resource * Get random tagline on site requets * Impl Crud for Tagline Remove superfluous properties * Move tagline endpoints under /admin * Impl Crud for CustomEmoji * Remove delete from tagline and custom emoji impls * Check markdown for tagline * Validate markdown on tagline * Make content fields non optional Add error types for tagline validation * Use process_markdown instead of process_markdown_opt * Consolidate Tagline error types * Remove unecessary clone * Updat misleading comments * Remove local_site_id from tagline and custom_emoji * Update TaglineInserForm and TaglineUpdateForm * Add ignore_page_limits for custom emojis EmojiPicker needs to be able to retrieve all emojis in 1 call * Update custom_emoji_view Only keep get_all als helper function calling list with paging ignored Only order on category when filtering on category * Removing pointless get_all fn. * remove tagline length checks * make fields of TaglineInsertForm and TaglineUpdateForm mandatory * move emoji order statement * add comment for GetSiteResponse.tagline --------- Co-authored-by: Freakazoid182 <> Co-authored-by: SleeplessOne1917 <28871516+SleeplessOne1917@users.noreply.github.com> Co-authored-by: Dessalines <tyhou13@gmx.com> Co-authored-by: Felix Ableitner <me@nutomic.com>
This commit is contained in:
parent
026e23cf32
commit
43f20881cb
29 changed files with 417 additions and 146 deletions
|
@ -12,7 +12,7 @@ use lemmy_db_schema::{
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
};
|
};
|
||||||
use lemmy_db_views::structs::{CustomEmojiView, LocalUserView, SiteView};
|
use lemmy_db_views::structs::{LocalUserView, SiteView};
|
||||||
use lemmy_db_views_actor::structs::PersonView;
|
use lemmy_db_views_actor::structs::PersonView;
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
error::{LemmyErrorType, LemmyResult},
|
error::{LemmyErrorType, LemmyResult},
|
||||||
|
@ -61,11 +61,9 @@ pub async fn leave_admin(
|
||||||
|
|
||||||
let all_languages = Language::read_all(&mut context.pool()).await?;
|
let all_languages = Language::read_all(&mut context.pool()).await?;
|
||||||
let discussion_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?;
|
let discussion_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?;
|
||||||
let taglines = Tagline::get_all(&mut context.pool(), site_view.local_site.id).await?;
|
|
||||||
let custom_emojis =
|
|
||||||
CustomEmojiView::get_all(&mut context.pool(), site_view.local_site.id).await?;
|
|
||||||
let oauth_providers = OAuthProvider::get_all_public(&mut context.pool()).await?;
|
let oauth_providers = OAuthProvider::get_all_public(&mut context.pool()).await?;
|
||||||
let blocked_urls = LocalSiteUrlBlocklist::get_all(&mut context.pool()).await?;
|
let blocked_urls = LocalSiteUrlBlocklist::get_all(&mut context.pool()).await?;
|
||||||
|
let tagline = Tagline::get_random(&mut context.pool()).await?;
|
||||||
|
|
||||||
Ok(Json(GetSiteResponse {
|
Ok(Json(GetSiteResponse {
|
||||||
site_view,
|
site_view,
|
||||||
|
@ -74,10 +72,9 @@ pub async fn leave_admin(
|
||||||
my_user: None,
|
my_user: None,
|
||||||
all_languages,
|
all_languages,
|
||||||
discussion_languages,
|
discussion_languages,
|
||||||
taglines,
|
|
||||||
custom_emojis,
|
|
||||||
oauth_providers: Some(oauth_providers),
|
oauth_providers: Some(oauth_providers),
|
||||||
admin_oauth_providers: None,
|
admin_oauth_providers: None,
|
||||||
blocked_urls,
|
blocked_urls,
|
||||||
|
tagline,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use lemmy_db_schema::newtypes::CustomEmojiId;
|
use lemmy_db_schema::newtypes::CustomEmojiId;
|
||||||
use lemmy_db_views::structs::CustomEmojiView;
|
use lemmy_db_views::structs::CustomEmojiView;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_with::skip_serializing_none;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -46,3 +47,23 @@ pub struct DeleteCustomEmoji {
|
||||||
pub struct CustomEmojiResponse {
|
pub struct CustomEmojiResponse {
|
||||||
pub custom_emoji: CustomEmojiView,
|
pub custom_emoji: CustomEmojiView,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// A response for custom emojis.
|
||||||
|
pub struct ListCustomEmojisResponse {
|
||||||
|
pub custom_emojis: Vec<CustomEmojiView>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[skip_serializing_none]
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// Fetches a list of custom emojis.
|
||||||
|
pub struct ListCustomEmojis {
|
||||||
|
pub page: Option<i64>,
|
||||||
|
pub limit: Option<i64>,
|
||||||
|
pub category: Option<String>,
|
||||||
|
pub ignore_page_limits: Option<bool>,
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ pub mod request;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod send_activity;
|
pub mod send_activity;
|
||||||
pub mod site;
|
pub mod site;
|
||||||
|
pub mod tagline;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ use lemmy_db_schema::{
|
||||||
};
|
};
|
||||||
use lemmy_db_views::structs::{
|
use lemmy_db_views::structs::{
|
||||||
CommentView,
|
CommentView,
|
||||||
CustomEmojiView,
|
|
||||||
LocalUserView,
|
LocalUserView,
|
||||||
PostView,
|
PostView,
|
||||||
RegistrationApplicationView,
|
RegistrationApplicationView,
|
||||||
|
@ -202,7 +201,6 @@ pub struct CreateSite {
|
||||||
pub captcha_difficulty: Option<String>,
|
pub captcha_difficulty: Option<String>,
|
||||||
pub allowed_instances: Option<Vec<String>>,
|
pub allowed_instances: Option<Vec<String>>,
|
||||||
pub blocked_instances: Option<Vec<String>>,
|
pub blocked_instances: Option<Vec<String>>,
|
||||||
pub taglines: Option<Vec<String>>,
|
|
||||||
pub registration_mode: Option<RegistrationMode>,
|
pub registration_mode: Option<RegistrationMode>,
|
||||||
pub oauth_registration: Option<bool>,
|
pub oauth_registration: Option<bool>,
|
||||||
pub content_warning: Option<String>,
|
pub content_warning: Option<String>,
|
||||||
|
@ -288,8 +286,6 @@ pub struct EditSite {
|
||||||
pub blocked_instances: Option<Vec<String>>,
|
pub blocked_instances: Option<Vec<String>>,
|
||||||
/// A list of blocked URLs
|
/// A list of blocked URLs
|
||||||
pub blocked_urls: Option<Vec<String>>,
|
pub blocked_urls: Option<Vec<String>>,
|
||||||
/// A list of taglines shown at the top of the front page.
|
|
||||||
pub taglines: Option<Vec<String>>,
|
|
||||||
pub registration_mode: Option<RegistrationMode>,
|
pub registration_mode: Option<RegistrationMode>,
|
||||||
/// Whether or not external auth methods can auto-register users.
|
/// Whether or not external auth methods can auto-register users.
|
||||||
pub oauth_registration: Option<bool>,
|
pub oauth_registration: Option<bool>,
|
||||||
|
@ -306,7 +302,6 @@ pub struct EditSite {
|
||||||
/// The response for a site.
|
/// The response for a site.
|
||||||
pub struct SiteResponse {
|
pub struct SiteResponse {
|
||||||
pub site_view: SiteView,
|
pub site_view: SiteView,
|
||||||
pub taglines: Vec<Tagline>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
|
@ -321,10 +316,8 @@ pub struct GetSiteResponse {
|
||||||
pub my_user: Option<MyUserInfo>,
|
pub my_user: Option<MyUserInfo>,
|
||||||
pub all_languages: Vec<Language>,
|
pub all_languages: Vec<Language>,
|
||||||
pub discussion_languages: Vec<LanguageId>,
|
pub discussion_languages: Vec<LanguageId>,
|
||||||
/// A list of taglines shown at the top of the front page.
|
/// If the site has any taglines, a random one is included here for displaying
|
||||||
pub taglines: Vec<Tagline>,
|
pub tagline: Option<Tagline>,
|
||||||
/// A list of custom emojis your site supports.
|
|
||||||
pub custom_emojis: Vec<CustomEmojiView>,
|
|
||||||
/// A list of external auth methods your site supports.
|
/// A list of external auth methods your site supports.
|
||||||
pub oauth_providers: Option<Vec<PublicOAuthProvider>>,
|
pub oauth_providers: Option<Vec<PublicOAuthProvider>>,
|
||||||
pub admin_oauth_providers: Option<Vec<OAuthProvider>>,
|
pub admin_oauth_providers: Option<Vec<OAuthProvider>>,
|
||||||
|
|
55
crates/api_common/src/tagline.rs
Normal file
55
crates/api_common/src/tagline.rs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
use lemmy_db_schema::{newtypes::TaglineId, source::tagline::Tagline};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_with::skip_serializing_none;
|
||||||
|
#[cfg(feature = "full")]
|
||||||
|
use ts_rs::TS;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// Create a tagline
|
||||||
|
pub struct CreateTagline {
|
||||||
|
pub content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// Update a tagline
|
||||||
|
pub struct UpdateTagline {
|
||||||
|
pub id: TaglineId,
|
||||||
|
pub content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// Delete a tagline
|
||||||
|
pub struct DeleteTagline {
|
||||||
|
pub id: TaglineId,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
pub struct TaglineResponse {
|
||||||
|
pub tagline: Tagline,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// A response for taglines.
|
||||||
|
pub struct ListTaglinesResponse {
|
||||||
|
pub taglines: Vec<Tagline>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[skip_serializing_none]
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, Copy, Default, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// Fetches a list of taglines.
|
||||||
|
pub struct ListTaglines {
|
||||||
|
pub page: Option<i64>,
|
||||||
|
pub limit: Option<i64>,
|
||||||
|
}
|
|
@ -5,10 +5,12 @@ use lemmy_api_common::{
|
||||||
custom_emoji::{CreateCustomEmoji, CustomEmojiResponse},
|
custom_emoji::{CreateCustomEmoji, CustomEmojiResponse},
|
||||||
utils::is_admin,
|
utils::is_admin,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::{
|
||||||
custom_emoji::{CustomEmoji, CustomEmojiInsertForm},
|
source::{
|
||||||
custom_emoji_keyword::{CustomEmojiKeyword, CustomEmojiKeywordInsertForm},
|
custom_emoji::{CustomEmoji, CustomEmojiInsertForm},
|
||||||
local_site::LocalSite,
|
custom_emoji_keyword::{CustomEmojiKeyword, CustomEmojiKeywordInsertForm},
|
||||||
|
},
|
||||||
|
traits::Crud,
|
||||||
};
|
};
|
||||||
use lemmy_db_views::structs::{CustomEmojiView, LocalUserView};
|
use lemmy_db_views::structs::{CustomEmojiView, LocalUserView};
|
||||||
use lemmy_utils::error::LemmyResult;
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
@ -19,12 +21,10 @@ pub async fn create_custom_emoji(
|
||||||
context: Data<LemmyContext>,
|
context: Data<LemmyContext>,
|
||||||
local_user_view: LocalUserView,
|
local_user_view: LocalUserView,
|
||||||
) -> LemmyResult<Json<CustomEmojiResponse>> {
|
) -> LemmyResult<Json<CustomEmojiResponse>> {
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
|
||||||
// Make sure user is an admin
|
// Make sure user is an admin
|
||||||
is_admin(&local_user_view)?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
let emoji_form = CustomEmojiInsertForm::builder()
|
let emoji_form = CustomEmojiInsertForm::builder()
|
||||||
.local_site_id(local_site.id)
|
|
||||||
.shortcode(data.shortcode.to_lowercase().trim().to_string())
|
.shortcode(data.shortcode.to_lowercase().trim().to_string())
|
||||||
.alt_text(data.alt_text.to_string())
|
.alt_text(data.alt_text.to_string())
|
||||||
.category(data.category.to_string())
|
.category(data.category.to_string())
|
||||||
|
|
|
@ -6,7 +6,7 @@ use lemmy_api_common::{
|
||||||
utils::is_admin,
|
utils::is_admin,
|
||||||
SuccessResponse,
|
SuccessResponse,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::custom_emoji::CustomEmoji;
|
use lemmy_db_schema::{source::custom_emoji::CustomEmoji, traits::Crud};
|
||||||
use lemmy_db_views::structs::LocalUserView;
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
use lemmy_utils::error::LemmyResult;
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
|
||||||
|
|
25
crates/api_crud/src/custom_emoji/list.rs
Normal file
25
crates/api_crud/src/custom_emoji/list.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
use actix_web::web::{Data, Json, Query};
|
||||||
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
custom_emoji::{ListCustomEmojis, ListCustomEmojisResponse},
|
||||||
|
};
|
||||||
|
use lemmy_db_views::structs::{CustomEmojiView, LocalUserView};
|
||||||
|
use lemmy_utils::error::LemmyError;
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(context))]
|
||||||
|
pub async fn list_custom_emojis(
|
||||||
|
data: Query<ListCustomEmojis>,
|
||||||
|
local_user_view: Option<LocalUserView>,
|
||||||
|
context: Data<LemmyContext>,
|
||||||
|
) -> Result<Json<ListCustomEmojisResponse>, LemmyError> {
|
||||||
|
let custom_emojis = CustomEmojiView::list(
|
||||||
|
&mut context.pool(),
|
||||||
|
&data.category,
|
||||||
|
data.page,
|
||||||
|
data.limit,
|
||||||
|
data.ignore_page_limits.unwrap_or(false),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(Json(ListCustomEmojisResponse { custom_emojis }))
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
pub mod create;
|
pub mod create;
|
||||||
pub mod delete;
|
pub mod delete;
|
||||||
|
pub mod list;
|
||||||
pub mod update;
|
pub mod update;
|
||||||
|
|
|
@ -5,10 +5,12 @@ use lemmy_api_common::{
|
||||||
custom_emoji::{CustomEmojiResponse, EditCustomEmoji},
|
custom_emoji::{CustomEmojiResponse, EditCustomEmoji},
|
||||||
utils::is_admin,
|
utils::is_admin,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::{
|
||||||
custom_emoji::{CustomEmoji, CustomEmojiUpdateForm},
|
source::{
|
||||||
custom_emoji_keyword::{CustomEmojiKeyword, CustomEmojiKeywordInsertForm},
|
custom_emoji::{CustomEmoji, CustomEmojiUpdateForm},
|
||||||
local_site::LocalSite,
|
custom_emoji_keyword::{CustomEmojiKeyword, CustomEmojiKeywordInsertForm},
|
||||||
|
},
|
||||||
|
traits::Crud,
|
||||||
};
|
};
|
||||||
use lemmy_db_views::structs::{CustomEmojiView, LocalUserView};
|
use lemmy_db_views::structs::{CustomEmojiView, LocalUserView};
|
||||||
use lemmy_utils::error::LemmyResult;
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
@ -19,12 +21,10 @@ pub async fn update_custom_emoji(
|
||||||
context: Data<LemmyContext>,
|
context: Data<LemmyContext>,
|
||||||
local_user_view: LocalUserView,
|
local_user_view: LocalUserView,
|
||||||
) -> LemmyResult<Json<CustomEmojiResponse>> {
|
) -> LemmyResult<Json<CustomEmojiResponse>> {
|
||||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
|
||||||
// Make sure user is an admin
|
// Make sure user is an admin
|
||||||
is_admin(&local_user_view)?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
let emoji_form = CustomEmojiUpdateForm::builder()
|
let emoji_form = CustomEmojiUpdateForm::builder()
|
||||||
.local_site_id(local_site.id)
|
|
||||||
.alt_text(data.alt_text.to_string())
|
.alt_text(data.alt_text.to_string())
|
||||||
.category(data.category.to_string())
|
.category(data.category.to_string())
|
||||||
.image_url(data.clone().image_url.into())
|
.image_url(data.clone().image_url.into())
|
||||||
|
|
|
@ -5,4 +5,5 @@ pub mod oauth_provider;
|
||||||
pub mod post;
|
pub mod post;
|
||||||
pub mod private_message;
|
pub mod private_message;
|
||||||
pub mod site;
|
pub mod site;
|
||||||
|
pub mod tagline;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
|
|
@ -20,7 +20,6 @@ use lemmy_db_schema::{
|
||||||
local_site::{LocalSite, LocalSiteUpdateForm},
|
local_site::{LocalSite, LocalSiteUpdateForm},
|
||||||
local_site_rate_limit::{LocalSiteRateLimit, LocalSiteRateLimitUpdateForm},
|
local_site_rate_limit::{LocalSiteRateLimit, LocalSiteRateLimitUpdateForm},
|
||||||
site::{Site, SiteUpdateForm},
|
site::{Site, SiteUpdateForm},
|
||||||
tagline::Tagline,
|
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
utils::{diesel_string_update, diesel_url_create, naive_now},
|
utils::{diesel_string_update, diesel_url_create, naive_now},
|
||||||
|
@ -135,17 +134,11 @@ pub async fn create_site(
|
||||||
|
|
||||||
let site_view = SiteView::read_local(&mut context.pool()).await?;
|
let site_view = SiteView::read_local(&mut context.pool()).await?;
|
||||||
|
|
||||||
let new_taglines = data.taglines.clone();
|
|
||||||
let taglines = Tagline::replace(&mut context.pool(), local_site.id, new_taglines).await?;
|
|
||||||
|
|
||||||
let rate_limit_config =
|
let rate_limit_config =
|
||||||
local_site_rate_limit_to_rate_limit_config(&site_view.local_site_rate_limit);
|
local_site_rate_limit_to_rate_limit_config(&site_view.local_site_rate_limit);
|
||||||
context.rate_limit_cell().set_config(rate_limit_config);
|
context.rate_limit_cell().set_config(rate_limit_config);
|
||||||
|
|
||||||
Ok(Json(SiteResponse {
|
Ok(Json(SiteResponse { site_view }))
|
||||||
site_view,
|
|
||||||
taglines,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_create_payload(local_site: &LocalSite, create_site: &CreateSite) -> LemmyResult<()> {
|
fn validate_create_payload(local_site: &LocalSite, create_site: &CreateSite) -> LemmyResult<()> {
|
||||||
|
|
|
@ -13,7 +13,7 @@ use lemmy_db_schema::source::{
|
||||||
person_block::PersonBlock,
|
person_block::PersonBlock,
|
||||||
tagline::Tagline,
|
tagline::Tagline,
|
||||||
};
|
};
|
||||||
use lemmy_db_views::structs::{CustomEmojiView, LocalUserView, SiteView};
|
use lemmy_db_views::structs::{LocalUserView, SiteView};
|
||||||
use lemmy_db_views_actor::structs::{CommunityFollowerView, CommunityModeratorView, PersonView};
|
use lemmy_db_views_actor::structs::{CommunityFollowerView, CommunityModeratorView, PersonView};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult},
|
error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||||
|
@ -42,10 +42,8 @@ pub async fn get_site(
|
||||||
let admins = PersonView::admins(&mut context.pool()).await?;
|
let admins = PersonView::admins(&mut context.pool()).await?;
|
||||||
let all_languages = Language::read_all(&mut context.pool()).await?;
|
let all_languages = Language::read_all(&mut context.pool()).await?;
|
||||||
let discussion_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?;
|
let discussion_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?;
|
||||||
let taglines = Tagline::get_all(&mut context.pool(), site_view.local_site.id).await?;
|
|
||||||
let custom_emojis =
|
|
||||||
CustomEmojiView::get_all(&mut context.pool(), site_view.local_site.id).await?;
|
|
||||||
let blocked_urls = LocalSiteUrlBlocklist::get_all(&mut context.pool()).await?;
|
let blocked_urls = LocalSiteUrlBlocklist::get_all(&mut context.pool()).await?;
|
||||||
|
let tagline = Tagline::get_random(&mut context.pool()).await?;
|
||||||
let admin_oauth_providers = OAuthProvider::get_all(&mut context.pool()).await?;
|
let admin_oauth_providers = OAuthProvider::get_all(&mut context.pool()).await?;
|
||||||
let oauth_providers =
|
let oauth_providers =
|
||||||
OAuthProvider::convert_providers_to_public(admin_oauth_providers.clone());
|
OAuthProvider::convert_providers_to_public(admin_oauth_providers.clone());
|
||||||
|
@ -57,9 +55,8 @@ pub async fn get_site(
|
||||||
my_user: None,
|
my_user: None,
|
||||||
all_languages,
|
all_languages,
|
||||||
discussion_languages,
|
discussion_languages,
|
||||||
taglines,
|
|
||||||
custom_emojis,
|
|
||||||
blocked_urls,
|
blocked_urls,
|
||||||
|
tagline,
|
||||||
oauth_providers: Some(oauth_providers),
|
oauth_providers: Some(oauth_providers),
|
||||||
admin_oauth_providers: Some(admin_oauth_providers),
|
admin_oauth_providers: Some(admin_oauth_providers),
|
||||||
})
|
})
|
||||||
|
|
|
@ -24,7 +24,6 @@ use lemmy_db_schema::{
|
||||||
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
||||||
local_user::LocalUser,
|
local_user::LocalUser,
|
||||||
site::{Site, SiteUpdateForm},
|
site::{Site, SiteUpdateForm},
|
||||||
tagline::Tagline,
|
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
utils::{diesel_string_update, diesel_url_update, naive_now},
|
utils::{diesel_string_update, diesel_url_update, naive_now},
|
||||||
|
@ -187,19 +186,13 @@ pub async fn update_site(
|
||||||
.with_lemmy_type(LemmyErrorType::CouldntSetAllEmailVerified)?;
|
.with_lemmy_type(LemmyErrorType::CouldntSetAllEmailVerified)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_taglines = data.taglines.clone();
|
|
||||||
let taglines = Tagline::replace(&mut context.pool(), local_site.id, new_taglines).await?;
|
|
||||||
|
|
||||||
let site_view = SiteView::read_local(&mut context.pool()).await?;
|
let site_view = SiteView::read_local(&mut context.pool()).await?;
|
||||||
|
|
||||||
let rate_limit_config =
|
let rate_limit_config =
|
||||||
local_site_rate_limit_to_rate_limit_config(&site_view.local_site_rate_limit);
|
local_site_rate_limit_to_rate_limit_config(&site_view.local_site_rate_limit);
|
||||||
context.rate_limit_cell().set_config(rate_limit_config);
|
context.rate_limit_cell().set_config(rate_limit_config);
|
||||||
|
|
||||||
Ok(Json(SiteResponse {
|
Ok(Json(SiteResponse { site_view }))
|
||||||
site_view,
|
|
||||||
taglines,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_update_payload(local_site: &LocalSite, edit_site: &EditSite) -> LemmyResult<()> {
|
fn validate_update_payload(local_site: &LocalSite, edit_site: &EditSite) -> LemmyResult<()> {
|
||||||
|
|
38
crates/api_crud/src/tagline/create.rs
Normal file
38
crates/api_crud/src/tagline/create.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
use activitypub_federation::config::Data;
|
||||||
|
use actix_web::web::Json;
|
||||||
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
tagline::{CreateTagline, TaglineResponse},
|
||||||
|
utils::{get_url_blocklist, is_admin, local_site_to_slur_regex, process_markdown},
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::{
|
||||||
|
source::{
|
||||||
|
local_site::LocalSite,
|
||||||
|
tagline::{Tagline, TaglineInsertForm},
|
||||||
|
},
|
||||||
|
traits::Crud,
|
||||||
|
};
|
||||||
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
|
use lemmy_utils::error::LemmyError;
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(context))]
|
||||||
|
pub async fn create_tagline(
|
||||||
|
data: Json<CreateTagline>,
|
||||||
|
context: Data<LemmyContext>,
|
||||||
|
local_user_view: LocalUserView,
|
||||||
|
) -> Result<Json<TaglineResponse>, LemmyError> {
|
||||||
|
// Make sure user is an admin
|
||||||
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
|
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||||
|
|
||||||
|
let slur_regex = local_site_to_slur_regex(&local_site);
|
||||||
|
let url_blocklist = get_url_blocklist(&context).await?;
|
||||||
|
let content = process_markdown(&data.content, &slur_regex, &url_blocklist, &context).await?;
|
||||||
|
|
||||||
|
let tagline_form = TaglineInsertForm { content };
|
||||||
|
|
||||||
|
let tagline = Tagline::create(&mut context.pool(), &tagline_form).await?;
|
||||||
|
|
||||||
|
Ok(Json(TaglineResponse { tagline }))
|
||||||
|
}
|
25
crates/api_crud/src/tagline/delete.rs
Normal file
25
crates/api_crud/src/tagline/delete.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
use activitypub_federation::config::Data;
|
||||||
|
use actix_web::web::Json;
|
||||||
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
tagline::DeleteTagline,
|
||||||
|
utils::is_admin,
|
||||||
|
SuccessResponse,
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::{source::tagline::Tagline, traits::Crud};
|
||||||
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
|
use lemmy_utils::error::LemmyError;
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(context))]
|
||||||
|
pub async fn delete_tagline(
|
||||||
|
data: Json<DeleteTagline>,
|
||||||
|
context: Data<LemmyContext>,
|
||||||
|
local_user_view: LocalUserView,
|
||||||
|
) -> Result<Json<SuccessResponse>, LemmyError> {
|
||||||
|
// Make sure user is an admin
|
||||||
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
|
Tagline::delete(&mut context.pool(), data.id).await?;
|
||||||
|
|
||||||
|
Ok(Json(SuccessResponse::default()))
|
||||||
|
}
|
19
crates/api_crud/src/tagline/list.rs
Normal file
19
crates/api_crud/src/tagline/list.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
use actix_web::web::{Data, Json, Query};
|
||||||
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
tagline::{ListTaglines, ListTaglinesResponse},
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::source::tagline::Tagline;
|
||||||
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
|
use lemmy_utils::error::LemmyError;
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(context))]
|
||||||
|
pub async fn list_taglines(
|
||||||
|
data: Query<ListTaglines>,
|
||||||
|
local_user_view: Option<LocalUserView>,
|
||||||
|
context: Data<LemmyContext>,
|
||||||
|
) -> Result<Json<ListTaglinesResponse>, LemmyError> {
|
||||||
|
let taglines = Tagline::list(&mut context.pool(), data.page, data.limit).await?;
|
||||||
|
|
||||||
|
Ok(Json(ListTaglinesResponse { taglines }))
|
||||||
|
}
|
4
crates/api_crud/src/tagline/mod.rs
Normal file
4
crates/api_crud/src/tagline/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
pub mod create;
|
||||||
|
pub mod delete;
|
||||||
|
pub mod list;
|
||||||
|
pub mod update;
|
42
crates/api_crud/src/tagline/update.rs
Normal file
42
crates/api_crud/src/tagline/update.rs
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
use activitypub_federation::config::Data;
|
||||||
|
use actix_web::web::Json;
|
||||||
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
tagline::{TaglineResponse, UpdateTagline},
|
||||||
|
utils::{get_url_blocklist, is_admin, local_site_to_slur_regex, process_markdown},
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::{
|
||||||
|
source::{
|
||||||
|
local_site::LocalSite,
|
||||||
|
tagline::{Tagline, TaglineUpdateForm},
|
||||||
|
},
|
||||||
|
traits::Crud,
|
||||||
|
utils::naive_now,
|
||||||
|
};
|
||||||
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
|
use lemmy_utils::error::LemmyError;
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(context))]
|
||||||
|
pub async fn update_tagline(
|
||||||
|
data: Json<UpdateTagline>,
|
||||||
|
context: Data<LemmyContext>,
|
||||||
|
local_user_view: LocalUserView,
|
||||||
|
) -> Result<Json<TaglineResponse>, LemmyError> {
|
||||||
|
// Make sure user is an admin
|
||||||
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
|
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||||
|
|
||||||
|
let slur_regex = local_site_to_slur_regex(&local_site);
|
||||||
|
let url_blocklist = get_url_blocklist(&context).await?;
|
||||||
|
let content = process_markdown(&data.content, &slur_regex, &url_blocklist, &context).await?;
|
||||||
|
|
||||||
|
let tagline_form = TaglineUpdateForm {
|
||||||
|
content,
|
||||||
|
updated: naive_now(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let tagline = Tagline::update(&mut context.pool(), data.id, &tagline_form).await?;
|
||||||
|
|
||||||
|
Ok(Json(TaglineResponse { tagline }))
|
||||||
|
}
|
|
@ -8,36 +8,37 @@ use crate::{
|
||||||
custom_emoji::{CustomEmoji, CustomEmojiInsertForm, CustomEmojiUpdateForm},
|
custom_emoji::{CustomEmoji, CustomEmojiInsertForm, CustomEmojiUpdateForm},
|
||||||
custom_emoji_keyword::{CustomEmojiKeyword, CustomEmojiKeywordInsertForm},
|
custom_emoji_keyword::{CustomEmojiKeyword, CustomEmojiKeywordInsertForm},
|
||||||
},
|
},
|
||||||
|
traits::Crud,
|
||||||
utils::{get_conn, DbPool},
|
utils::{get_conn, DbPool},
|
||||||
};
|
};
|
||||||
use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl};
|
use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl};
|
||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
|
|
||||||
impl CustomEmoji {
|
#[async_trait]
|
||||||
pub async fn create(pool: &mut DbPool<'_>, form: &CustomEmojiInsertForm) -> Result<Self, Error> {
|
impl Crud for CustomEmoji {
|
||||||
|
type InsertForm = CustomEmojiInsertForm;
|
||||||
|
type UpdateForm = CustomEmojiUpdateForm;
|
||||||
|
type IdType = CustomEmojiId;
|
||||||
|
|
||||||
|
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
insert_into(custom_emoji)
|
insert_into(custom_emoji)
|
||||||
.values(form)
|
.values(form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
pub async fn update(
|
|
||||||
|
async fn update(
|
||||||
pool: &mut DbPool<'_>,
|
pool: &mut DbPool<'_>,
|
||||||
emoji_id: CustomEmojiId,
|
emoji_id: Self::IdType,
|
||||||
form: &CustomEmojiUpdateForm,
|
new_custom_emoji: &Self::UpdateForm,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
diesel::update(custom_emoji.find(emoji_id))
|
diesel::update(custom_emoji.find(emoji_id))
|
||||||
.set(form)
|
.set(new_custom_emoji)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
pub async fn delete(pool: &mut DbPool<'_>, emoji_id: CustomEmojiId) -> Result<usize, Error> {
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
diesel::delete(custom_emoji.find(emoji_id))
|
|
||||||
.execute(conn)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CustomEmojiKeyword {
|
impl CustomEmojiKeyword {
|
||||||
|
|
|
@ -1,58 +1,64 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
newtypes::LocalSiteId,
|
newtypes::TaglineId,
|
||||||
schema::tagline::dsl::{local_site_id, tagline},
|
schema::tagline::dsl::{published, tagline},
|
||||||
source::tagline::{Tagline, TaglineForm},
|
source::tagline::{Tagline, TaglineInsertForm, TaglineUpdateForm},
|
||||||
utils::{get_conn, DbPool},
|
traits::Crud,
|
||||||
|
utils::{get_conn, limit_and_offset, DbPool},
|
||||||
};
|
};
|
||||||
use diesel::{insert_into, result::Error, ExpressionMethods, QueryDsl};
|
use diesel::{insert_into, result::Error, ExpressionMethods, OptionalExtension, QueryDsl};
|
||||||
use diesel_async::{AsyncPgConnection, RunQueryDsl};
|
use diesel_async::RunQueryDsl;
|
||||||
|
|
||||||
impl Tagline {
|
#[async_trait]
|
||||||
pub async fn replace(
|
impl Crud for Tagline {
|
||||||
pool: &mut DbPool<'_>,
|
type InsertForm = TaglineInsertForm;
|
||||||
for_local_site_id: LocalSiteId,
|
type UpdateForm = TaglineUpdateForm;
|
||||||
list_content: Option<Vec<String>>,
|
type IdType = TaglineId;
|
||||||
) -> Result<Vec<Self>, Error> {
|
|
||||||
|
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
if let Some(list) = list_content {
|
insert_into(tagline)
|
||||||
conn
|
.values(form)
|
||||||
.build_transaction()
|
.get_result::<Self>(conn)
|
||||||
.run(|conn| {
|
.await
|
||||||
Box::pin(async move {
|
|
||||||
Self::clear(conn).await?;
|
|
||||||
|
|
||||||
for item in list {
|
|
||||||
let form = TaglineForm {
|
|
||||||
local_site_id: for_local_site_id,
|
|
||||||
content: item,
|
|
||||||
updated: None,
|
|
||||||
};
|
|
||||||
insert_into(tagline)
|
|
||||||
.values(form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
Self::get_all(&mut conn.into(), for_local_site_id).await
|
|
||||||
}) as _
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
} else {
|
|
||||||
Self::get_all(&mut conn.into(), for_local_site_id).await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn clear(conn: &mut AsyncPgConnection) -> Result<usize, Error> {
|
async fn update(
|
||||||
diesel::delete(tagline).execute(conn).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_all(
|
|
||||||
pool: &mut DbPool<'_>,
|
pool: &mut DbPool<'_>,
|
||||||
for_local_site_id: LocalSiteId,
|
tagline_id: TaglineId,
|
||||||
) -> Result<Vec<Self>, Error> {
|
new_tagline: &Self::UpdateForm,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
tagline
|
diesel::update(tagline.find(tagline_id))
|
||||||
.filter(local_site_id.eq(for_local_site_id))
|
.set(new_tagline)
|
||||||
.get_results::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Tagline {
|
||||||
|
pub async fn list(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
page: Option<i64>,
|
||||||
|
limit: Option<i64>,
|
||||||
|
) -> Result<Vec<Self>, Error> {
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
let (limit, offset) = limit_and_offset(page, limit)?;
|
||||||
|
tagline
|
||||||
|
.order(published.desc())
|
||||||
|
.offset(offset)
|
||||||
|
.limit(limit)
|
||||||
|
.get_results::<Self>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_random(pool: &mut DbPool<'_>) -> Result<Option<Self>, Error> {
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
sql_function!(fn random() -> Text);
|
||||||
|
tagline
|
||||||
|
.order(random())
|
||||||
|
.limit(1)
|
||||||
|
.first::<Self>(conn)
|
||||||
|
.await
|
||||||
|
.optional()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -148,6 +148,12 @@ pub struct LocalSiteId(i32);
|
||||||
/// The custom emoji id.
|
/// The custom emoji id.
|
||||||
pub struct CustomEmojiId(i32);
|
pub struct CustomEmojiId(i32);
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||||
|
#[cfg_attr(feature = "full", derive(DieselNewType, TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// The tagline id.
|
||||||
|
pub struct TaglineId(i32);
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||||
#[cfg_attr(feature = "full", derive(DieselNewType, TS))]
|
#[cfg_attr(feature = "full", derive(DieselNewType, TS))]
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
|
|
@ -258,7 +258,6 @@ diesel::table! {
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
custom_emoji (id) {
|
custom_emoji (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
local_site_id -> Int4,
|
|
||||||
#[max_length = 128]
|
#[max_length = 128]
|
||||||
shortcode -> Varchar,
|
shortcode -> Varchar,
|
||||||
image_url -> Text,
|
image_url -> Text,
|
||||||
|
@ -974,7 +973,6 @@ diesel::table! {
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
tagline (id) {
|
tagline (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
local_site_id -> Int4,
|
|
||||||
content -> Text,
|
content -> Text,
|
||||||
published -> Timestamptz,
|
published -> Timestamptz,
|
||||||
updated -> Nullable<Timestamptz>,
|
updated -> Nullable<Timestamptz>,
|
||||||
|
@ -1011,7 +1009,6 @@ diesel::joinable!(community_moderator -> community (community_id));
|
||||||
diesel::joinable!(community_moderator -> person (person_id));
|
diesel::joinable!(community_moderator -> person (person_id));
|
||||||
diesel::joinable!(community_person_ban -> community (community_id));
|
diesel::joinable!(community_person_ban -> community (community_id));
|
||||||
diesel::joinable!(community_person_ban -> person (person_id));
|
diesel::joinable!(community_person_ban -> person (person_id));
|
||||||
diesel::joinable!(custom_emoji -> local_site (local_site_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));
|
||||||
|
@ -1075,7 +1072,6 @@ 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!(tagline -> local_site (local_site_id));
|
|
||||||
|
|
||||||
diesel::allow_tables_to_appear_in_same_query!(
|
diesel::allow_tables_to_appear_in_same_query!(
|
||||||
admin_purge_comment,
|
admin_purge_comment,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::newtypes::{CustomEmojiId, DbUrl, LocalSiteId};
|
use crate::newtypes::{CustomEmojiId, DbUrl};
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
use crate::schema::custom_emoji;
|
use crate::schema::custom_emoji;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
@ -10,21 +10,13 @@ use typed_builder::TypedBuilder;
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
|
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable, TS))]
|
||||||
feature = "full",
|
|
||||||
derive(Queryable, Selectable, Associations, Identifiable, TS)
|
|
||||||
)]
|
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = custom_emoji))]
|
#[cfg_attr(feature = "full", diesel(table_name = custom_emoji))]
|
||||||
#[cfg_attr(
|
|
||||||
feature = "full",
|
|
||||||
diesel(belongs_to(crate::source::local_site::LocalSite))
|
|
||||||
)]
|
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
/// A custom emoji.
|
/// A custom emoji.
|
||||||
pub struct CustomEmoji {
|
pub struct CustomEmoji {
|
||||||
pub id: CustomEmojiId,
|
pub id: CustomEmojiId,
|
||||||
pub local_site_id: LocalSiteId,
|
|
||||||
pub shortcode: String,
|
pub shortcode: String,
|
||||||
pub image_url: DbUrl,
|
pub image_url: DbUrl,
|
||||||
pub alt_text: String,
|
pub alt_text: String,
|
||||||
|
@ -37,7 +29,6 @@ pub struct CustomEmoji {
|
||||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = custom_emoji))]
|
#[cfg_attr(feature = "full", diesel(table_name = custom_emoji))]
|
||||||
pub struct CustomEmojiInsertForm {
|
pub struct CustomEmojiInsertForm {
|
||||||
pub local_site_id: LocalSiteId,
|
|
||||||
pub shortcode: String,
|
pub shortcode: String,
|
||||||
pub image_url: DbUrl,
|
pub image_url: DbUrl,
|
||||||
pub alt_text: String,
|
pub alt_text: String,
|
||||||
|
@ -48,7 +39,6 @@ pub struct CustomEmojiInsertForm {
|
||||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = custom_emoji))]
|
#[cfg_attr(feature = "full", diesel(table_name = custom_emoji))]
|
||||||
pub struct CustomEmojiUpdateForm {
|
pub struct CustomEmojiUpdateForm {
|
||||||
pub local_site_id: LocalSiteId,
|
|
||||||
pub image_url: DbUrl,
|
pub image_url: DbUrl,
|
||||||
pub alt_text: String,
|
pub alt_text: String,
|
||||||
pub category: String,
|
pub category: String,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use crate::newtypes::LocalSiteId;
|
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
use crate::schema::tagline;
|
use crate::schema::tagline;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
@ -9,21 +8,13 @@ use ts_rs::TS;
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
|
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable, TS))]
|
||||||
feature = "full",
|
|
||||||
derive(Queryable, Selectable, Associations, Identifiable, TS)
|
|
||||||
)]
|
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = tagline))]
|
#[cfg_attr(feature = "full", diesel(table_name = tagline))]
|
||||||
#[cfg_attr(
|
|
||||||
feature = "full",
|
|
||||||
diesel(belongs_to(crate::source::local_site::LocalSite))
|
|
||||||
)]
|
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
/// A tagline, shown at the top of your site.
|
/// A tagline, shown at the top of your site.
|
||||||
pub struct Tagline {
|
pub struct Tagline {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub local_site_id: LocalSiteId,
|
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub published: DateTime<Utc>,
|
pub published: DateTime<Utc>,
|
||||||
pub updated: Option<DateTime<Utc>>,
|
pub updated: Option<DateTime<Utc>>,
|
||||||
|
@ -32,8 +23,14 @@ pub struct Tagline {
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = tagline))]
|
#[cfg_attr(feature = "full", diesel(table_name = tagline))]
|
||||||
pub struct TaglineForm {
|
pub struct TaglineInsertForm {
|
||||||
pub local_site_id: LocalSiteId,
|
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub updated: Option<DateTime<Utc>>,
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(table_name = tagline))]
|
||||||
|
pub struct TaglineUpdateForm {
|
||||||
|
pub content: String,
|
||||||
|
pub updated: DateTime<Utc>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@ use crate::structs::CustomEmojiView;
|
||||||
use diesel::{result::Error, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl};
|
use diesel::{result::Error, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl};
|
||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::{CustomEmojiId, LocalSiteId},
|
newtypes::CustomEmojiId,
|
||||||
schema::{custom_emoji, custom_emoji_keyword},
|
schema::{custom_emoji, custom_emoji_keyword},
|
||||||
source::{custom_emoji::CustomEmoji, custom_emoji_keyword::CustomEmojiKeyword},
|
source::{custom_emoji::CustomEmoji, custom_emoji_keyword::CustomEmojiKeyword},
|
||||||
utils::{get_conn, DbPool},
|
utils::{get_conn, limit_and_offset, DbPool},
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
@ -35,18 +35,34 @@ impl CustomEmojiView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_all(
|
pub async fn list(
|
||||||
pool: &mut DbPool<'_>,
|
pool: &mut DbPool<'_>,
|
||||||
for_local_site_id: LocalSiteId,
|
category: &Option<String>,
|
||||||
|
page: Option<i64>,
|
||||||
|
limit: Option<i64>,
|
||||||
|
ignore_page_limits: bool,
|
||||||
) -> Result<Vec<Self>, Error> {
|
) -> Result<Vec<Self>, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
let emojis = custom_emoji::table
|
|
||||||
.filter(custom_emoji::local_site_id.eq(for_local_site_id))
|
let mut query = custom_emoji::table
|
||||||
.left_join(
|
.left_join(
|
||||||
custom_emoji_keyword::table.on(custom_emoji_keyword::custom_emoji_id.eq(custom_emoji::id)),
|
custom_emoji_keyword::table.on(custom_emoji_keyword::custom_emoji_id.eq(custom_emoji::id)),
|
||||||
)
|
)
|
||||||
.order(custom_emoji::category)
|
.order(custom_emoji::category)
|
||||||
.then_order_by(custom_emoji::id)
|
.into_boxed();
|
||||||
|
|
||||||
|
if !ignore_page_limits {
|
||||||
|
let (limit, offset) = limit_and_offset(page, limit)?;
|
||||||
|
query = query.limit(limit).offset(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(category) = category {
|
||||||
|
query = query.filter(custom_emoji::category.eq(category))
|
||||||
|
}
|
||||||
|
|
||||||
|
query = query.then_order_by(custom_emoji::id);
|
||||||
|
|
||||||
|
let emojis = query
|
||||||
.select((
|
.select((
|
||||||
custom_emoji::all_columns,
|
custom_emoji::all_columns,
|
||||||
custom_emoji_keyword::all_columns.nullable(), // (or all the columns if you want)
|
custom_emoji_keyword::all_columns.nullable(), // (or all the columns if you want)
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
ALTER TABLE custom_emoji
|
||||||
|
ADD COLUMN local_site_id int REFERENCES local_site (site_id) ON UPDATE CASCADE ON DELETE CASCADE;
|
||||||
|
|
||||||
|
UPDATE
|
||||||
|
custom_emoji
|
||||||
|
SET
|
||||||
|
local_site_id = (
|
||||||
|
SELECT
|
||||||
|
site_id
|
||||||
|
FROM
|
||||||
|
local_site
|
||||||
|
LIMIT 1);
|
||||||
|
|
||||||
|
ALTER TABLE custom_emoji
|
||||||
|
ALTER COLUMN local_site_id SET NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE tagline
|
||||||
|
ADD COLUMN local_site_id int REFERENCES local_site (site_id) ON UPDATE CASCADE ON DELETE CASCADE;
|
||||||
|
|
||||||
|
UPDATE
|
||||||
|
tagline
|
||||||
|
SET
|
||||||
|
local_site_id = (
|
||||||
|
SELECT
|
||||||
|
site_id
|
||||||
|
FROM
|
||||||
|
local_site
|
||||||
|
LIMIT 1);
|
||||||
|
|
||||||
|
ALTER TABLE tagline
|
||||||
|
ALTER COLUMN local_site_id SET NOT NULL;
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
ALTER TABLE custom_emoji
|
||||||
|
DROP COLUMN local_site_id;
|
||||||
|
|
||||||
|
ALTER TABLE tagline
|
||||||
|
DROP COLUMN local_site_id;
|
||||||
|
|
|
@ -107,6 +107,7 @@ use lemmy_api_crud::{
|
||||||
custom_emoji::{
|
custom_emoji::{
|
||||||
create::create_custom_emoji,
|
create::create_custom_emoji,
|
||||||
delete::delete_custom_emoji,
|
delete::delete_custom_emoji,
|
||||||
|
list::list_custom_emojis,
|
||||||
update::update_custom_emoji,
|
update::update_custom_emoji,
|
||||||
},
|
},
|
||||||
oauth_provider::{
|
oauth_provider::{
|
||||||
|
@ -128,6 +129,12 @@ use lemmy_api_crud::{
|
||||||
update::update_private_message,
|
update::update_private_message,
|
||||||
},
|
},
|
||||||
site::{create::create_site, read::get_site, update::update_site},
|
site::{create::create_site, read::get_site, update::update_site},
|
||||||
|
tagline::{
|
||||||
|
create::create_tagline,
|
||||||
|
delete::delete_tagline,
|
||||||
|
list::list_taglines,
|
||||||
|
update::update_tagline,
|
||||||
|
},
|
||||||
user::{
|
user::{
|
||||||
create::{authenticate_with_oauth, register},
|
create::{authenticate_with_oauth, register},
|
||||||
delete::delete_account,
|
delete::delete_account,
|
||||||
|
@ -381,6 +388,14 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
|
||||||
.route("/community", web::post().to(purge_community))
|
.route("/community", web::post().to(purge_community))
|
||||||
.route("/post", web::post().to(purge_post))
|
.route("/post", web::post().to(purge_post))
|
||||||
.route("/comment", web::post().to(purge_comment)),
|
.route("/comment", web::post().to(purge_comment)),
|
||||||
|
)
|
||||||
|
.service(
|
||||||
|
web::scope("/tagline")
|
||||||
|
.wrap(rate_limit.message())
|
||||||
|
.route("", web::post().to(create_tagline))
|
||||||
|
.route("", web::put().to(update_tagline))
|
||||||
|
.route("/delete", web::post().to(delete_tagline))
|
||||||
|
.route("/list", web::get().to(list_taglines)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.service(
|
.service(
|
||||||
|
@ -388,7 +403,8 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
|
||||||
.wrap(rate_limit.message())
|
.wrap(rate_limit.message())
|
||||||
.route("", web::post().to(create_custom_emoji))
|
.route("", web::post().to(create_custom_emoji))
|
||||||
.route("", web::put().to(update_custom_emoji))
|
.route("", web::put().to(update_custom_emoji))
|
||||||
.route("/delete", web::post().to(delete_custom_emoji)),
|
.route("/delete", web::post().to(delete_custom_emoji))
|
||||||
|
.route("/list", web::get().to(list_custom_emojis)),
|
||||||
)
|
)
|
||||||
.service(
|
.service(
|
||||||
web::scope("/oauth_provider")
|
web::scope("/oauth_provider")
|
||||||
|
|
Loading…
Reference in a new issue