mirror of https://github.com/LemmyNet/lemmy
Merge 920adccdb4
into b459949f57
commit
ff21690fd8
@ -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>,
|
||||
}
|
@ -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 delete;
|
||||
pub mod list;
|
||||
pub mod update;
|
||||
|
@ -0,0 +1,41 @@
|
||||
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, utils::validation::is_valid_tagline_content};
|
||||
|
||||
#[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?;
|
||||
is_valid_tagline_content(&content)?;
|
||||
|
||||
let tagline_form = TaglineInsertForm {
|
||||
content: Some(content),
|
||||
};
|
||||
|
||||
let tagline = Tagline::create(&mut context.pool(), &tagline_form).await?;
|
||||
|
||||
Ok(Json(TaglineResponse { tagline }))
|
||||
}
|
@ -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()))
|
||||
}
|
@ -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 }))
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
pub mod create;
|
||||
pub mod delete;
|
||||
pub mod list;
|
||||
pub mod update;
|
@ -0,0 +1,43 @@
|
||||
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, utils::validation::is_valid_tagline_content};
|
||||
|
||||
#[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?;
|
||||
is_valid_tagline_content(&content)?;
|
||||
|
||||
let tagline_form = TaglineUpdateForm {
|
||||
content: Some(content),
|
||||
updated: Some(Some(naive_now())),
|
||||
};
|
||||
|
||||
let tagline = Tagline::update(&mut context.pool(), data.id, &tagline_form).await?;
|
||||
|
||||
Ok(Json(TaglineResponse { tagline }))
|
||||
}
|
@ -1,58 +1,64 @@
|
||||
use crate::{
|
||||
newtypes::LocalSiteId,
|
||||
schema::tagline::dsl::{local_site_id, tagline},
|
||||
source::tagline::{Tagline, TaglineForm},
|
||||
utils::{get_conn, DbPool},
|
||||
newtypes::TaglineId,
|
||||
schema::tagline::dsl::{published, tagline},
|
||||
source::tagline::{Tagline, TaglineInsertForm, TaglineUpdateForm},
|
||||
traits::Crud,
|
||||
utils::{get_conn, limit_and_offset, DbPool},
|
||||
};
|
||||
use diesel::{insert_into, result::Error, ExpressionMethods, QueryDsl};
|
||||
use diesel_async::{AsyncPgConnection, RunQueryDsl};
|
||||
use diesel::{insert_into, result::Error, ExpressionMethods, OptionalExtension, QueryDsl};
|
||||
use diesel_async::RunQueryDsl;
|
||||
|
||||
impl Tagline {
|
||||
pub async fn replace(
|
||||
pool: &mut DbPool<'_>,
|
||||
for_local_site_id: LocalSiteId,
|
||||
list_content: Option<Vec<String>>,
|
||||
) -> Result<Vec<Self>, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
if let Some(list) = list_content {
|
||||
conn
|
||||
.build_transaction()
|
||||
.run(|conn| {
|
||||
Box::pin(async move {
|
||||
Self::clear(conn).await?;
|
||||
#[async_trait]
|
||||
impl Crud for Tagline {
|
||||
type InsertForm = TaglineInsertForm;
|
||||
type UpdateForm = TaglineUpdateForm;
|
||||
type IdType = TaglineId;
|
||||
|
||||
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 create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(tagline)
|
||||
.values(form)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn clear(conn: &mut AsyncPgConnection) -> Result<usize, Error> {
|
||||
diesel::delete(tagline).execute(conn).await
|
||||
async fn update(
|
||||
pool: &mut DbPool<'_>,
|
||||
tagline_id: TaglineId,
|
||||
new_tagline: &Self::UpdateForm,
|
||||
) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
diesel::update(tagline.find(tagline_id))
|
||||
.set(new_tagline)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_all(
|
||||
impl Tagline {
|
||||
pub async fn list(
|
||||
pool: &mut DbPool<'_>,
|
||||
for_local_site_id: LocalSiteId,
|
||||
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
|
||||
.filter(local_site_id.eq(for_local_site_id))
|
||||
.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()
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue