Get rid of remaining Perform/SendActivity traits (fixes #3670) (#3926)

* Get rid of remaining Perform/SendActivity traits (fixes #3670)

* fix api tests

* ci
use_person_id_for_add_admin
Nutomic 2023-09-05 11:33:46 +02:00 committed by GitHub
parent a1a9c3e4c0
commit 366d9d1e2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 1373 additions and 1981 deletions

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use anyhow::Context; use anyhow::Context;
use lemmy_api_common::{ use lemmy_api_common::{
community::{GetCommunityResponse, TransferCommunity}, community::{GetCommunityResponse, TransferCommunity},
@ -21,17 +20,12 @@ use lemmy_utils::{
// TODO: we dont do anything for federation here, it should be updated the next time the community // TODO: we dont do anything for federation here, it should be updated the next time the community
// gets fetched. i hope we can get rid of the community creator role soon. // gets fetched. i hope we can get rid of the community creator role soon.
#[async_trait::async_trait(?Send)]
impl Perform for TransferCommunity {
type Response = GetCommunityResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform( pub async fn transfer_community(
&self, data: Json<TransferCommunity>,
context: &Data<LemmyContext>, context: Data<LemmyContext>,
) -> Result<GetCommunityResponse, LemmyError> { ) -> Result<Json<GetCommunityResponse>, LemmyError> {
let data: &TransferCommunity = self; let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
// Fetch the community mods // Fetch the community mods
let community_id = data.community_id; let community_id = data.community_id;
@ -39,8 +33,7 @@ impl Perform for TransferCommunity {
CommunityModeratorView::for_community(&mut context.pool(), community_id).await?; CommunityModeratorView::for_community(&mut context.pool(), community_id).await?;
// Make sure transferrer is either the top community mod, or an admin // Make sure transferrer is either the top community mod, or an admin
if !(is_top_mod(&local_user_view, &community_mods).is_ok() if !(is_top_mod(&local_user_view, &community_mods).is_ok() || is_admin(&local_user_view).is_ok())
|| is_admin(&local_user_view).is_ok())
{ {
Err(LemmyErrorType::NotAnAdmin)? Err(LemmyErrorType::NotAnAdmin)?
} }
@ -94,11 +87,10 @@ impl Perform for TransferCommunity {
.with_lemmy_type(LemmyErrorType::CouldntFindCommunity)?; .with_lemmy_type(LemmyErrorType::CouldntFindCommunity)?;
// Return the jwt // Return the jwt
Ok(GetCommunityResponse { Ok(Json(GetCommunityResponse {
community_view, community_view,
site: None, site: None,
moderators, moderators,
discussion_languages: vec![], discussion_languages: vec![],
}) }))
}
} }

View File

@ -1,7 +1,6 @@
use actix_web::web::Data;
use base64::{engine::general_purpose::STANDARD_NO_PAD as base64, Engine}; use base64::{engine::general_purpose::STANDARD_NO_PAD as base64, Engine};
use captcha::Captcha; use captcha::Captcha;
use lemmy_api_common::{context::LemmyContext, utils::local_site_to_slur_regex}; use lemmy_api_common::utils::local_site_to_slur_regex;
use lemmy_db_schema::source::local_site::LocalSite; use lemmy_db_schema::source::local_site::LocalSite;
use lemmy_utils::{ use lemmy_utils::{
error::{LemmyError, LemmyErrorExt, LemmyErrorType}, error::{LemmyError, LemmyErrorExt, LemmyErrorType},
@ -20,13 +19,6 @@ pub mod private_message_report;
pub mod site; pub mod site;
pub mod sitemap; pub mod sitemap;
#[async_trait::async_trait(?Send)]
pub trait Perform {
type Response: serde::ser::Serialize + Send + Clone + Sync;
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError>;
}
/// Converts the captcha to a base64 encoded wav audio file /// Converts the captcha to a base64 encoded wav audio file
pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> Result<String, LemmyError> { pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> Result<String, LemmyError> {
let letters = captcha.as_wav(); let letters = captcha.as_wav();

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{AddAdmin, AddAdminResponse}, person::{AddAdmin, AddAdminResponse},
@ -15,14 +14,12 @@ use lemmy_db_schema::{
use lemmy_db_views_actor::structs::PersonView; use lemmy_db_views_actor::structs::PersonView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
#[async_trait::async_trait(?Send)]
impl Perform for AddAdmin {
type Response = AddAdminResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<AddAdminResponse, LemmyError> { pub async fn add_admin(
let data: &AddAdmin = self; data: Json<AddAdmin>,
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; context: Data<LemmyContext>,
) -> Result<Json<AddAdminResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
// Make sure user is an admin // Make sure user is an admin
is_admin(&local_user_view)?; is_admin(&local_user_view)?;
@ -49,6 +46,5 @@ impl Perform for AddAdmin {
let admins = PersonView::admins(&mut context.pool()).await?; let admins = PersonView::admins(&mut context.pool()).await?;
Ok(AddAdminResponse { admins }) Ok(Json(AddAdminResponse { admins }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{BlockPerson, BlockPersonResponse}, person::{BlockPerson, BlockPersonResponse},
@ -13,14 +12,12 @@ use lemmy_db_views::structs::LocalUserView;
use lemmy_db_views_actor::structs::PersonView; use lemmy_db_views_actor::structs::PersonView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
#[async_trait::async_trait(?Send)]
impl Perform for BlockPerson {
type Response = BlockPersonResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<BlockPersonResponse, LemmyError> { pub async fn block_person(
let data: &BlockPerson = self; data: Json<BlockPerson>,
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; context: Data<LemmyContext>,
) -> Result<Json<BlockPersonResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let target_id = data.person_id; let target_id = data.person_id;
let person_id = local_user_view.person.id; let person_id = local_user_view.person.id;
@ -51,9 +48,8 @@ impl Perform for BlockPerson {
} }
let person_view = PersonView::read(&mut context.pool(), target_id).await?; let person_view = PersonView::read(&mut context.pool(), target_id).await?;
Ok(BlockPersonResponse { Ok(Json(BlockPersonResponse {
person_view, person_view,
blocked: data.block, blocked: data.block,
}) }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use bcrypt::verify; use bcrypt::verify;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
@ -12,14 +11,12 @@ use lemmy_utils::{
error::{LemmyError, LemmyErrorType}, error::{LemmyError, LemmyErrorType},
}; };
#[async_trait::async_trait(?Send)] #[tracing::instrument(skip(context))]
impl Perform for ChangePassword { pub async fn change_password(
type Response = LoginResponse; data: Json<ChangePassword>,
context: Data<LemmyContext>,
#[tracing::instrument(skip(self, context))] ) -> Result<Json<LoginResponse>, LemmyError> {
async fn perform(&self, context: &Data<LemmyContext>) -> Result<LoginResponse, LemmyError> { let local_user_view = local_user_view_from_jwt(data.auth.as_ref(), &context).await?;
let data: &ChangePassword = self;
let local_user_view = local_user_view_from_jwt(data.auth.as_ref(), context).await?;
password_length_check(&data.new_password)?; password_length_check(&data.new_password)?;
@ -44,7 +41,7 @@ impl Perform for ChangePassword {
LocalUser::update_password(&mut context.pool(), local_user_id, &new_password).await?; LocalUser::update_password(&mut context.pool(), local_user_id, &new_password).await?;
// Return the jwt // Return the jwt
Ok(LoginResponse { Ok(Json(LoginResponse {
jwt: Some( jwt: Some(
Claims::jwt( Claims::jwt(
updated_local_user.id.0, updated_local_user.id.0,
@ -55,6 +52,5 @@ impl Perform for ChangePassword {
), ),
verify_email_sent: false, verify_email_sent: false,
registration_created: false, registration_created: false,
}) }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{LoginResponse, PasswordChangeAfterReset}, person::{LoginResponse, PasswordChangeAfterReset},
@ -11,14 +10,11 @@ use lemmy_db_schema::source::{
}; };
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
#[async_trait::async_trait(?Send)] #[tracing::instrument(skip(context))]
impl Perform for PasswordChangeAfterReset { pub async fn change_password_after_reset(
type Response = LoginResponse; data: Json<PasswordChangeAfterReset>,
context: Data<LemmyContext>,
#[tracing::instrument(skip(self, context))] ) -> Result<Json<LoginResponse>, LemmyError> {
async fn perform(&self, context: &Data<LemmyContext>) -> Result<LoginResponse, LemmyError> {
let data: &PasswordChangeAfterReset = self;
// Fetch the user_id from the token // Fetch the user_id from the token
let token = data.token.clone(); let token = data.token.clone();
let local_user_id = PasswordResetRequest::read_from_token(&mut context.pool(), &token) let local_user_id = PasswordResetRequest::read_from_token(&mut context.pool(), &token)
@ -38,10 +34,9 @@ impl Perform for PasswordChangeAfterReset {
.await .await
.with_lemmy_type(LemmyErrorType::CouldntUpdateUser)?; .with_lemmy_type(LemmyErrorType::CouldntUpdateUser)?;
Ok(LoginResponse { Ok(Json(LoginResponse {
jwt: None, jwt: None,
verify_email_sent: false, verify_email_sent: false,
registration_created: false, registration_created: false,
}) }))
}
} }

View File

@ -1,9 +1,9 @@
use crate::{captcha_as_wav_base64, Perform}; use crate::captcha_as_wav_base64;
use actix_web::web::Data; use actix_web::web::{Data, Json};
use captcha::{gen, Difficulty}; use captcha::{gen, Difficulty};
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{CaptchaResponse, GetCaptcha, GetCaptchaResponse}, person::{CaptchaResponse, GetCaptchaResponse},
}; };
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
captcha_answer::{CaptchaAnswer, CaptchaAnswerForm}, captcha_answer::{CaptchaAnswer, CaptchaAnswerForm},
@ -11,16 +11,14 @@ use lemmy_db_schema::source::{
}; };
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetCaptcha {
type Response = GetCaptchaResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { pub async fn get_captcha(
context: Data<LemmyContext>,
) -> Result<Json<GetCaptchaResponse>, LemmyError> {
let local_site = LocalSite::read(&mut context.pool()).await?; let local_site = LocalSite::read(&mut context.pool()).await?;
if !local_site.captcha_enabled { if !local_site.captcha_enabled {
return Ok(GetCaptchaResponse { ok: None }); return Ok(Json(GetCaptchaResponse { ok: None }));
} }
let captcha = gen(match local_site.captcha_difficulty.as_str() { let captcha = gen(match local_site.captcha_difficulty.as_str() {
@ -39,12 +37,11 @@ impl Perform for GetCaptcha {
// Stores the captcha item in the db // Stores the captcha item in the db
let captcha = CaptchaAnswer::insert(&mut context.pool(), &captcha_form).await?; let captcha = CaptchaAnswer::insert(&mut context.pool(), &captcha_form).await?;
Ok(GetCaptchaResponse { Ok(Json(GetCaptchaResponse {
ok: Some(CaptchaResponse { ok: Some(CaptchaResponse {
png, png,
wav, wav,
uuid: captcha.uuid.to_string(), uuid: captcha.uuid.to_string(),
}), }),
}) }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json, Query};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{BannedPersonsResponse, GetBannedPersons}, person::{BannedPersonsResponse, GetBannedPersons},
@ -8,19 +7,16 @@ use lemmy_api_common::{
use lemmy_db_views_actor::structs::PersonView; use lemmy_db_views_actor::structs::PersonView;
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)] pub async fn list_banned_users(
impl Perform for GetBannedPersons { data: Query<GetBannedPersons>,
type Response = BannedPersonsResponse; context: Data<LemmyContext>,
) -> Result<Json<BannedPersonsResponse>, LemmyError> {
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let data: &GetBannedPersons = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
// Make sure user is an admin // Make sure user is an admin
is_admin(&local_user_view)?; is_admin(&local_user_view)?;
let banned = PersonView::banned(&mut context.pool()).await?; let banned = PersonView::banned(&mut context.pool()).await?;
Ok(Self::Response { banned }) Ok(Json(BannedPersonsResponse { banned }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use bcrypt::verify; use bcrypt::verify;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
@ -13,14 +12,11 @@ use lemmy_utils::{
utils::validation::check_totp_2fa_valid, utils::validation::check_totp_2fa_valid,
}; };
#[async_trait::async_trait(?Send)]
impl Perform for Login {
type Response = LoginResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<LoginResponse, LemmyError> { pub async fn login(
let data: &Login = self; data: Json<Login>,
context: Data<LemmyContext>,
) -> Result<Json<LoginResponse>, LemmyError> {
let site_view = SiteView::read_local(&mut context.pool()).await?; let site_view = SiteView::read_local(&mut context.pool()).await?;
// Fetch that username / email // Fetch that username / email
@ -66,7 +62,7 @@ impl Perform for Login {
)?; )?;
// Return the jwt // Return the jwt
Ok(LoginResponse { Ok(Json(LoginResponse {
jwt: Some( jwt: Some(
Claims::jwt( Claims::jwt(
local_user_view.local_user.id.0, local_user_view.local_user.id.0,
@ -77,6 +73,5 @@ impl Perform for Login {
), ),
verify_email_sent: false, verify_email_sent: false,
registration_created: false, registration_created: false,
}) }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json, Query};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{GetPersonMentions, GetPersonMentionsResponse}, person::{GetPersonMentions, GetPersonMentionsResponse},
@ -8,17 +7,12 @@ use lemmy_api_common::{
use lemmy_db_views_actor::person_mention_view::PersonMentionQuery; use lemmy_db_views_actor::person_mention_view::PersonMentionQuery;
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetPersonMentions {
type Response = GetPersonMentionsResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform( pub async fn list_mentions(
&self, data: Query<GetPersonMentions>,
context: &Data<LemmyContext>, context: Data<LemmyContext>,
) -> Result<GetPersonMentionsResponse, LemmyError> { ) -> Result<Json<GetPersonMentionsResponse>, LemmyError> {
let data: &GetPersonMentions = self; let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let sort = data.sort; let sort = data.sort;
let page = data.page; let page = data.page;
@ -39,6 +33,5 @@ impl Perform for GetPersonMentions {
.list(&mut context.pool()) .list(&mut context.pool())
.await?; .await?;
Ok(GetPersonMentionsResponse { mentions }) Ok(Json(GetPersonMentionsResponse { mentions }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json, Query};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{GetReplies, GetRepliesResponse}, person::{GetReplies, GetRepliesResponse},
@ -8,14 +7,12 @@ use lemmy_api_common::{
use lemmy_db_views_actor::comment_reply_view::CommentReplyQuery; use lemmy_db_views_actor::comment_reply_view::CommentReplyQuery;
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetReplies {
type Response = GetRepliesResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<GetRepliesResponse, LemmyError> { pub async fn list_replies(
let data: &GetReplies = self; data: Query<GetReplies>,
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; context: Data<LemmyContext>,
) -> Result<Json<GetRepliesResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let sort = data.sort; let sort = data.sort;
let page = data.page; let page = data.page;
@ -36,6 +33,5 @@ impl Perform for GetReplies {
.list(&mut context.pool()) .list(&mut context.pool())
.await?; .await?;
Ok(GetRepliesResponse { replies }) Ok(Json(GetRepliesResponse { replies }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{GetRepliesResponse, MarkAllAsRead}, person::{GetRepliesResponse, MarkAllAsRead},
@ -12,14 +11,12 @@ use lemmy_db_schema::source::{
}; };
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
#[async_trait::async_trait(?Send)]
impl Perform for MarkAllAsRead {
type Response = GetRepliesResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<GetRepliesResponse, LemmyError> { pub async fn mark_all_notifications_read(
let data: &MarkAllAsRead = self; data: Json<MarkAllAsRead>,
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; context: Data<LemmyContext>,
) -> Result<Json<GetRepliesResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let person_id = local_user_view.person.id; let person_id = local_user_view.person.id;
// Mark all comment_replies as read // Mark all comment_replies as read
@ -37,6 +34,5 @@ impl Perform for MarkAllAsRead {
.await .await
.with_lemmy_type(LemmyErrorType::CouldntUpdatePrivateMessage)?; .with_lemmy_type(LemmyErrorType::CouldntUpdatePrivateMessage)?;
Ok(GetRepliesResponse { replies: vec![] }) Ok(Json(GetRepliesResponse { replies: vec![] }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{MarkPersonMentionAsRead, PersonMentionResponse}, person::{MarkPersonMentionAsRead, PersonMentionResponse},
@ -12,17 +11,12 @@ use lemmy_db_schema::{
use lemmy_db_views_actor::structs::PersonMentionView; use lemmy_db_views_actor::structs::PersonMentionView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
#[async_trait::async_trait(?Send)]
impl Perform for MarkPersonMentionAsRead {
type Response = PersonMentionResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform( pub async fn mark_person_mention_as_read(
&self, data: Json<MarkPersonMentionAsRead>,
context: &Data<LemmyContext>, context: Data<LemmyContext>,
) -> Result<PersonMentionResponse, LemmyError> { ) -> Result<Json<PersonMentionResponse>, LemmyError> {
let data: &MarkPersonMentionAsRead = self; let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let person_mention_id = data.person_mention_id; let person_mention_id = data.person_mention_id;
let read_person_mention = PersonMention::read(&mut context.pool(), person_mention_id).await?; let read_person_mention = PersonMention::read(&mut context.pool(), person_mention_id).await?;
@ -46,8 +40,7 @@ impl Perform for MarkPersonMentionAsRead {
let person_mention_view = let person_mention_view =
PersonMentionView::read(&mut context.pool(), person_mention_id, Some(person_id)).await?; PersonMentionView::read(&mut context.pool(), person_mention_id, Some(person_id)).await?;
Ok(PersonMentionResponse { Ok(Json(PersonMentionResponse {
person_mention_view, person_mention_view,
}) }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json, Query};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{GetUnreadCount, GetUnreadCountResponse}, person::{GetUnreadCount, GetUnreadCountResponse},
@ -9,14 +8,12 @@ use lemmy_db_views::structs::PrivateMessageView;
use lemmy_db_views_actor::structs::{CommentReplyView, PersonMentionView}; use lemmy_db_views_actor::structs::{CommentReplyView, PersonMentionView};
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetUnreadCount {
type Response = GetUnreadCountResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { pub async fn unread_count(
let data = self; data: Query<GetUnreadCount>,
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; context: Data<LemmyContext>,
) -> Result<Json<GetUnreadCountResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let person_id = local_user_view.person.id; let person_id = local_user_view.person.id;
@ -27,10 +24,9 @@ impl Perform for GetUnreadCount {
let private_messages = let private_messages =
PrivateMessageView::get_unread_messages(&mut context.pool(), person_id).await?; PrivateMessageView::get_unread_messages(&mut context.pool(), person_id).await?;
Ok(Self::Response { Ok(Json(GetUnreadCountResponse {
replies, replies,
mentions, mentions,
private_messages, private_messages,
}) }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{GetReportCount, GetReportCountResponse}, person::{GetReportCount, GetReportCountResponse},
@ -8,17 +7,12 @@ use lemmy_api_common::{
use lemmy_db_views::structs::{CommentReportView, PostReportView, PrivateMessageReportView}; use lemmy_db_views::structs::{CommentReportView, PostReportView, PrivateMessageReportView};
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetReportCount {
type Response = GetReportCountResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform( pub async fn report_count(
&self, data: Json<GetReportCount>,
context: &Data<LemmyContext>, context: Data<LemmyContext>,
) -> Result<GetReportCountResponse, LemmyError> { ) -> Result<Json<GetReportCountResponse>, LemmyError> {
let data: &GetReportCount = self; let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let person_id = local_user_view.person.id; let person_id = local_user_view.person.id;
let admin = local_user_view.local_user.admin; let admin = local_user_view.local_user.admin;
@ -37,11 +31,10 @@ impl Perform for GetReportCount {
None None
}; };
Ok(GetReportCountResponse { Ok(Json(GetReportCountResponse {
community_id, community_id,
comment_reports, comment_reports,
post_reports, post_reports,
private_message_reports, private_message_reports,
}) }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{PasswordReset, PasswordResetResponse}, person::{PasswordReset, PasswordResetResponse},
@ -9,17 +8,11 @@ use lemmy_db_schema::source::password_reset_request::PasswordResetRequest;
use lemmy_db_views::structs::LocalUserView; use lemmy_db_views::structs::LocalUserView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
#[async_trait::async_trait(?Send)] #[tracing::instrument(skip(context))]
impl Perform for PasswordReset { pub async fn reset_password(
type Response = PasswordResetResponse; data: Json<PasswordReset>,
context: Data<LemmyContext>,
#[tracing::instrument(skip(self, context))] ) -> Result<Json<PasswordResetResponse>, LemmyError> {
async fn perform(
&self,
context: &Data<LemmyContext>,
) -> Result<PasswordResetResponse, LemmyError> {
let data: &PasswordReset = self;
// Fetch that email // Fetch that email
let email = data.email.to_lowercase(); let email = data.email.to_lowercase();
let local_user_view = LocalUserView::find_by_email(&mut context.pool(), &email) let local_user_view = LocalUserView::find_by_email(&mut context.pool(), &email)
@ -38,6 +31,5 @@ impl Perform for PasswordReset {
// Email the pure token to the user. // Email the pure token to the user.
send_password_reset_email(&local_user_view, &mut context.pool(), context.settings()).await?; send_password_reset_email(&local_user_view, &mut context.pool(), context.settings()).await?;
Ok(PasswordResetResponse {}) Ok(Json(PasswordResetResponse {}))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{LoginResponse, SaveUserSettings}, person::{LoginResponse, SaveUserSettings},
@ -27,14 +26,12 @@ use lemmy_utils::{
}, },
}; };
#[async_trait::async_trait(?Send)]
impl Perform for SaveUserSettings {
type Response = LoginResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<LoginResponse, LemmyError> { pub async fn save_user_settings(
let data: &SaveUserSettings = self; data: Json<SaveUserSettings>,
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; context: Data<LemmyContext>,
) -> Result<Json<LoginResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let site_view = SiteView::read_local(&mut context.pool()).await?; let site_view = SiteView::read_local(&mut context.pool()).await?;
let bio = sanitize_html_opt(&data.bio); let bio = sanitize_html_opt(&data.bio);
@ -162,7 +159,7 @@ impl Perform for SaveUserSettings {
}; };
// Return the jwt // Return the jwt
Ok(LoginResponse { Ok(Json(LoginResponse {
jwt: Some( jwt: Some(
Claims::jwt( Claims::jwt(
updated_local_user.id.0, updated_local_user.id.0,
@ -173,6 +170,5 @@ impl Perform for SaveUserSettings {
), ),
verify_email_sent: false, verify_email_sent: false,
registration_created: false, registration_created: false,
}) }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{VerifyEmail, VerifyEmailResponse}, person::{VerifyEmail, VerifyEmailResponse},
@ -13,12 +12,11 @@ use lemmy_db_schema::{
}; };
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
#[async_trait::async_trait(?Send)] pub async fn verify_email(
impl Perform for VerifyEmail { data: Json<VerifyEmail>,
type Response = VerifyEmailResponse; context: Data<LemmyContext>,
) -> Result<Json<VerifyEmailResponse>, LemmyError> {
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { let token = data.token.clone();
let token = self.token.clone();
let verification = EmailVerification::read_for_token(&mut context.pool(), &token) let verification = EmailVerification::read_for_token(&mut context.pool(), &token)
.await .await
.with_lemmy_type(LemmyErrorType::TokenNotFound)?; .with_lemmy_type(LemmyErrorType::TokenNotFound)?;
@ -36,6 +34,5 @@ impl Perform for VerifyEmail {
EmailVerification::delete_old_tokens_for_local_user(&mut context.pool(), local_user_id).await?; EmailVerification::delete_old_tokens_for_local_user(&mut context.pool(), local_user_id).await?;
Ok(VerifyEmailResponse {}) Ok(Json(VerifyEmailResponse {}))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
post::{GetSiteMetadata, GetSiteMetadataResponse}, post::{GetSiteMetadata, GetSiteMetadataResponse},
@ -7,19 +6,12 @@ use lemmy_api_common::{
}; };
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetSiteMetadata {
type Response = GetSiteMetadataResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform( pub async fn get_link_metadata(
&self, data: Json<GetSiteMetadata>,
context: &Data<LemmyContext>, context: Data<LemmyContext>,
) -> Result<GetSiteMetadataResponse, LemmyError> { ) -> Result<Json<GetSiteMetadataResponse>, LemmyError> {
let data: &Self = self;
let metadata = fetch_site_metadata(context.client(), &data.url).await?; let metadata = fetch_site_metadata(context.client(), &data.url).await?;
Ok(GetSiteMetadataResponse { metadata }) Ok(Json(GetSiteMetadataResponse { metadata }))
}
} }

View File

@ -1,35 +1,32 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
post::{MarkPostAsRead, PostResponse}, post::{MarkPostAsRead, PostResponse},
utils::{local_user_view_from_jwt, mark_post_as_read, mark_post_as_unread}, utils,
utils::local_user_view_from_jwt,
}; };
use lemmy_db_views::structs::PostView; use lemmy_db_views::structs::PostView;
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for MarkPostAsRead {
type Response = PostResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { pub async fn mark_post_as_read(
let data = self; data: Json<MarkPostAsRead>,
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; context: Data<LemmyContext>,
) -> Result<Json<PostResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let post_id = data.post_id; let post_id = data.post_id;
let person_id = local_user_view.person.id; let person_id = local_user_view.person.id;
// Mark the post as read / unread // Mark the post as read / unread
if data.read { if data.read {
mark_post_as_read(person_id, post_id, &mut context.pool()).await?; utils::mark_post_as_read(person_id, post_id, &mut context.pool()).await?;
} else { } else {
mark_post_as_unread(person_id, post_id, &mut context.pool()).await?; utils::mark_post_as_unread(person_id, post_id, &mut context.pool()).await?;
} }
// Fetch it // Fetch it
let post_view = PostView::read(&mut context.pool(), post_id, Some(person_id), false).await?; let post_view = PostView::read(&mut context.pool(), post_id, Some(person_id), false).await?;
Ok(Self::Response { post_view }) Ok(Json(PostResponse { post_view }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
post::{PostResponse, SavePost}, post::{PostResponse, SavePost},
@ -12,14 +11,12 @@ use lemmy_db_schema::{
use lemmy_db_views::structs::PostView; use lemmy_db_views::structs::PostView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
#[async_trait::async_trait(?Send)]
impl Perform for SavePost {
type Response = PostResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostResponse, LemmyError> { pub async fn save_post(
let data: &SavePost = self; data: Json<SavePost>,
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; context: Data<LemmyContext>,
) -> Result<Json<PostResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let post_saved_form = PostSavedForm { let post_saved_form = PostSavedForm {
post_id: data.post_id, post_id: data.post_id,
@ -43,6 +40,5 @@ impl Perform for SavePost {
// Mark the post as read // Mark the post as read
mark_post_as_read(person_id, post_id, &mut context.pool()).await?; mark_post_as_read(person_id, post_id, &mut context.pool()).await?;
Ok(PostResponse { post_view }) Ok(Json(PostResponse { post_view }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json, Query};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
post::{ListPostReports, ListPostReportsResponse}, post::{ListPostReports, ListPostReportsResponse},
@ -10,17 +9,12 @@ use lemmy_utils::error::LemmyError;
/// Lists post reports for a community if an id is supplied /// Lists post reports for a community if an id is supplied
/// or returns all post reports for communities a user moderates /// or returns all post reports for communities a user moderates
#[async_trait::async_trait(?Send)]
impl Perform for ListPostReports {
type Response = ListPostReportsResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform( pub async fn list_post_reports(
&self, data: Query<ListPostReports>,
context: &Data<LemmyContext>, context: Data<LemmyContext>,
) -> Result<ListPostReportsResponse, LemmyError> { ) -> Result<Json<ListPostReportsResponse>, LemmyError> {
let data: &ListPostReports = self; let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let community_id = data.community_id; let community_id = data.community_id;
let unresolved_only = data.unresolved_only.unwrap_or_default(); let unresolved_only = data.unresolved_only.unwrap_or_default();
@ -36,6 +30,5 @@ impl Perform for ListPostReports {
.list(&mut context.pool(), &local_user_view) .list(&mut context.pool(), &local_user_view)
.await?; .await?;
Ok(ListPostReportsResponse { post_reports }) Ok(Json(ListPostReportsResponse { post_reports }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
post::{PostReportResponse, ResolvePostReport}, post::{PostReportResponse, ResolvePostReport},
@ -10,14 +9,12 @@ use lemmy_db_views::structs::PostReportView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
/// Resolves or unresolves a post report and notifies the moderators of the community /// Resolves or unresolves a post report and notifies the moderators of the community
#[async_trait::async_trait(?Send)]
impl Perform for ResolvePostReport {
type Response = PostReportResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostReportResponse, LemmyError> { pub async fn resolve_post_report(
let data: &ResolvePostReport = self; data: Json<ResolvePostReport>,
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; context: Data<LemmyContext>,
) -> Result<Json<PostReportResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let report_id = data.report_id; let report_id = data.report_id;
let person_id = local_user_view.person.id; let person_id = local_user_view.person.id;
@ -38,6 +35,5 @@ impl Perform for ResolvePostReport {
let post_report_view = PostReportView::read(&mut context.pool(), report_id, person_id).await?; let post_report_view = PostReportView::read(&mut context.pool(), report_id, person_id).await?;
Ok(PostReportResponse { post_report_view }) Ok(Json(PostReportResponse { post_report_view }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
private_message::{MarkPrivateMessageAsRead, PrivateMessageResponse}, private_message::{MarkPrivateMessageAsRead, PrivateMessageResponse},
@ -12,22 +11,16 @@ use lemmy_db_schema::{
use lemmy_db_views::structs::PrivateMessageView; use lemmy_db_views::structs::PrivateMessageView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
#[async_trait::async_trait(?Send)]
impl Perform for MarkPrivateMessageAsRead {
type Response = PrivateMessageResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform( pub async fn mark_pm_as_read(
&self, data: Json<MarkPrivateMessageAsRead>,
context: &Data<LemmyContext>, context: Data<LemmyContext>,
) -> Result<PrivateMessageResponse, LemmyError> { ) -> Result<Json<PrivateMessageResponse>, LemmyError> {
let data: &MarkPrivateMessageAsRead = self; let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
// Checking permissions // Checking permissions
let private_message_id = data.private_message_id; let private_message_id = data.private_message_id;
let orig_private_message = let orig_private_message = PrivateMessage::read(&mut context.pool(), private_message_id).await?;
PrivateMessage::read(&mut context.pool(), private_message_id).await?;
if local_user_view.person.id != orig_private_message.recipient_id { if local_user_view.person.id != orig_private_message.recipient_id {
Err(LemmyErrorType::CouldntUpdatePrivateMessage)? Err(LemmyErrorType::CouldntUpdatePrivateMessage)?
} }
@ -47,8 +40,7 @@ impl Perform for MarkPrivateMessageAsRead {
.with_lemmy_type(LemmyErrorType::CouldntUpdatePrivateMessage)?; .with_lemmy_type(LemmyErrorType::CouldntUpdatePrivateMessage)?;
let view = PrivateMessageView::read(&mut context.pool(), private_message_id).await?; let view = PrivateMessageView::read(&mut context.pool(), private_message_id).await?;
Ok(PrivateMessageResponse { Ok(Json(PrivateMessageResponse {
private_message_view: view, private_message_view: view,
}) }))
}
} }

View File

@ -1 +1 @@
mod mark_read; pub mod mark_read;

View File

@ -1,5 +1,5 @@
use crate::{check_report_reason, Perform}; use crate::check_report_reason;
use actix_web::web::Data; use actix_web::web::{Data, Json};
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
private_message::{CreatePrivateMessageReport, PrivateMessageReportResponse}, private_message::{CreatePrivateMessageReport, PrivateMessageReportResponse},
@ -16,20 +16,19 @@ use lemmy_db_schema::{
use lemmy_db_views::structs::PrivateMessageReportView; use lemmy_db_views::structs::PrivateMessageReportView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
#[async_trait::async_trait(?Send)]
impl Perform for CreatePrivateMessageReport {
type Response = PrivateMessageReportResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { pub async fn create_pm_report(
let local_user_view = local_user_view_from_jwt(&self.auth, context).await?; data: Json<CreatePrivateMessageReport>,
context: Data<LemmyContext>,
) -> Result<Json<PrivateMessageReportResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let local_site = LocalSite::read(&mut context.pool()).await?; let local_site = LocalSite::read(&mut context.pool()).await?;
let reason = sanitize_html(self.reason.trim()); let reason = sanitize_html(data.reason.trim());
check_report_reason(&reason, &local_site)?; check_report_reason(&reason, &local_site)?;
let person_id = local_user_view.person.id; let person_id = local_user_view.person.id;
let private_message_id = self.private_message_id; let private_message_id = data.private_message_id;
let private_message = PrivateMessage::read(&mut context.pool(), private_message_id).await?; let private_message = PrivateMessage::read(&mut context.pool(), private_message_id).await?;
let report_form = PrivateMessageReportForm { let report_form = PrivateMessageReportForm {
@ -59,8 +58,7 @@ impl Perform for CreatePrivateMessageReport {
// TODO: consider federating this // TODO: consider federating this
Ok(PrivateMessageReportResponse { Ok(Json(PrivateMessageReportResponse {
private_message_report_view, private_message_report_view,
}) }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json, Query};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
private_message::{ListPrivateMessageReports, ListPrivateMessageReportsResponse}, private_message::{ListPrivateMessageReports, ListPrivateMessageReportsResponse},
@ -8,19 +7,18 @@ use lemmy_api_common::{
use lemmy_db_views::private_message_report_view::PrivateMessageReportQuery; use lemmy_db_views::private_message_report_view::PrivateMessageReportQuery;
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for ListPrivateMessageReports {
type Response = ListPrivateMessageReportsResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { pub async fn list_pm_reports(
let local_user_view = local_user_view_from_jwt(&self.auth, context).await?; data: Query<ListPrivateMessageReports>,
context: Data<LemmyContext>,
) -> Result<Json<ListPrivateMessageReportsResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
is_admin(&local_user_view)?; is_admin(&local_user_view)?;
let unresolved_only = self.unresolved_only.unwrap_or_default(); let unresolved_only = data.unresolved_only.unwrap_or_default();
let page = self.page; let page = data.page;
let limit = self.limit; let limit = data.limit;
let private_message_reports = PrivateMessageReportQuery { let private_message_reports = PrivateMessageReportQuery {
unresolved_only, unresolved_only,
page, page,
@ -29,8 +27,7 @@ impl Perform for ListPrivateMessageReports {
.list(&mut context.pool()) .list(&mut context.pool())
.await?; .await?;
Ok(ListPrivateMessageReportsResponse { Ok(Json(ListPrivateMessageReportsResponse {
private_message_reports, private_message_reports,
}) }))
}
} }

View File

@ -1,3 +1,3 @@
mod create; pub mod create;
mod list; pub mod list;
mod resolve; pub mod resolve;

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
private_message::{PrivateMessageReportResponse, ResolvePrivateMessageReport}, private_message::{PrivateMessageReportResponse, ResolvePrivateMessageReport},
@ -9,19 +8,18 @@ use lemmy_db_schema::{source::private_message_report::PrivateMessageReport, trai
use lemmy_db_views::structs::PrivateMessageReportView; use lemmy_db_views::structs::PrivateMessageReportView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
#[async_trait::async_trait(?Send)]
impl Perform for ResolvePrivateMessageReport {
type Response = PrivateMessageReportResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { pub async fn resolve_pm_report(
let local_user_view = local_user_view_from_jwt(&self.auth, context).await?; data: Json<ResolvePrivateMessageReport>,
context: Data<LemmyContext>,
) -> Result<Json<PrivateMessageReportResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
is_admin(&local_user_view)?; is_admin(&local_user_view)?;
let report_id = self.report_id; let report_id = data.report_id;
let person_id = local_user_view.person.id; let person_id = local_user_view.person.id;
if self.resolved { if data.resolved {
PrivateMessageReport::resolve(&mut context.pool(), report_id, person_id) PrivateMessageReport::resolve(&mut context.pool(), report_id, person_id)
.await .await
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)?; .with_lemmy_type(LemmyErrorType::CouldntResolveReport)?;
@ -34,8 +32,7 @@ impl Perform for ResolvePrivateMessageReport {
let private_message_report_view = let private_message_report_view =
PrivateMessageReportView::read(&mut context.pool(), report_id).await?; PrivateMessageReportView::read(&mut context.pool(), report_id).await?;
Ok(PrivateMessageReportResponse { Ok(Json(PrivateMessageReportResponse {
private_message_report_view, private_message_report_view,
}) }))
}
} }

View File

@ -1,25 +1,21 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
site::{GetFederatedInstances, GetFederatedInstancesResponse}, site::GetFederatedInstancesResponse,
utils::build_federated_instances, utils::build_federated_instances,
}; };
use lemmy_db_views::structs::SiteView; use lemmy_db_views::structs::SiteView;
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetFederatedInstances {
type Response = GetFederatedInstancesResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { pub async fn get_federated_instances(
context: Data<LemmyContext>,
) -> Result<Json<GetFederatedInstancesResponse>, LemmyError> {
let site_view = SiteView::read_local(&mut context.pool()).await?; let site_view = SiteView::read_local(&mut context.pool()).await?;
let federated_instances = let federated_instances =
build_federated_instances(&site_view.local_site, &mut context.pool()).await?; build_federated_instances(&site_view.local_site, &mut context.pool()).await?;
Ok(Self::Response { Ok(Json(GetFederatedInstancesResponse {
federated_instances, federated_instances,
}) }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
site::{GetSiteResponse, LeaveAdmin}, site::{GetSiteResponse, LeaveAdmin},
@ -22,14 +21,12 @@ use lemmy_utils::{
version, version,
}; };
#[async_trait::async_trait(?Send)]
impl Perform for LeaveAdmin {
type Response = GetSiteResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<GetSiteResponse, LemmyError> { pub async fn leave_admin(
let data: &LeaveAdmin = self; data: Json<LeaveAdmin>,
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; context: Data<LemmyContext>,
) -> Result<Json<GetSiteResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
is_admin(&local_user_view)?; is_admin(&local_user_view)?;
@ -69,7 +66,7 @@ impl Perform for LeaveAdmin {
let custom_emojis = let custom_emojis =
CustomEmojiView::get_all(&mut context.pool(), site_view.local_site.id).await?; CustomEmojiView::get_all(&mut context.pool(), site_view.local_site.id).await?;
Ok(GetSiteResponse { Ok(Json(GetSiteResponse {
site_view, site_view,
admins, admins,
version: version::VERSION.to_string(), version: version::VERSION.to_string(),
@ -78,6 +75,5 @@ impl Perform for LeaveAdmin {
discussion_languages, discussion_languages,
taglines, taglines,
custom_emojis, custom_emojis,
}) }))
}
} }

View File

@ -1,5 +1,5 @@
mod federated_instances; pub mod federated_instances;
mod leave_admin; pub mod leave_admin;
mod mod_log; pub mod mod_log;
mod purge; pub mod purge;
mod registration_applications; pub mod registration_applications;

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json, Query};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
site::{GetModlog, GetModlogResponse}, site::{GetModlog, GetModlogResponse},
@ -31,15 +30,12 @@ use lemmy_db_views_moderator::structs::{
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
use ModlogActionType::*; use ModlogActionType::*;
#[async_trait::async_trait(?Send)]
impl Perform for GetModlog {
type Response = GetModlogResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<GetModlogResponse, LemmyError> { pub async fn get_mod_log(
let data: &GetModlog = self; data: Query<GetModlog>,
context: Data<LemmyContext>,
let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), context).await; ) -> Result<Json<GetModlogResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), &context).await;
let local_site = LocalSite::read(&mut context.pool()).await?; let local_site = LocalSite::read(&mut context.pool()).await?;
check_private_instance(&local_user_view, &local_site)?; check_private_instance(&local_user_view, &local_site)?;
@ -96,9 +92,7 @@ impl Perform for GetModlog {
}; };
let banned_from_community = match type_ { let banned_from_community = match type_ {
All | ModBanFromCommunity => { All | ModBanFromCommunity => ModBanFromCommunityView::list(&mut context.pool(), params).await?,
ModBanFromCommunityView::list(&mut context.pool(), params).await?
}
_ => Default::default(), _ => Default::default(),
}; };
@ -176,7 +170,7 @@ impl Perform for GetModlog {
}; };
// Return the jwt // Return the jwt
Ok(GetModlogResponse { Ok(Json(GetModlogResponse {
removed_posts, removed_posts,
locked_posts, locked_posts,
featured_posts, featured_posts,
@ -192,6 +186,5 @@ impl Perform for GetModlog {
admin_purged_posts, admin_purged_posts,
admin_purged_comments, admin_purged_comments,
hidden_communities, hidden_communities,
}) }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
site::{PurgeComment, PurgeItemResponse}, site::{PurgeComment, PurgeItemResponse},
@ -14,14 +13,12 @@ use lemmy_db_schema::{
}; };
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for PurgeComment {
type Response = PurgeItemResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { pub async fn purge_comment(
let data: &Self = self; data: Json<PurgeComment>,
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; context: Data<LemmyContext>,
) -> Result<Json<PurgeItemResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
// Only let admin purge an item // Only let admin purge an item
is_admin(&local_user_view)?; is_admin(&local_user_view)?;
@ -47,6 +44,5 @@ impl Perform for PurgeComment {
AdminPurgeComment::create(&mut context.pool(), &form).await?; AdminPurgeComment::create(&mut context.pool(), &form).await?;
Ok(PurgeItemResponse { success: true }) Ok(Json(PurgeItemResponse { success: true }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
request::purge_image_from_pictrs, request::purge_image_from_pictrs,
@ -15,14 +14,12 @@ use lemmy_db_schema::{
}; };
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for PurgeCommunity {
type Response = PurgeItemResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { pub async fn purge_community(
let data: &Self = self; data: Json<PurgeCommunity>,
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; context: Data<LemmyContext>,
) -> Result<Json<PurgeItemResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
// Only let admin purge an item // Only let admin purge an item
is_admin(&local_user_view)?; is_admin(&local_user_view)?;
@ -33,14 +30,14 @@ impl Perform for PurgeCommunity {
let community = Community::read(&mut context.pool(), community_id).await?; let community = Community::read(&mut context.pool(), community_id).await?;
if let Some(banner) = community.banner { if let Some(banner) = community.banner {
purge_image_from_pictrs(&banner, context).await.ok(); purge_image_from_pictrs(&banner, &context).await.ok();
} }
if let Some(icon) = community.icon { if let Some(icon) = community.icon {
purge_image_from_pictrs(&icon, context).await.ok(); purge_image_from_pictrs(&icon, &context).await.ok();
} }
purge_image_posts_for_community(community_id, context).await?; purge_image_posts_for_community(community_id, &context).await?;
Community::delete(&mut context.pool(), community_id).await?; Community::delete(&mut context.pool(), community_id).await?;
@ -53,6 +50,5 @@ impl Perform for PurgeCommunity {
AdminPurgeCommunity::create(&mut context.pool(), &form).await?; AdminPurgeCommunity::create(&mut context.pool(), &form).await?;
Ok(PurgeItemResponse { success: true }) Ok(Json(PurgeItemResponse { success: true }))
}
} }

View File

@ -1,4 +1,4 @@
mod comment; pub mod comment;
mod community; pub mod community;
mod person; pub mod person;
mod post; pub mod post;

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
request::purge_image_from_pictrs, request::purge_image_from_pictrs,
@ -15,14 +14,12 @@ use lemmy_db_schema::{
}; };
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for PurgePerson {
type Response = PurgeItemResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { pub async fn purge_person(
let data: &Self = self; data: Json<PurgePerson>,
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; context: Data<LemmyContext>,
) -> Result<Json<PurgeItemResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
// Only let admin purge an item // Only let admin purge an item
is_admin(&local_user_view)?; is_admin(&local_user_view)?;
@ -32,14 +29,14 @@ impl Perform for PurgePerson {
let person = Person::read(&mut context.pool(), person_id).await?; let person = Person::read(&mut context.pool(), person_id).await?;
if let Some(banner) = person.banner { if let Some(banner) = person.banner {
purge_image_from_pictrs(&banner, context).await.ok(); purge_image_from_pictrs(&banner, &context).await.ok();
} }
if let Some(avatar) = person.avatar { if let Some(avatar) = person.avatar {
purge_image_from_pictrs(&avatar, context).await.ok(); purge_image_from_pictrs(&avatar, &context).await.ok();
} }
purge_image_posts_for_person(person_id, context).await?; purge_image_posts_for_person(person_id, &context).await?;
Person::delete(&mut context.pool(), person_id).await?; Person::delete(&mut context.pool(), person_id).await?;
@ -52,6 +49,5 @@ impl Perform for PurgePerson {
AdminPurgePerson::create(&mut context.pool(), &form).await?; AdminPurgePerson::create(&mut context.pool(), &form).await?;
Ok(PurgeItemResponse { success: true }) Ok(Json(PurgeItemResponse { success: true }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
request::purge_image_from_pictrs, request::purge_image_from_pictrs,
@ -15,14 +14,12 @@ use lemmy_db_schema::{
}; };
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for PurgePost {
type Response = PurgeItemResponse;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { pub async fn purge_post(
let data: &Self = self; data: Json<PurgePost>,
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; context: Data<LemmyContext>,
) -> Result<Json<PurgeItemResponse>, LemmyError> {
let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
// Only let admin purge an item // Only let admin purge an item
is_admin(&local_user_view)?; is_admin(&local_user_view)?;
@ -34,11 +31,11 @@ impl Perform for PurgePost {
// Purge image // Purge image
if let Some(url) = post.url { if let Some(url) = post.url {
purge_image_from_pictrs(&url, context).await.ok(); purge_image_from_pictrs(&url, &context).await.ok();
} }
// Purge thumbnail // Purge thumbnail
if let Some(thumbnail_url) = post.thumbnail_url { if let Some(thumbnail_url) = post.thumbnail_url {
purge_image_from_pictrs(&thumbnail_url, context).await.ok(); purge_image_from_pictrs(&thumbnail_url, &context).await.ok();
} }
let community_id = post.community_id; let community_id = post.community_id;
@ -55,6 +52,5 @@ impl Perform for PurgePost {
AdminPurgePost::create(&mut context.pool(), &form).await?; AdminPurgePost::create(&mut context.pool(), &form).await?;
Ok(PurgeItemResponse { success: true }) Ok(Json(PurgeItemResponse { success: true }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
site::{ApproveRegistrationApplication, RegistrationApplicationResponse}, site::{ApproveRegistrationApplication, RegistrationApplicationResponse},
@ -16,13 +15,11 @@ use lemmy_db_schema::{
use lemmy_db_views::structs::{LocalUserView, RegistrationApplicationView}; use lemmy_db_views::structs::{LocalUserView, RegistrationApplicationView};
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)] pub async fn approve_registration_application(
impl Perform for ApproveRegistrationApplication { data: Json<ApproveRegistrationApplication>,
type Response = RegistrationApplicationResponse; context: Data<LemmyContext>,
) -> Result<Json<RegistrationApplicationResponse>, LemmyError> {
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let data = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let app_id = data.id; let app_id = data.id;
@ -61,8 +58,7 @@ impl Perform for ApproveRegistrationApplication {
let registration_application = let registration_application =
RegistrationApplicationView::read(&mut context.pool(), app_id).await?; RegistrationApplicationView::read(&mut context.pool(), app_id).await?;
Ok(Self::Response { Ok(Json(RegistrationApplicationResponse {
registration_application, registration_application,
}) }))
}
} }

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json, Query};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
site::{ListRegistrationApplications, ListRegistrationApplicationsResponse}, site::{ListRegistrationApplications, ListRegistrationApplicationsResponse},
@ -10,13 +9,11 @@ use lemmy_db_views::registration_application_view::RegistrationApplicationQuery;
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
/// Lists registration applications, filterable by undenied only. /// Lists registration applications, filterable by undenied only.
#[async_trait::async_trait(?Send)] pub async fn list_registration_applications(
impl Perform for ListRegistrationApplications { data: Query<ListRegistrationApplications>,
type Response = ListRegistrationApplicationsResponse; context: Data<LemmyContext>,
) -> Result<Json<ListRegistrationApplicationsResponse>, LemmyError> {
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let data = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let local_site = LocalSite::read(&mut context.pool()).await?; let local_site = LocalSite::read(&mut context.pool()).await?;
// Make sure user is an admin // Make sure user is an admin
@ -36,8 +33,7 @@ impl Perform for ListRegistrationApplications {
.list(&mut context.pool()) .list(&mut context.pool())
.await?; .await?;
Ok(Self::Response { Ok(Json(ListRegistrationApplicationsResponse {
registration_applications, registration_applications,
}) }))
}
} }

View File

@ -1,3 +1,3 @@
mod approve; pub mod approve;
mod list; pub mod list;
mod unread_count; pub mod unread_count;

View File

@ -1,5 +1,4 @@
use crate::Perform; use actix_web::web::{Data, Json, Query};
use actix_web::web::Data;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
site::{GetUnreadRegistrationApplicationCount, GetUnreadRegistrationApplicationCountResponse}, site::{GetUnreadRegistrationApplicationCount, GetUnreadRegistrationApplicationCountResponse},
@ -9,13 +8,11 @@ use lemmy_db_schema::source::local_site::LocalSite;
use lemmy_db_views::structs::RegistrationApplicationView; use lemmy_db_views::structs::RegistrationApplicationView;
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)] pub async fn get_unread_registration_application_count(
impl Perform for GetUnreadRegistrationApplicationCount { data: Query<GetUnreadRegistrationApplicationCount>,
type Response = GetUnreadRegistrationApplicationCountResponse; context: Data<LemmyContext>,
) -> Result<Json<GetUnreadRegistrationApplicationCountResponse>, LemmyError> {
async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> { let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
let data = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let local_site = LocalSite::read(&mut context.pool()).await?; let local_site = LocalSite::read(&mut context.pool()).await?;
// Only let admins do this // Only let admins do this
@ -24,11 +21,9 @@ impl Perform for GetUnreadRegistrationApplicationCount {
let verified_email_only = local_site.require_email_verification; let verified_email_only = local_site.require_email_verification;
let registration_applications = let registration_applications =
RegistrationApplicationView::get_unread_count(&mut context.pool(), verified_email_only) RegistrationApplicationView::get_unread_count(&mut context.pool(), verified_email_only).await?;
.await?;
Ok(Self::Response { Ok(Json(GetUnreadRegistrationApplicationCountResponse {
registration_applications, registration_applications,
}) }))
}
} }

View File

@ -19,7 +19,7 @@ Here is an example using [reqwest](https://crates.io/crates/reqwest):
print!("{:?}", &json); print!("{:?}", &json);
``` ```
As you can see, each API endpoint needs a parameter type ( GetPosts), path (/post/list) and response type (GetPostsResponse). You can find the paths and parameter types from [this file](https://github.com/LemmyNet/lemmy/blob/main/src/api_routes_http.rs). For the response types you need to look through the crates [lemmy_api](https://github.com/LemmyNet/lemmy/tree/main/crates/api/src) and [lemmy_api_crud](https://github.com/LemmyNet/lemmy/tree/main/crates/api_crud/src) for the place where Perform/PerformCrud is implemented for the parameter type. The response type is specified as a type parameter on the trait. As you can see, each API endpoint needs a parameter type ( GetPosts), path (/post/list) and response type (GetPostsResponse). You can find the paths and handler methods from [this file](https://github.com/LemmyNet/lemmy/blob/main/src/api_routes_http.rs). The parameter type and response type are defined on each handler method.
For a real example of a Lemmy API client, look at [lemmyBB](https://github.com/LemmyNet/lemmyBB/tree/main/src/api). For a real example of a Lemmy API client, look at [lemmyBB](https://github.com/LemmyNet/lemmyBB/tree/main/src/api).

View File

@ -51,15 +51,6 @@ pub struct Register {
pub answer: Option<String>, pub answer: Option<String>,
} }
#[skip_serializing_none]
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[cfg_attr(feature = "full", derive(TS))]
#[cfg_attr(feature = "full", ts(export))]
/// Fetches a Captcha item.
pub struct GetCaptcha {
pub auth: Option<Sensitive<String>>,
}
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "full", derive(TS))] #[cfg_attr(feature = "full", derive(TS))]

View File

@ -301,15 +301,6 @@ pub struct GetSiteResponse {
pub custom_emojis: Vec<CustomEmojiView>, pub custom_emojis: Vec<CustomEmojiView>,
} }
#[skip_serializing_none]
#[derive(Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "full", derive(TS))]
#[cfg_attr(feature = "full", ts(export))]
/// Fetches the federated instances for your site.
pub struct GetFederatedInstances {
pub auth: Option<Sensitive<String>>,
}
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "full", derive(TS))] #[cfg_attr(feature = "full", derive(TS))]

View File

@ -65,7 +65,6 @@ pub mod community;
pub mod create_or_update; pub mod create_or_update;
pub mod deletion; pub mod deletion;
pub mod following; pub mod following;
pub mod unfederated;
pub mod voting; pub mod voting;
/// Amount of time that the list of dead instances is cached. This is only updated once a day, /// Amount of time that the list of dead instances is cached. This is only updated once a day,

View File

@ -1,320 +0,0 @@
use crate::SendActivity;
use lemmy_api_common::{
comment::{
CommentReportResponse,
CommentResponse,
DistinguishComment,
GetComment,
ListCommentReports,
ListCommentReportsResponse,
ResolveCommentReport,
SaveComment,
},
community::{
CommunityResponse,
CreateCommunity,
GetCommunityResponse,
ListCommunities,
ListCommunitiesResponse,
TransferCommunity,
},
custom_emoji::{
CreateCustomEmoji,
CustomEmojiResponse,
DeleteCustomEmoji,
DeleteCustomEmojiResponse,
EditCustomEmoji,
},
person::{
AddAdmin,
AddAdminResponse,
BannedPersonsResponse,
BlockPerson,
BlockPersonResponse,
ChangePassword,
CommentReplyResponse,
GetBannedPersons,
GetCaptcha,
GetCaptchaResponse,
GetPersonMentions,
GetPersonMentionsResponse,
GetReplies,
GetRepliesResponse,
GetReportCount,
GetReportCountResponse,
GetUnreadCount,
GetUnreadCountResponse,
Login,
LoginResponse,
MarkAllAsRead,
MarkCommentReplyAsRead,
MarkPersonMentionAsRead,
PasswordChangeAfterReset,
PasswordReset,
PasswordResetResponse,
PersonMentionResponse,
Register,
SaveUserSettings,
VerifyEmail,
VerifyEmailResponse,
},
post::{
GetPost,
GetPostResponse,
GetSiteMetadata,
GetSiteMetadataResponse,
ListPostReports,
ListPostReportsResponse,
MarkPostAsRead,
PostReportResponse,
PostResponse,
ResolvePostReport,
SavePost,
},
private_message::{
CreatePrivateMessageReport,
GetPrivateMessages,
ListPrivateMessageReports,
ListPrivateMessageReportsResponse,
MarkPrivateMessageAsRead,
PrivateMessageReportResponse,
PrivateMessageResponse,
PrivateMessagesResponse,
ResolvePrivateMessageReport,
},
site::{
ApproveRegistrationApplication,
CreateSite,
EditSite,
GetFederatedInstances,
GetFederatedInstancesResponse,
GetModlog,
GetModlogResponse,
GetSite,
GetSiteResponse,
GetUnreadRegistrationApplicationCount,
GetUnreadRegistrationApplicationCountResponse,
LeaveAdmin,
ListRegistrationApplications,
ListRegistrationApplicationsResponse,
PurgeComment,
PurgeCommunity,
PurgeItemResponse,
PurgePerson,
PurgePost,
RegistrationApplicationResponse,
SiteResponse,
},
};
impl SendActivity for Register {
type Response = LoginResponse;
}
impl SendActivity for GetPrivateMessages {
type Response = PrivateMessagesResponse;
}
impl SendActivity for CreateSite {
type Response = SiteResponse;
}
impl SendActivity for EditSite {
type Response = SiteResponse;
}
impl SendActivity for GetSite {
type Response = GetSiteResponse;
}
impl SendActivity for ListCommunities {
type Response = ListCommunitiesResponse;
}
impl SendActivity for CreateCommunity {
type Response = CommunityResponse;
}
impl SendActivity for GetPost {
type Response = GetPostResponse;
}
impl SendActivity for GetComment {
type Response = CommentResponse;
}
impl SendActivity for Login {
type Response = LoginResponse;
}
impl SendActivity for GetCaptcha {
type Response = GetCaptchaResponse;
}
impl SendActivity for GetReplies {
type Response = GetRepliesResponse;
}
impl SendActivity for AddAdmin {
type Response = AddAdminResponse;
}
impl SendActivity for GetUnreadRegistrationApplicationCount {
type Response = GetUnreadRegistrationApplicationCountResponse;
}
impl SendActivity for ListRegistrationApplications {
type Response = ListRegistrationApplicationsResponse;
}
impl SendActivity for ApproveRegistrationApplication {
type Response = RegistrationApplicationResponse;
}
impl SendActivity for GetBannedPersons {
type Response = BannedPersonsResponse;
}
impl SendActivity for BlockPerson {
type Response = BlockPersonResponse;
}
impl SendActivity for GetPersonMentions {
type Response = GetPersonMentionsResponse;
}
impl SendActivity for MarkPersonMentionAsRead {
type Response = PersonMentionResponse;
}
impl SendActivity for MarkCommentReplyAsRead {
type Response = CommentReplyResponse;
}
impl SendActivity for MarkAllAsRead {
type Response = GetRepliesResponse;
}
impl SendActivity for PasswordReset {
type Response = PasswordResetResponse;
}
impl SendActivity for PasswordChangeAfterReset {
type Response = LoginResponse;
}
impl SendActivity for SaveUserSettings {
type Response = LoginResponse;
}
impl SendActivity for ChangePassword {
type Response = LoginResponse;
}
impl SendActivity for GetReportCount {
type Response = GetReportCountResponse;
}
impl SendActivity for GetUnreadCount {
type Response = GetUnreadCountResponse;
}
impl SendActivity for VerifyEmail {
type Response = VerifyEmailResponse;
}
impl SendActivity for MarkPrivateMessageAsRead {
type Response = PrivateMessageResponse;
}
impl SendActivity for CreatePrivateMessageReport {
type Response = PrivateMessageReportResponse;
}
impl SendActivity for ResolvePrivateMessageReport {
type Response = PrivateMessageReportResponse;
}
impl SendActivity for ListPrivateMessageReports {
type Response = ListPrivateMessageReportsResponse;
}
impl SendActivity for GetModlog {
type Response = GetModlogResponse;
}
impl SendActivity for PurgePerson {
type Response = PurgeItemResponse;
}
impl SendActivity for PurgeCommunity {
type Response = PurgeItemResponse;
}
impl SendActivity for PurgePost {
type Response = PurgeItemResponse;
}
impl SendActivity for PurgeComment {
type Response = PurgeItemResponse;
}
impl SendActivity for TransferCommunity {
type Response = GetCommunityResponse;
}
impl SendActivity for LeaveAdmin {
type Response = GetSiteResponse;
}
impl SendActivity for MarkPostAsRead {
type Response = PostResponse;
}
impl SendActivity for SavePost {
type Response = PostResponse;
}
impl SendActivity for ListPostReports {
type Response = ListPostReportsResponse;
}
impl SendActivity for ResolvePostReport {
type Response = PostReportResponse;
}
impl SendActivity for GetSiteMetadata {
type Response = GetSiteMetadataResponse;
}
impl SendActivity for SaveComment {
type Response = CommentResponse;
}
impl SendActivity for DistinguishComment {
type Response = CommentResponse;
}
impl SendActivity for ListCommentReports {
type Response = ListCommentReportsResponse;
}
impl SendActivity for ResolveCommentReport {
type Response = CommentReportResponse;
}
impl SendActivity for CreateCustomEmoji {
type Response = CustomEmojiResponse;
}
impl SendActivity for EditCustomEmoji {
type Response = CustomEmojiResponse;
}
impl SendActivity for DeleteCustomEmoji {
type Response = DeleteCustomEmojiResponse;
}
impl SendActivity for GetFederatedInstances {
type Response = GetFederatedInstancesResponse;
}

View File

@ -194,16 +194,3 @@ async fn insert_received_activity(
ReceivedActivity::create(&mut data.pool(), &ap_id.clone().into()).await?; ReceivedActivity::create(&mut data.pool(), &ap_id.clone().into()).await?;
Ok(()) Ok(())
} }
#[async_trait::async_trait]
pub trait SendActivity: Sync {
type Response: Sync + Send + Clone;
async fn send_activity(
_request: &Self,
_response: &Self::Response,
_context: &Data<LemmyContext>,
) -> Result<(), LemmyError> {
Ok(())
}
}

View File

@ -1,4 +1,4 @@
use actix_web::{guard, web, Error, HttpResponse, Result}; use actix_web::{guard, web};
use lemmy_api::{ use lemmy_api::{
comment::{distinguish::distinguish_comment, like::like_comment, save::save_comment}, comment::{distinguish::distinguish_comment, like::like_comment, save::save_comment},
comment_report::{ comment_report::{
@ -12,53 +12,66 @@ use lemmy_api::{
block::block_community, block::block_community,
follow::follow_community, follow::follow_community,
hide::hide_community, hide::hide_community,
transfer::transfer_community,
}, },
local_user::{ban_person::ban_from_site, notifications::mark_reply_read::mark_reply_as_read}, local_user::{
post::{feature::feature_post, like::like_post, lock::lock_post}, add_admin::add_admin,
post_report::create::create_post_report, ban_person::ban_from_site,
sitemap::get_sitemap, block::block_person,
Perform, change_password::change_password,
}; change_password_after_reset::change_password_after_reset,
use lemmy_api_common::{ get_captcha::get_captcha,
community::TransferCommunity, list_banned::list_banned_users,
context::LemmyContext, login::login,
person::{ notifications::{
AddAdmin, list_mentions::list_mentions,
BlockPerson, list_replies::list_replies,
ChangePassword, mark_all_read::mark_all_notifications_read,
GetBannedPersons, mark_mention_read::mark_person_mention_as_read,
GetCaptcha, mark_reply_read::mark_reply_as_read,
GetPersonMentions, unread_count::unread_count,
GetReplies,
GetReportCount,
GetUnreadCount,
Login,
MarkAllAsRead,
MarkPersonMentionAsRead,
PasswordChangeAfterReset,
PasswordReset,
SaveUserSettings,
VerifyEmail,
}, },
post::{GetSiteMetadata, ListPostReports, MarkPostAsRead, ResolvePostReport, SavePost}, report_count::report_count,
private_message::{ reset_password::reset_password,
CreatePrivateMessageReport, save_settings::save_user_settings,
ListPrivateMessageReports, verify_email::verify_email,
MarkPrivateMessageAsRead, },
ResolvePrivateMessageReport, post::{
feature::feature_post,
get_link_metadata::get_link_metadata,
like::like_post,
lock::lock_post,
mark_read::mark_post_as_read,
save::save_post,
},
post_report::{
create::create_post_report,
list::list_post_reports,
resolve::resolve_post_report,
},
private_message::mark_read::mark_pm_as_read,
private_message_report::{
create::create_pm_report,
list::list_pm_reports,
resolve::resolve_pm_report,
}, },
site::{ site::{
ApproveRegistrationApplication, federated_instances::get_federated_instances,
GetFederatedInstances, leave_admin::leave_admin,
GetModlog, mod_log::get_mod_log,
GetUnreadRegistrationApplicationCount, purge::{
LeaveAdmin, comment::purge_comment,
ListRegistrationApplications, community::purge_community,
PurgeComment, person::purge_person,
PurgeCommunity, post::purge_post,
PurgePerson,
PurgePost,
}, },
registration_applications::{
approve::approve_registration_application,
list::list_registration_applications,
unread_count::get_unread_registration_application_count,
},
},
sitemap::get_sitemap,
}; };
use lemmy_api_crud::{ use lemmy_api_crud::{
comment::{ comment::{
@ -96,19 +109,15 @@ use lemmy_api_crud::{
site::{create::create_site, read::get_site, update::update_site}, site::{create::create_site, read::get_site, update::update_site},
user::{create::register, delete::delete_account}, user::{create::register, delete::delete_account},
}; };
use lemmy_apub::{ use lemmy_apub::api::{
api::{
list_comments::list_comments, list_comments::list_comments,
list_posts::list_posts, list_posts::list_posts,
read_community::get_community, read_community::get_community,
read_person::read_person, read_person::read_person,
resolve_object::resolve_object, resolve_object::resolve_object,
search::search, search::search,
},
SendActivity,
}; };
use lemmy_utils::{rate_limit::RateLimitCell, spawn_try_task, SYNCHRONOUS_FEDERATION}; use lemmy_utils::rate_limit::RateLimitCell;
use serde::Deserialize;
pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) { pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
cfg.service( cfg.service(
@ -125,7 +134,7 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
.service( .service(
web::resource("/modlog") web::resource("/modlog")
.wrap(rate_limit.message()) .wrap(rate_limit.message())
.route(web::get().to(route_get::<GetModlog>)), .route(web::get().to(get_mod_log)),
) )
.service( .service(
web::resource("/search") web::resource("/search")
@ -156,14 +165,14 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
.route("/delete", web::post().to(delete_community)) .route("/delete", web::post().to(delete_community))
// Mod Actions // Mod Actions
.route("/remove", web::post().to(remove_community)) .route("/remove", web::post().to(remove_community))
.route("/transfer", web::post().to(route_post::<TransferCommunity>)) .route("/transfer", web::post().to(transfer_community))
.route("/ban_user", web::post().to(ban_from_community)) .route("/ban_user", web::post().to(ban_from_community))
.route("/mod", web::post().to(add_mod_to_community)), .route("/mod", web::post().to(add_mod_to_community)),
) )
.service( .service(
web::scope("/federated_instances") web::scope("/federated_instances")
.wrap(rate_limit.message()) .wrap(rate_limit.message())
.route("", web::get().to(route_get::<GetFederatedInstances>)), .route("", web::get().to(get_federated_instances)),
) )
// Post // Post
.service( .service(
@ -180,25 +189,16 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
.route("", web::put().to(update_post)) .route("", web::put().to(update_post))
.route("/delete", web::post().to(delete_post)) .route("/delete", web::post().to(delete_post))
.route("/remove", web::post().to(remove_post)) .route("/remove", web::post().to(remove_post))
.route( .route("/mark_as_read", web::post().to(mark_post_as_read))
"/mark_as_read",
web::post().to(route_post::<MarkPostAsRead>),
)
.route("/lock", web::post().to(lock_post)) .route("/lock", web::post().to(lock_post))
.route("/feature", web::post().to(feature_post)) .route("/feature", web::post().to(feature_post))
.route("/list", web::get().to(list_posts)) .route("/list", web::get().to(list_posts))
.route("/like", web::post().to(like_post)) .route("/like", web::post().to(like_post))
.route("/save", web::put().to(route_post::<SavePost>)) .route("/save", web::put().to(save_post))
.route("/report", web::post().to(create_post_report)) .route("/report", web::post().to(create_post_report))
.route( .route("/report/resolve", web::put().to(resolve_post_report))
"/report/resolve", .route("/report/list", web::get().to(list_post_reports))
web::put().to(route_post::<ResolvePostReport>), .route("/site_metadata", web::get().to(get_link_metadata)),
)
.route("/report/list", web::get().to(route_get::<ListPostReports>))
.route(
"/site_metadata",
web::get().to(route_get::<GetSiteMetadata>),
),
) )
// Comment // Comment
.service( .service(
@ -232,22 +232,10 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
.route("", web::post().to(create_private_message)) .route("", web::post().to(create_private_message))
.route("", web::put().to(update_private_message)) .route("", web::put().to(update_private_message))
.route("/delete", web::post().to(delete_private_message)) .route("/delete", web::post().to(delete_private_message))
.route( .route("/mark_as_read", web::post().to(mark_pm_as_read))
"/mark_as_read", .route("/report", web::post().to(create_pm_report))
web::post().to(route_post::<MarkPrivateMessageAsRead>), .route("/report/resolve", web::put().to(resolve_pm_report))
) .route("/report/list", web::get().to(list_pm_reports)),
.route(
"/report",
web::post().to(route_post::<CreatePrivateMessageReport>),
)
.route(
"/report/resolve",
web::put().to(route_post::<ResolvePrivateMessageReport>),
)
.route(
"/report/list",
web::get().to(route_get::<ListPrivateMessageReports>),
),
) )
// User // User
.service( .service(
@ -262,75 +250,66 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
// Handle captcha separately // Handle captcha separately
web::resource("/user/get_captcha") web::resource("/user/get_captcha")
.wrap(rate_limit.post()) .wrap(rate_limit.post())
.route(web::get().to(route_get::<GetCaptcha>)), .route(web::get().to(get_captcha)),
) )
// User actions // User actions
.service( .service(
web::scope("/user") web::scope("/user")
.wrap(rate_limit.message()) .wrap(rate_limit.message())
.route("", web::get().to(read_person)) .route("", web::get().to(read_person))
.route("/mention", web::get().to(route_get::<GetPersonMentions>)) .route("/mention", web::get().to(list_mentions))
.route( .route(
"/mention/mark_as_read", "/mention/mark_as_read",
web::post().to(route_post::<MarkPersonMentionAsRead>), web::post().to(mark_person_mention_as_read),
) )
.route("/replies", web::get().to(route_get::<GetReplies>)) .route("/replies", web::get().to(list_replies))
// Admin action. I don't like that it's in /user // Admin action. I don't like that it's in /user
.route("/ban", web::post().to(ban_from_site)) .route("/ban", web::post().to(ban_from_site))
.route("/banned", web::get().to(route_get::<GetBannedPersons>)) .route("/banned", web::get().to(list_banned_users))
.route("/block", web::post().to(route_post::<BlockPerson>)) .route("/block", web::post().to(block_person))
// Account actions. I don't like that they're in /user maybe /accounts // Account actions. I don't like that they're in /user maybe /accounts
.route("/login", web::post().to(route_post::<Login>)) .route("/login", web::post().to(login))
.route("/delete_account", web::post().to(delete_account)) .route("/delete_account", web::post().to(delete_account))
.route( .route("/password_reset", web::post().to(reset_password))
"/password_reset",
web::post().to(route_post::<PasswordReset>),
)
.route( .route(
"/password_change", "/password_change",
web::post().to(route_post::<PasswordChangeAfterReset>), web::post().to(change_password_after_reset),
) )
// mark_all_as_read feels off being in this section as well // mark_all_as_read feels off being in this section as well
.route( .route(
"/mark_all_as_read", "/mark_all_as_read",
web::post().to(route_post::<MarkAllAsRead>), web::post().to(mark_all_notifications_read),
) )
.route( .route("/save_user_settings", web::put().to(save_user_settings))
"/save_user_settings", .route("/change_password", web::put().to(change_password))
web::put().to(route_post::<SaveUserSettings>), .route("/report_count", web::get().to(report_count))
) .route("/unread_count", web::get().to(unread_count))
.route( .route("/verify_email", web::post().to(verify_email))
"/change_password", .route("/leave_admin", web::post().to(leave_admin)),
web::put().to(route_post::<ChangePassword>),
)
.route("/report_count", web::get().to(route_get::<GetReportCount>))
.route("/unread_count", web::get().to(route_get::<GetUnreadCount>))
.route("/verify_email", web::post().to(route_post::<VerifyEmail>))
.route("/leave_admin", web::post().to(route_post::<LeaveAdmin>)),
) )
// Admin Actions // Admin Actions
.service( .service(
web::scope("/admin") web::scope("/admin")
.wrap(rate_limit.message()) .wrap(rate_limit.message())
.route("/add", web::post().to(route_post::<AddAdmin>)) .route("/add", web::post().to(add_admin))
.route( .route(
"/registration_application/count", "/registration_application/count",
web::get().to(route_get::<GetUnreadRegistrationApplicationCount>), web::get().to(get_unread_registration_application_count),
) )
.route( .route(
"/registration_application/list", "/registration_application/list",
web::get().to(route_get::<ListRegistrationApplications>), web::get().to(list_registration_applications),
) )
.route( .route(
"/registration_application/approve", "/registration_application/approve",
web::put().to(route_post::<ApproveRegistrationApplication>), web::put().to(approve_registration_application),
) )
.service( .service(
web::scope("/purge") web::scope("/purge")
.route("/person", web::post().to(route_post::<PurgePerson>)) .route("/person", web::post().to(purge_person))
.route("/community", web::post().to(route_post::<PurgeCommunity>)) .route("/community", web::post().to(purge_community))
.route("/post", web::post().to(route_post::<PurgePost>)) .route("/post", web::post().to(purge_post))
.route("/comment", web::post().to(route_post::<PurgeComment>)), .route("/comment", web::post().to(purge_comment)),
), ),
) )
.service( .service(
@ -347,59 +326,3 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
.route("", web::get().to(get_sitemap)), .route("", web::get().to(get_sitemap)),
); );
} }
async fn perform<'a, Data>(
data: Data,
context: web::Data<LemmyContext>,
apub_data: activitypub_federation::config::Data<LemmyContext>,
) -> Result<HttpResponse, Error>
where
Data: Perform
+ SendActivity<Response = <Data as Perform>::Response>
+ Clone
+ Deserialize<'a>
+ Send
+ 'static,
{
let res = data.perform(&context).await?;
let res_clone = res.clone();
let fed_task = async move { SendActivity::send_activity(&data, &res_clone, &apub_data).await };
if *SYNCHRONOUS_FEDERATION {
fed_task.await?;
} else {
spawn_try_task(fed_task);
}
Ok(HttpResponse::Ok().json(&res))
}
async fn route_get<'a, Data>(
data: web::Query<Data>,
context: web::Data<LemmyContext>,
apub_data: activitypub_federation::config::Data<LemmyContext>,
) -> Result<HttpResponse, Error>
where
Data: Perform
+ SendActivity<Response = <Data as Perform>::Response>
+ Clone
+ Deserialize<'a>
+ Send
+ 'static,
{
perform::<Data>(data.0, context, apub_data).await
}
async fn route_post<'a, Data>(
data: web::Json<Data>,
context: web::Data<LemmyContext>,
apub_data: activitypub_federation::config::Data<LemmyContext>,
) -> Result<HttpResponse, Error>
where
Data: Perform
+ SendActivity<Response = <Data as Perform>::Response>
+ Clone
+ Deserialize<'a>
+ Send
+ 'static,
{
perform::<Data>(data.0, context, apub_data).await
}