use crate::{api::claims::Claims, blocking, ConnectionId, DbPool, LemmyContext, LemmyError}; use actix_web::web::Data; use lemmy_db::{ community::*, community_view::*, moderator::*, post::Post, site::*, user::*, user_view::*, Crud, }; use lemmy_utils::{slur_check, slurs_vec_to_str}; use thiserror::Error; pub mod claims; pub mod comment; pub mod community; pub mod post; pub mod site; pub mod user; #[derive(Debug, Error)] #[error("{{\"error\":\"{message}\"}}")] pub struct APIError { pub message: String, } impl APIError { pub fn err(msg: &str) -> Self { APIError { message: msg.to_string(), } } } #[async_trait::async_trait(?Send)] pub trait Perform { type Response: serde::ser::Serialize + Send; async fn perform( &self, context: &Data, websocket_id: Option, ) -> Result; } pub(in crate::api) async fn is_mod_or_admin( pool: &DbPool, user_id: i32, community_id: i32, ) -> Result<(), LemmyError> { let is_mod_or_admin = blocking(pool, move |conn| { Community::is_mod_or_admin(conn, user_id, community_id) }) .await?; if !is_mod_or_admin { return Err(APIError::err("not_a_mod_or_admin").into()); } Ok(()) } pub async fn is_admin(pool: &DbPool, user_id: i32) -> Result<(), LemmyError> { let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??; if !user.admin { return Err(APIError::err("not_an_admin").into()); } Ok(()) } pub(in crate::api) async fn get_post(post_id: i32, pool: &DbPool) -> Result { match blocking(pool, move |conn| Post::read(conn, post_id)).await? { Ok(post) => Ok(post), Err(_e) => Err(APIError::err("couldnt_find_post").into()), } } pub(in crate::api) async fn get_user_from_jwt( jwt: &str, pool: &DbPool, ) -> Result { let claims = match Claims::decode(&jwt) { Ok(claims) => claims.claims, Err(_e) => return Err(APIError::err("not_logged_in").into()), }; let user_id = claims.id; let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??; // Check for a site ban if user.banned { return Err(APIError::err("site_ban").into()); } Ok(user) } pub(in crate::api) async fn get_user_from_jwt_opt( jwt: &Option, pool: &DbPool, ) -> Result, LemmyError> { match jwt { Some(jwt) => Ok(Some(get_user_from_jwt(jwt, pool).await?)), None => Ok(None), } } pub(in crate) fn check_slurs(text: &str) -> Result<(), APIError> { if let Err(slurs) = slur_check(text) { Err(APIError::err(&slurs_vec_to_str(slurs))) } else { Ok(()) } } pub(in crate) fn check_slurs_opt(text: &Option) -> Result<(), APIError> { match text { Some(t) => check_slurs(t), None => Ok(()), } } pub(in crate::api) async fn check_community_ban( user_id: i32, community_id: i32, pool: &DbPool, ) -> Result<(), LemmyError> { let is_banned = move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok(); if blocking(pool, is_banned).await? { Err(APIError::err("community_ban").into()) } else { Ok(()) } }