Removing a few more Result<bool> . (#4977)

* Removing a few more Result<bool> .

* Running taplo fmt.

* Running fmt.

* Adding email taken test.

* Fixing tests.

* Adding back in missing admin check.

* Rename check_has_local_followers function.
This commit is contained in:
Dessalines 2024-09-23 20:55:35 -04:00 committed by GitHub
parent 62e1790ae7
commit d476d32200
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 182 additions and 220 deletions

View File

@ -21,16 +21,16 @@
},
"devDependencies": {
"@types/jest": "^29.5.12",
"@types/node": "^22.0.2",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"eslint": "^9.8.0",
"@types/node": "^22.3.0",
"@typescript-eslint/eslint-plugin": "^8.1.0",
"@typescript-eslint/parser": "^8.1.0",
"eslint": "^9.9.0",
"eslint-plugin-prettier": "^5.1.3",
"jest": "^29.5.0",
"lemmy-js-client": "0.20.0-alpha.11",
"prettier": "^3.2.5",
"ts-jest": "^29.1.0",
"typescript": "^5.5.4",
"typescript-eslint": "^8.0.0"
"typescript-eslint": "^8.1.0"
}
}

View File

@ -12,16 +12,16 @@ importers:
specifier: ^29.5.12
version: 29.5.12
'@types/node':
specifier: ^22.0.2
specifier: ^22.3.0
version: 22.3.0
'@typescript-eslint/eslint-plugin':
specifier: ^8.0.0
specifier: ^8.1.0
version: 8.1.0(@typescript-eslint/parser@8.1.0(eslint@9.9.0)(typescript@5.5.4))(eslint@9.9.0)(typescript@5.5.4)
'@typescript-eslint/parser':
specifier: ^8.0.0
specifier: ^8.1.0
version: 8.1.0(eslint@9.9.0)(typescript@5.5.4)
eslint:
specifier: ^9.8.0
specifier: ^9.9.0
version: 9.9.0
eslint-plugin-prettier:
specifier: ^5.1.3
@ -42,7 +42,7 @@ importers:
specifier: ^5.5.4
version: 5.5.4
typescript-eslint:
specifier: ^8.0.0
specifier: ^8.1.0
version: 8.1.0(eslint@9.9.0)(typescript@5.5.4)
packages:

View File

@ -628,7 +628,7 @@ test("Enforce community ban for federated user", async () => {
// Alpha tries to make post on beta, but it fails because of ban
await expect(
createPost(alpha, betaCommunity.community.id),
).rejects.toStrictEqual(Error("banned_from_community"));
).rejects.toStrictEqual(Error("person_is_banned_from_community"));
// Unban alpha
let unBanAlpha = await banPersonFromCommunity(

View File

@ -52,15 +52,12 @@ pub async fn add_mod_to_community(
// moderator. This is necessary because otherwise the action would be rejected
// by the community's home instance.
if local_user_view.local_user.admin && !community.local {
let is_mod = CommunityModeratorView::is_community_moderator(
CommunityModeratorView::check_is_community_moderator(
&mut context.pool(),
community.id,
local_user_view.person.id,
)
.await?;
if !is_mod {
Err(LemmyErrorType::NotAModerator)?
}
}
// Update in local database

View File

@ -63,9 +63,7 @@ pub async fn save_user_settings(
let previous_email = local_user_view.local_user.email.clone().unwrap_or_default();
// if email was changed, check that it is not taken and send verification mail
if previous_email.deref() != email {
if LocalUser::is_email_taken(&mut context.pool(), email).await? {
return Err(LemmyErrorType::EmailAlreadyExists)?;
}
LocalUser::check_is_email_taken(&mut context.pool(), email).await?;
send_verification_email(
&local_user_view,
email,

View File

@ -29,12 +29,8 @@ impl Claims {
let claims =
decode::<Claims>(jwt, &key, &validation).with_lemmy_type(LemmyErrorType::NotLoggedIn)?;
let user_id = LocalUserId(claims.claims.sub.parse()?);
let is_valid = LoginToken::validate(&mut context.pool(), user_id, jwt).await?;
if !is_valid {
Err(LemmyErrorType::NotLoggedIn)?
} else {
Ok(user_id)
}
LoginToken::validate(&mut context.pool(), user_id, jwt).await?;
Ok(user_id)
}
pub async fn generate(

View File

@ -73,13 +73,7 @@ pub async fn is_mod_or_admin(
community_id: CommunityId,
) -> LemmyResult<()> {
check_user_valid(person)?;
let is_mod_or_admin = CommunityView::is_mod_or_admin(pool, person.id, community_id).await?;
if !is_mod_or_admin {
Err(LemmyErrorType::NotAModOrAdmin)?
} else {
Ok(())
}
CommunityView::check_is_mod_or_admin(pool, person.id, community_id).await
}
#[tracing::instrument(skip_all)]
@ -110,13 +104,7 @@ pub async fn check_community_mod_of_any_or_admin_action(
let person = &local_user_view.person;
check_user_valid(person)?;
let is_mod_of_any_or_admin = CommunityView::is_mod_of_any_or_admin(pool, person.id).await?;
if !is_mod_of_any_or_admin {
Err(LemmyErrorType::NotAModOrAdmin)?
} else {
Ok(())
}
CommunityView::check_is_mod_of_any_or_admin(pool, person.id).await
}
pub fn is_admin(local_user_view: &LocalUserView) -> LemmyResult<()> {
@ -242,7 +230,7 @@ pub async fn check_community_user_action(
) -> LemmyResult<()> {
check_user_valid(person)?;
check_community_deleted_removed(community_id, pool).await?;
check_community_ban(person, community_id, pool).await?;
CommunityPersonBanView::check(pool, person.id, community_id).await?;
Ok(())
}
@ -257,19 +245,6 @@ async fn check_community_deleted_removed(
Ok(())
}
async fn check_community_ban(
person: &Person,
community_id: CommunityId,
pool: &mut DbPool<'_>,
) -> LemmyResult<()> {
// check if user was banned from site or community
let is_banned = CommunityPersonBanView::get(pool, person.id, community_id).await?;
if is_banned {
Err(LemmyErrorType::BannedFromCommunity)?
}
Ok(())
}
/// Check that the given user can perform a mod action in the community.
///
/// In particular it checks that he is an admin or mod, wasn't banned and the community isn't
@ -281,7 +256,7 @@ pub async fn check_community_mod_action(
pool: &mut DbPool<'_>,
) -> LemmyResult<()> {
is_mod_or_admin(pool, person, community_id).await?;
check_community_ban(person, community_id, pool).await?;
CommunityPersonBanView::check(pool, person.id, community_id).await?;
// it must be possible to restore deleted community
if !allow_deleted {
@ -307,51 +282,6 @@ pub fn check_comment_deleted_or_removed(comment: &Comment) -> LemmyResult<()> {
}
}
/// Throws an error if a recipient has blocked a person.
#[tracing::instrument(skip_all)]
pub async fn check_person_block(
my_id: PersonId,
potential_blocker_id: PersonId,
pool: &mut DbPool<'_>,
) -> LemmyResult<()> {
let is_blocked = PersonBlock::read(pool, potential_blocker_id, my_id).await?;
if is_blocked {
Err(LemmyErrorType::PersonIsBlocked)?
} else {
Ok(())
}
}
/// Throws an error if a recipient has blocked a community.
#[tracing::instrument(skip_all)]
async fn check_community_block(
community_id: CommunityId,
person_id: PersonId,
pool: &mut DbPool<'_>,
) -> LemmyResult<()> {
let is_blocked = CommunityBlock::read(pool, person_id, community_id).await?;
if is_blocked {
Err(LemmyErrorType::CommunityIsBlocked)?
} else {
Ok(())
}
}
/// Throws an error if a recipient has blocked an instance.
#[tracing::instrument(skip_all)]
async fn check_instance_block(
instance_id: InstanceId,
person_id: PersonId,
pool: &mut DbPool<'_>,
) -> LemmyResult<()> {
let is_blocked = InstanceBlock::read(pool, person_id, instance_id).await?;
if is_blocked {
Err(LemmyErrorType::InstanceIsBlocked)?
} else {
Ok(())
}
}
#[tracing::instrument(skip_all)]
pub async fn check_person_instance_community_block(
my_id: PersonId,
@ -360,9 +290,9 @@ pub async fn check_person_instance_community_block(
community_id: CommunityId,
pool: &mut DbPool<'_>,
) -> LemmyResult<()> {
check_person_block(my_id, potential_blocker_id, pool).await?;
check_instance_block(community_instance_id, potential_blocker_id, pool).await?;
check_community_block(community_id, potential_blocker_id, pool).await?;
PersonBlock::read(pool, potential_blocker_id, my_id).await?;
InstanceBlock::read(pool, potential_blocker_id, community_instance_id).await?;
CommunityBlock::read(pool, potential_blocker_id, community_id).await?;
Ok(())
}

View File

@ -95,15 +95,12 @@ pub async fn create_post(
let community = Community::read(&mut context.pool(), community_id).await?;
if community.posting_restricted_to_mods {
let community_id = data.community_id;
let is_mod = CommunityModeratorView::is_community_moderator(
CommunityModeratorView::check_is_community_moderator(
&mut context.pool(),
community_id,
local_user_view.local_user.person_id,
)
.await?;
if !is_mod {
Err(LemmyErrorType::OnlyModsCanPostInCommunity)?
}
}
// Only need to check if language is allowed in case user set it explicitly. When using default

View File

@ -5,7 +5,6 @@ use lemmy_api_common::{
private_message::{CreatePrivateMessage, PrivateMessageResponse},
send_activity::{ActivityChannel, SendActivityData},
utils::{
check_person_block,
get_interface_language,
get_url_blocklist,
local_site_to_slur_regex,
@ -16,6 +15,7 @@ use lemmy_api_common::{
use lemmy_db_schema::{
source::{
local_site::LocalSite,
person_block::PersonBlock,
private_message::{PrivateMessage, PrivateMessageInsertForm},
},
traits::Crud,
@ -39,10 +39,10 @@ pub async fn create_private_message(
let content = process_markdown(&data.content, &slur_regex, &url_blocklist, &context).await?;
is_valid_body_field(&content, false)?;
check_person_block(
local_user_view.person.id,
data.recipient_id,
PersonBlock::read(
&mut context.pool(),
data.recipient_id,
local_user_view.person.id,
)
.await?;

View File

@ -92,22 +92,15 @@ pub async fn register(
}
if local_site.site_setup && local_site.captcha_enabled {
if let Some(captcha_uuid) = &data.captcha_uuid {
let uuid = uuid::Uuid::parse_str(captcha_uuid)?;
let check = CaptchaAnswer::check_captcha(
&mut context.pool(),
CheckCaptchaAnswer {
uuid,
answer: data.captcha_answer.clone().unwrap_or_default(),
},
)
.await?;
if !check {
Err(LemmyErrorType::CaptchaIncorrect)?
}
} else {
Err(LemmyErrorType::CaptchaIncorrect)?
}
let uuid = uuid::Uuid::parse_str(&data.captcha_uuid.clone().unwrap_or_default())?;
CaptchaAnswer::check_captcha(
&mut context.pool(),
CheckCaptchaAnswer {
uuid,
answer: data.captcha_answer.clone().unwrap_or_default(),
},
)
.await?;
}
let slur_regex = local_site_to_slur_regex(&local_site);
@ -119,9 +112,7 @@ pub async fn register(
}
if let Some(email) = &data.email {
if LocalUser::is_email_taken(&mut context.pool(), email).await? {
Err(LemmyErrorType::EmailAlreadyExists)?
}
LocalUser::check_is_email_taken(&mut context.pool(), email).await?;
}
// We have to create both a person, and local_user

View File

@ -213,15 +213,13 @@ async fn can_accept_activity_in_community(
context: &Data<LemmyContext>,
) -> LemmyResult<()> {
if let Some(community) = community {
if !community.local
&& !CommunityFollower::has_local_followers(&mut context.pool(), community.id).await?
{
Err(LemmyErrorType::CommunityHasNoFollowers)?
}
// Local only community can't federate
if community.visibility != CommunityVisibility::Public {
return Err(LemmyErrorType::NotFound.into());
}
if !community.local {
CommunityFollower::check_has_local_followers(&mut context.pool(), community.id).await?
}
}
Ok(())
}

View File

@ -87,12 +87,7 @@ pub(crate) async fn verify_person_in_community(
}
let person_id = person.id;
let community_id = community.id;
let is_banned = CommunityPersonBanView::get(&mut context.pool(), person_id, community_id).await?;
if is_banned {
Err(LemmyErrorType::PersonIsBannedFromCommunity)?
} else {
Ok(())
}
CommunityPersonBanView::check(&mut context.pool(), person_id, community_id).await
}
/// Verify that mod action in community was performed by a moderator.
@ -106,14 +101,6 @@ pub(crate) async fn verify_mod_action(
community: &Community,
context: &Data<LemmyContext>,
) -> LemmyResult<()> {
let mod_ = mod_id.dereference(context).await?;
let is_mod_or_admin =
CommunityView::is_mod_or_admin(&mut context.pool(), mod_.id, community.id).await?;
if is_mod_or_admin {
return Ok(());
}
// mod action comes from the same instance as the community, so it was presumably done
// by an instance admin.
// TODO: federate instance admin status and check it here
@ -121,7 +108,8 @@ pub(crate) async fn verify_mod_action(
return Ok(());
}
Err(LemmyErrorType::NotAModerator)?
let mod_ = mod_id.dereference(context).await?;
CommunityView::check_is_mod_or_admin(&mut context.pool(), mod_.id, community.id).await
}
pub(crate) fn verify_is_public(to: &[Url], cc: &[Url]) -> LemmyResult<()> {

View File

@ -39,7 +39,7 @@ use lemmy_db_schema::{
};
use lemmy_db_views_actor::structs::CommunityModeratorView;
use lemmy_utils::{
error::{LemmyError, LemmyErrorType, LemmyResult},
error::{LemmyError, LemmyResult},
spawn_try_task,
utils::{
markdown::markdown_to_html,
@ -180,15 +180,12 @@ impl Object for ApubPost {
let creator = page.creator()?.dereference(context).await?;
let community = page.community(context).await?;
if community.posting_restricted_to_mods {
let is_mod = CommunityModeratorView::is_community_moderator(
CommunityModeratorView::check_is_community_moderator(
&mut context.pool(),
community.id,
creator.id,
)
.await?;
if !is_mod {
Err(LemmyErrorType::OnlyModsCanPostInCommunity)?
}
}
let mut name = page
.name

View File

@ -15,12 +15,13 @@ use activitypub_federation::{
use chrono::{DateTime, Utc};
use lemmy_api_common::{
context::LemmyContext,
utils::{check_person_block, get_url_blocklist, local_site_opt_to_slur_regex, process_markdown},
utils::{get_url_blocklist, local_site_opt_to_slur_regex, process_markdown},
};
use lemmy_db_schema::{
source::{
local_site::LocalSite,
person::Person,
person_block::PersonBlock,
private_message::{PrivateMessage, PrivateMessageInsertForm},
},
traits::Crud,
@ -126,7 +127,7 @@ impl Object for ApubPrivateMessage {
) -> LemmyResult<ApubPrivateMessage> {
let creator = note.attributed_to.dereference(context).await?;
let recipient = note.to[0].dereference(context).await?;
check_person_block(creator.id, recipient.id, &mut context.pool()).await?;
PersonBlock::read(&mut context.pool(), recipient.id, creator.id).await?;
let local_site = LocalSite::read(&mut context.pool()).await.ok();
let slur_regex = &local_site_opt_to_slur_regex(&local_site);

View File

@ -13,6 +13,7 @@ use diesel::{
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_utils::{error::LemmyResult, LemmyErrorType};
impl CaptchaAnswer {
pub async fn insert(pool: &mut DbPool<'_>, captcha: &CaptchaAnswerForm) -> Result<Self, Error> {
@ -27,7 +28,7 @@ impl CaptchaAnswer {
pub async fn check_captcha(
pool: &mut DbPool<'_>,
to_check: CheckCaptchaAnswer,
) -> Result<bool, Error> {
) -> LemmyResult<()> {
let conn = &mut get_conn(pool).await?;
// fetch requested captcha
@ -43,7 +44,9 @@ impl CaptchaAnswer {
.execute(conn)
.await?;
Ok(captcha_exists)
captcha_exists
.then_some(())
.ok_or(LemmyErrorType::CaptchaIncorrect.into())
}
}
@ -83,7 +86,6 @@ mod tests {
.await;
assert!(result.is_ok());
assert!(result.unwrap());
}
#[tokio::test]
@ -119,7 +121,6 @@ mod tests {
)
.await;
assert!(result_repeat.is_ok());
assert!(!result_repeat.unwrap());
assert!(result_repeat.is_err());
}
}

View File

@ -35,8 +35,7 @@ use crate::{
use chrono::{DateTime, Utc};
use diesel::{
deserialize,
dsl,
dsl::{exists, insert_into},
dsl::{self, exists, insert_into},
pg::Pg,
result::Error,
select,
@ -320,16 +319,18 @@ impl CommunityFollower {
/// Check if a remote instance has any followers on local instance. For this it is enough to check
/// if any follow relation is stored. Dont use this for local community.
pub async fn has_local_followers(
pub async fn check_has_local_followers(
pool: &mut DbPool<'_>,
remote_community_id: CommunityId,
) -> Result<bool, Error> {
) -> LemmyResult<()> {
let conn = &mut get_conn(pool).await?;
select(exists(community_follower::table.filter(
community_follower::community_id.eq(remote_community_id),
)))
.get_result(conn)
.await
.get_result::<bool>(conn)
.await?
.then_some(())
.ok_or(LemmyErrorType::CommunityHasNoFollowers.into())
}
}

View File

@ -9,26 +9,29 @@ use crate::{
utils::{get_conn, DbPool},
};
use diesel::{
dsl::{exists, insert_into},
dsl::{exists, insert_into, not},
result::Error,
select,
ExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_utils::{error::LemmyResult, LemmyErrorType};
impl CommunityBlock {
pub async fn read(
pool: &mut DbPool<'_>,
for_person_id: PersonId,
for_community_id: CommunityId,
) -> Result<bool, Error> {
) -> LemmyResult<()> {
let conn = &mut get_conn(pool).await?;
select(exists(
select(not(exists(
community_block::table.find((for_person_id, for_community_id)),
))
.get_result(conn)
.await
)))
.get_result::<bool>(conn)
.await?
.then_some(())
.ok_or(LemmyErrorType::CommunityIsBlocked.into())
}
pub async fn for_person(

View File

@ -9,26 +9,29 @@ use crate::{
utils::{get_conn, DbPool},
};
use diesel::{
dsl::{exists, insert_into},
dsl::{exists, insert_into, not},
result::Error,
select,
ExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_utils::{error::LemmyResult, LemmyErrorType};
impl InstanceBlock {
pub async fn read(
pool: &mut DbPool<'_>,
for_person_id: PersonId,
for_instance_id: InstanceId,
) -> Result<bool, Error> {
) -> LemmyResult<()> {
let conn = &mut get_conn(pool).await?;
select(exists(
select(not(exists(
instance_block::table.find((for_person_id, for_instance_id)),
))
.get_result(conn)
.await
)))
.get_result::<bool>(conn)
.await?
.then_some(())
.ok_or(LemmyErrorType::InstanceIsBlocked.into())
}
pub async fn for_person(

View File

@ -136,14 +136,16 @@ impl LocalUser {
diesel::delete(persons).execute(conn).await
}
pub async fn is_email_taken(pool: &mut DbPool<'_>, email: &str) -> Result<bool, Error> {
pub async fn check_is_email_taken(pool: &mut DbPool<'_>, email: &str) -> LemmyResult<()> {
use diesel::dsl::{exists, select};
let conn = &mut get_conn(pool).await?;
select(exists(local_user::table.filter(
select(not(exists(local_user::table.filter(
lower(coalesce(local_user::email, "")).eq(email.to_lowercase()),
)))
.get_result(conn)
.await
))))
.get_result::<bool>(conn)
.await?
.then_some(())
.ok_or(LemmyErrorType::EmailAlreadyExists.into())
}
// TODO: maybe move this and pass in LocalUserView
@ -419,4 +421,32 @@ mod tests {
Ok(())
}
#[tokio::test]
#[serial]
async fn test_email_taken() -> LemmyResult<()> {
let pool = &build_db_pool_for_tests().await;
let pool = &mut pool.into();
let darwin_email = "charles.darwin@gmail.com";
let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()).await?;
let darwin_person = PersonInsertForm::test_form(inserted_instance.id, "darwin");
let inserted_darwin_person = Person::create(pool, &darwin_person).await?;
let mut darwin_local_user_form =
LocalUserInsertForm::test_form_admin(inserted_darwin_person.id);
darwin_local_user_form.email = Some(darwin_email.into());
let _inserted_darwin_local_user =
LocalUser::create(pool, &darwin_local_user_form, vec![]).await?;
let check = LocalUser::check_is_email_taken(pool, darwin_email).await;
assert!(check.is_err());
let passed_check = LocalUser::check_is_email_taken(pool, "not_charles@gmail.com").await;
assert!(passed_check.is_ok());
Ok(())
}
}

View File

@ -7,6 +7,7 @@ use crate::{
};
use diesel::{delete, dsl::exists, insert_into, result::Error, select};
use diesel_async::RunQueryDsl;
use lemmy_utils::{error::LemmyResult, LemmyErrorType};
impl LoginToken {
pub async fn create(pool: &mut DbPool<'_>, form: LoginTokenCreateForm) -> Result<Self, Error> {
@ -22,13 +23,15 @@ impl LoginToken {
pool: &mut DbPool<'_>,
user_id_: LocalUserId,
token_: &str,
) -> Result<bool, Error> {
) -> LemmyResult<()> {
let conn = &mut get_conn(pool).await?;
select(exists(
login_token.find(token_).filter(user_id.eq(user_id_)),
))
.get_result(conn)
.await
.get_result::<bool>(conn)
.await?
.then_some(())
.ok_or(LemmyErrorType::NotLoggedIn.into())
}
pub async fn list(

View File

@ -9,7 +9,7 @@ use crate::{
utils::{get_conn, DbPool},
};
use diesel::{
dsl::{exists, insert_into},
dsl::{exists, insert_into, not},
result::Error,
select,
ExpressionMethods,
@ -17,19 +17,22 @@ use diesel::{
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_utils::{error::LemmyResult, LemmyErrorType};
impl PersonBlock {
pub async fn read(
pool: &mut DbPool<'_>,
for_person_id: PersonId,
for_recipient_id: PersonId,
) -> Result<bool, Error> {
) -> LemmyResult<()> {
let conn = &mut get_conn(pool).await?;
select(exists(
select(not(exists(
person_block::table.find((for_person_id, for_recipient_id)),
))
.get_result(conn)
.await
)))
.get_result::<bool>(conn)
.await?
.then_some(())
.ok_or(LemmyErrorType::PersonIsBlocked.into())
}
pub async fn for_person(

View File

@ -15,7 +15,13 @@ doctest = false
workspace = true
[features]
full = ["lemmy_db_schema/full", "diesel", "diesel-async", "ts-rs"]
full = [
"lemmy_db_schema/full",
"lemmy_utils/full",
"diesel",
"diesel-async",
"ts-rs",
]
[dependencies]
lemmy_db_schema = { workspace = true }
@ -33,6 +39,7 @@ serde_with = { workspace = true }
ts-rs = { workspace = true, optional = true }
chrono.workspace = true
strum = { workspace = true }
lemmy_utils = { workspace = true, optional = true }
[dev-dependencies]
serial_test = { workspace = true }

View File

@ -8,13 +8,14 @@ use lemmy_db_schema::{
source::local_user::LocalUser,
utils::{get_conn, DbPool},
};
use lemmy_utils::{error::LemmyResult, LemmyErrorType};
impl CommunityModeratorView {
pub async fn is_community_moderator(
pub async fn check_is_community_moderator(
pool: &mut DbPool<'_>,
find_community_id: CommunityId,
find_person_id: PersonId,
) -> Result<bool, Error> {
) -> LemmyResult<()> {
use lemmy_db_schema::schema::community_moderator::dsl::{
community_id,
community_moderator,
@ -27,20 +28,24 @@ impl CommunityModeratorView {
.filter(person_id.eq(find_person_id)),
))
.get_result::<bool>(conn)
.await
.await?
.then_some(())
.ok_or(LemmyErrorType::NotAModerator.into())
}
pub(crate) async fn is_community_moderator_of_any(
pool: &mut DbPool<'_>,
find_person_id: PersonId,
) -> Result<bool, Error> {
) -> LemmyResult<()> {
use lemmy_db_schema::schema::community_moderator::dsl::{community_moderator, person_id};
let conn = &mut get_conn(pool).await?;
select(exists(
community_moderator.filter(person_id.eq(find_person_id)),
))
.get_result::<bool>(conn)
.await
.await?
.then_some(())
.ok_or(LemmyErrorType::NotAModerator.into())
}
pub async fn for_community(

View File

@ -1,25 +1,33 @@
use crate::structs::CommunityPersonBanView;
use diesel::{dsl::exists, result::Error, select, ExpressionMethods, QueryDsl};
use diesel::{
dsl::{exists, not},
select,
ExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::{CommunityId, PersonId},
schema::community_person_ban,
utils::{get_conn, DbPool},
};
use lemmy_utils::{error::LemmyResult, LemmyErrorType};
impl CommunityPersonBanView {
pub async fn get(
pub async fn check(
pool: &mut DbPool<'_>,
from_person_id: PersonId,
from_community_id: CommunityId,
) -> Result<bool, Error> {
) -> LemmyResult<()> {
let conn = &mut get_conn(pool).await?;
select(exists(
select(not(exists(
community_person_ban::table
.filter(community_person_ban::community_id.eq(from_community_id))
.filter(community_person_ban::person_id.eq(from_person_id)),
))
)))
.get_result::<bool>(conn)
.await
.await?
.then_some(())
.ok_or(LemmyErrorType::PersonIsBannedFromCommunity.into())
}
}

View File

@ -26,6 +26,7 @@ use lemmy_db_schema::{
ListingType,
PostSortType,
};
use lemmy_utils::{error::LemmyResult, LemmyErrorType};
fn queries<'a>() -> Queries<
impl ReadFn<'a, CommunityView, (CommunityId, Option<&'a LocalUser>, bool)>,
@ -185,35 +186,39 @@ impl CommunityView {
.await
}
pub async fn is_mod_or_admin(
pub async fn check_is_mod_or_admin(
pool: &mut DbPool<'_>,
person_id: PersonId,
community_id: CommunityId,
) -> Result<bool, Error> {
) -> LemmyResult<()> {
let is_mod =
CommunityModeratorView::is_community_moderator(pool, community_id, person_id).await?;
if is_mod {
Ok(true)
} else if let Ok(person_view) = PersonView::read(pool, person_id).await {
Ok(person_view.is_admin)
CommunityModeratorView::check_is_community_moderator(pool, community_id, person_id).await;
if is_mod.is_ok()
|| PersonView::read(pool, person_id)
.await
.is_ok_and(|t| t.is_admin)
{
Ok(())
} else {
Ok(false)
Err(LemmyErrorType::NotAModOrAdmin)?
}
}
/// Checks if a person is an admin, or moderator of any community.
pub async fn is_mod_of_any_or_admin(
pub async fn check_is_mod_of_any_or_admin(
pool: &mut DbPool<'_>,
person_id: PersonId,
) -> Result<bool, Error> {
) -> LemmyResult<()> {
let is_mod_of_any =
CommunityModeratorView::is_community_moderator_of_any(pool, person_id).await?;
if is_mod_of_any {
Ok(true)
} else if let Ok(person_view) = PersonView::read(pool, person_id).await {
Ok(person_view.is_admin)
CommunityModeratorView::is_community_moderator_of_any(pool, person_id).await;
if is_mod_of_any.is_ok()
|| PersonView::read(pool, person_id)
.await
.is_ok_and(|t| t.is_admin)
{
Ok(())
} else {
Ok(false)
Err(LemmyErrorType::NotAModOrAdmin)?
}
}
}