-use crate::{
- get_user_from_jwt,
- get_user_from_jwt_opt,
- get_user_safe_settings_from_jwt,
- get_user_safe_settings_from_jwt_opt,
- is_admin,
- linked_instances,
- version,
- Perform,
-};
+use crate::Perform;
use actix_web::web::Data;
use anyhow::Context;
+use lemmy_api_common::{
+ blocking,
+ build_federated_instances,
+ get_local_user_settings_view_from_jwt,
+ get_local_user_view_from_jwt,
+ get_local_user_view_from_jwt_opt,
+ is_admin,
+ site::*,
+};
use lemmy_apub::fetcher::search::search_by_apub_id;
use lemmy_db_queries::{
- diesel_option_overwrite,
- source::{category::Category_, site::Site_},
+ from_opt_str_to_opt_enum,
+ source::site::Site_,
Crud,
+ ListingType,
SearchType,
SortType,
};
-use lemmy_db_schema::{
- naive_now,
- source::{
- category::Category,
- moderator::*,
- site::{Site, *},
- },
-};
+use lemmy_db_schema::source::{moderator::*, site::Site};
use lemmy_db_views::{
comment_view::CommentQueryBuilder,
post_view::PostQueryBuilder,
};
use lemmy_db_views_actor::{
community_view::CommunityQueryBuilder,
- user_view::{UserQueryBuilder, UserViewSafe},
+ person_view::{PersonQueryBuilder, PersonViewSafe},
};
use lemmy_db_views_moderator::{
mod_add_community_view::ModAddCommunityView,
mod_remove_post_view::ModRemovePostView,
mod_sticky_post_view::ModStickyPostView,
};
-use lemmy_structs::{blocking, site::*, user::Register};
use lemmy_utils::{
location_info,
- settings::Settings,
- utils::{check_slurs, check_slurs_opt},
- APIError,
+ settings::structs::Settings,
+ version,
+ ApiError,
ConnectionId,
LemmyError,
};
-use lemmy_websocket::{
- messages::{GetUsersOnline, SendAllMessage},
- LemmyContext,
- UserOperation,
-};
-use log::{debug, info};
-use std::str::FromStr;
-
-#[async_trait::async_trait(?Send)]
-impl Perform for ListCategories {
- type Response = ListCategoriesResponse;
-
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<ListCategoriesResponse, LemmyError> {
- let _data: &ListCategories = &self;
-
- let categories = blocking(context.pool(), move |conn| Category::list_all(conn)).await??;
-
- // Return the jwt
- Ok(ListCategoriesResponse { categories })
- }
-}
+use lemmy_websocket::LemmyContext;
+use log::debug;
#[async_trait::async_trait(?Send)]
impl Perform for GetModlog {
let data: &GetModlog = &self;
let community_id = data.community_id;
- let mod_user_id = data.mod_user_id;
+ let mod_person_id = data.mod_person_id;
let page = data.page;
let limit = data.limit;
let removed_posts = blocking(context.pool(), move |conn| {
- ModRemovePostView::list(conn, community_id, mod_user_id, page, limit)
+ ModRemovePostView::list(conn, community_id, mod_person_id, page, limit)
})
.await??;
let locked_posts = blocking(context.pool(), move |conn| {
- ModLockPostView::list(conn, community_id, mod_user_id, page, limit)
+ ModLockPostView::list(conn, community_id, mod_person_id, page, limit)
})
.await??;
let stickied_posts = blocking(context.pool(), move |conn| {
- ModStickyPostView::list(conn, community_id, mod_user_id, page, limit)
+ ModStickyPostView::list(conn, community_id, mod_person_id, page, limit)
})
.await??;
let removed_comments = blocking(context.pool(), move |conn| {
- ModRemoveCommentView::list(conn, community_id, mod_user_id, page, limit)
+ ModRemoveCommentView::list(conn, community_id, mod_person_id, page, limit)
})
.await??;
let banned_from_community = blocking(context.pool(), move |conn| {
- ModBanFromCommunityView::list(conn, community_id, mod_user_id, page, limit)
+ ModBanFromCommunityView::list(conn, community_id, mod_person_id, page, limit)
})
.await??;
let added_to_community = blocking(context.pool(), move |conn| {
- ModAddCommunityView::list(conn, community_id, mod_user_id, page, limit)
+ ModAddCommunityView::list(conn, community_id, mod_person_id, page, limit)
})
.await??;
let (removed_communities, banned, added) = if data.community_id.is_none() {
blocking(context.pool(), move |conn| {
Ok((
- ModRemoveCommunityView::list(conn, mod_user_id, page, limit)?,
- ModBanView::list(conn, mod_user_id, page, limit)?,
- ModAddView::list(conn, mod_user_id, page, limit)?,
+ ModRemoveCommunityView::list(conn, mod_person_id, page, limit)?,
+ ModBanView::list(conn, mod_person_id, page, limit)?,
+ ModAddView::list(conn, mod_person_id, page, limit)?,
)) as Result<_, LemmyError>
})
.await??
}
}
-#[async_trait::async_trait(?Send)]
-impl Perform for CreateSite {
- type Response = SiteResponse;
-
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<SiteResponse, LemmyError> {
- let data: &CreateSite = &self;
-
- let read_site = move |conn: &'_ _| Site::read_simple(conn);
- if blocking(context.pool(), read_site).await?.is_ok() {
- return Err(APIError::err("site_already_exists").into());
- };
-
- let user = get_user_from_jwt(&data.auth, context.pool()).await?;
-
- check_slurs(&data.name)?;
- check_slurs_opt(&data.description)?;
-
- // Make sure user is an admin
- is_admin(context.pool(), user.id).await?;
-
- let site_form = SiteForm {
- name: data.name.to_owned(),
- description: data.description.to_owned(),
- icon: Some(data.icon.to_owned()),
- banner: Some(data.banner.to_owned()),
- creator_id: user.id,
- enable_downvotes: data.enable_downvotes,
- open_registration: data.open_registration,
- enable_nsfw: data.enable_nsfw,
- updated: None,
- };
-
- let create_site = move |conn: &'_ _| Site::create(conn, &site_form);
- if blocking(context.pool(), create_site).await?.is_err() {
- return Err(APIError::err("site_already_exists").into());
- }
-
- let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
-
- Ok(SiteResponse { site_view })
- }
-}
-
-#[async_trait::async_trait(?Send)]
-impl Perform for EditSite {
- type Response = SiteResponse;
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<SiteResponse, LemmyError> {
- let data: &EditSite = &self;
- let user = get_user_from_jwt(&data.auth, context.pool()).await?;
-
- check_slurs(&data.name)?;
- check_slurs_opt(&data.description)?;
-
- // Make sure user is an admin
- is_admin(context.pool(), user.id).await?;
-
- let found_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
-
- let icon = diesel_option_overwrite(&data.icon);
- let banner = diesel_option_overwrite(&data.banner);
-
- let site_form = SiteForm {
- name: data.name.to_owned(),
- description: data.description.to_owned(),
- icon,
- banner,
- creator_id: found_site.creator_id,
- updated: Some(naive_now()),
- enable_downvotes: data.enable_downvotes,
- open_registration: data.open_registration,
- enable_nsfw: data.enable_nsfw,
- };
-
- let update_site = move |conn: &'_ _| Site::update(conn, 1, &site_form);
- if blocking(context.pool(), update_site).await?.is_err() {
- return Err(APIError::err("couldnt_update_site").into());
- }
-
- let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
-
- let res = SiteResponse { site_view };
-
- context.chat_server().do_send(SendAllMessage {
- op: UserOperation::EditSite,
- response: res.clone(),
- websocket_id,
- });
-
- Ok(res)
- }
-}
-
-#[async_trait::async_trait(?Send)]
-impl Perform for GetSite {
- type Response = GetSiteResponse;
-
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<GetSiteResponse, LemmyError> {
- let data: &GetSite = &self;
-
- let site_view = match blocking(context.pool(), move |conn| SiteView::read(conn)).await? {
- Ok(site_view) => Some(site_view),
- // If the site isn't created yet, check the setup
- Err(_) => {
- if let Some(setup) = Settings::get().setup.as_ref() {
- let register = Register {
- username: setup.admin_username.to_owned(),
- email: setup.admin_email.to_owned(),
- password: setup.admin_password.to_owned(),
- password_verify: setup.admin_password.to_owned(),
- show_nsfw: true,
- captcha_uuid: None,
- captcha_answer: None,
- };
- let login_response = register.perform(context, websocket_id).await?;
- info!("Admin {} created", setup.admin_username);
-
- let create_site = CreateSite {
- name: setup.site_name.to_owned(),
- description: None,
- icon: None,
- banner: None,
- enable_downvotes: true,
- open_registration: true,
- enable_nsfw: true,
- auth: login_response.jwt,
- };
- create_site.perform(context, websocket_id).await?;
- info!("Site {} created", setup.site_name);
- Some(blocking(context.pool(), move |conn| SiteView::read(conn)).await??)
- } else {
- None
- }
- }
- };
-
- let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??;
-
- // Make sure the site creator is the top admin
- if let Some(site_view) = site_view.to_owned() {
- let site_creator_id = site_view.creator.id;
- // TODO investigate why this is sometimes coming back null
- // Maybe user_.admin isn't being set to true?
- if let Some(creator_index) = admins.iter().position(|r| r.user.id == site_creator_id) {
- let creator_user = admins.remove(creator_index);
- admins.insert(0, creator_user);
- }
- }
-
- let banned = blocking(context.pool(), move |conn| UserViewSafe::banned(conn)).await??;
-
- let online = context
- .chat_server()
- .send(GetUsersOnline)
- .await
- .unwrap_or(1);
-
- let my_user = get_user_safe_settings_from_jwt_opt(&data.auth, context.pool()).await?;
-
- Ok(GetSiteResponse {
- site_view,
- admins,
- banned,
- online,
- version: version::VERSION.to_string(),
- my_user,
- federated_instances: linked_instances(context.pool()).await?,
- })
- }
-}
-
#[async_trait::async_trait(?Send)]
impl Perform for Search {
type Response = SearchResponse;
Err(e) => debug!("Failed to resolve search query as activitypub ID: {}", e),
}
- let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?;
- let user_id = user.map(|u| u.id);
+ let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
+
+ let show_nsfw = local_user_view.as_ref().map(|t| t.local_user.show_nsfw);
+ let show_bot_accounts = local_user_view
+ .as_ref()
+ .map(|t| t.local_user.show_bot_accounts);
+ let show_read_posts = local_user_view
+ .as_ref()
+ .map(|t| t.local_user.show_read_posts);
- let type_ = SearchType::from_str(&data.type_)?;
+ let person_id = local_user_view.map(|u| u.person.id);
let mut posts = Vec::new();
let mut comments = Vec::new();
let q = data.q.to_owned();
let page = data.page;
let limit = data.limit;
- let sort = SortType::from_str(&data.sort)?;
+ let sort: Option<SortType> = from_opt_str_to_opt_enum(&data.sort);
+ let listing_type: Option<ListingType> = from_opt_str_to_opt_enum(&data.listing_type);
+ let search_type: SearchType = from_opt_str_to_opt_enum(&data.type_).unwrap_or(SearchType::All);
let community_id = data.community_id;
let community_name = data.community_name.to_owned();
- match type_ {
+ let creator_id = data.creator_id;
+ match search_type {
SearchType::Posts => {
posts = blocking(context.pool(), move |conn| {
PostQueryBuilder::create(conn)
- .sort(&sort)
- .show_nsfw(true)
+ .sort(sort)
+ .show_nsfw(show_nsfw)
+ .show_bot_accounts(show_bot_accounts)
+ .show_read_posts(show_read_posts)
+ .listing_type(listing_type)
.community_id(community_id)
.community_name(community_name)
- .my_user_id(user_id)
+ .creator_id(creator_id)
+ .my_person_id(person_id)
.search_term(q)
.page(page)
.limit(limit)
SearchType::Comments => {
comments = blocking(context.pool(), move |conn| {
CommentQueryBuilder::create(&conn)
- .sort(&sort)
+ .sort(sort)
+ .listing_type(listing_type)
.search_term(q)
- .my_user_id(user_id)
+ .show_bot_accounts(show_bot_accounts)
+ .community_id(community_id)
+ .community_name(community_name)
+ .creator_id(creator_id)
+ .my_person_id(person_id)
.page(page)
.limit(limit)
.list()
SearchType::Communities => {
communities = blocking(context.pool(), move |conn| {
CommunityQueryBuilder::create(conn)
- .sort(&sort)
+ .sort(sort)
+ .listing_type(listing_type)
.search_term(q)
+ .my_person_id(person_id)
.page(page)
.limit(limit)
.list()
}
SearchType::Users => {
users = blocking(context.pool(), move |conn| {
- UserQueryBuilder::create(conn)
- .sort(&sort)
+ PersonQueryBuilder::create(conn)
+ .sort(sort)
.search_term(q)
.page(page)
.limit(limit)
.await??;
}
SearchType::All => {
+ // If the community or creator is included, dont search communities or users
+ let community_or_creator_included =
+ data.community_id.is_some() || data.community_name.is_some() || data.creator_id.is_some();
+
posts = blocking(context.pool(), move |conn| {
PostQueryBuilder::create(conn)
- .sort(&sort)
- .show_nsfw(true)
+ .sort(sort)
+ .show_nsfw(show_nsfw)
+ .show_bot_accounts(show_bot_accounts)
+ .show_read_posts(show_read_posts)
+ .listing_type(listing_type)
.community_id(community_id)
.community_name(community_name)
- .my_user_id(user_id)
+ .creator_id(creator_id)
+ .my_person_id(person_id)
.search_term(q)
.page(page)
.limit(limit)
.await??;
let q = data.q.to_owned();
- let sort = SortType::from_str(&data.sort)?;
+ let community_name = data.community_name.to_owned();
comments = blocking(context.pool(), move |conn| {
CommentQueryBuilder::create(conn)
- .sort(&sort)
+ .sort(sort)
+ .listing_type(listing_type)
.search_term(q)
- .my_user_id(user_id)
+ .show_bot_accounts(show_bot_accounts)
+ .community_id(community_id)
+ .community_name(community_name)
+ .creator_id(creator_id)
+ .my_person_id(person_id)
.page(page)
.limit(limit)
.list()
.await??;
let q = data.q.to_owned();
- let sort = SortType::from_str(&data.sort)?;
- communities = blocking(context.pool(), move |conn| {
- CommunityQueryBuilder::create(conn)
- .sort(&sort)
- .search_term(q)
- .page(page)
- .limit(limit)
- .list()
- })
- .await??;
+ communities = if community_or_creator_included {
+ vec![]
+ } else {
+ blocking(context.pool(), move |conn| {
+ CommunityQueryBuilder::create(conn)
+ .sort(sort)
+ .listing_type(listing_type)
+ .search_term(q)
+ .my_person_id(person_id)
+ .page(page)
+ .limit(limit)
+ .list()
+ })
+ .await??
+ };
let q = data.q.to_owned();
- let sort = SortType::from_str(&data.sort)?;
- users = blocking(context.pool(), move |conn| {
- UserQueryBuilder::create(conn)
- .sort(&sort)
- .search_term(q)
- .page(page)
- .limit(limit)
- .list()
- })
- .await??;
+ users = if community_or_creator_included {
+ vec![]
+ } else {
+ blocking(context.pool(), move |conn| {
+ PersonQueryBuilder::create(conn)
+ .sort(sort)
+ .search_term(q)
+ .page(page)
+ .limit(limit)
+ .list()
+ })
+ .await??
+ };
}
SearchType::Url => {
posts = blocking(context.pool(), move |conn| {
PostQueryBuilder::create(conn)
- .sort(&sort)
- .show_nsfw(true)
+ .sort(sort)
+ .show_nsfw(show_nsfw)
+ .show_bot_accounts(show_bot_accounts)
+ .show_read_posts(show_read_posts)
+ .listing_type(listing_type)
+ .my_person_id(person_id)
.community_id(community_id)
.community_name(community_name)
+ .creator_id(creator_id)
.url_search(q)
.page(page)
.limit(limit)
// Return the jwt
Ok(SearchResponse {
- type_: data.type_.to_owned(),
+ type_: search_type.to_string(),
comments,
posts,
communities,
_websocket_id: Option<ConnectionId>,
) -> Result<GetSiteResponse, LemmyError> {
let data: &TransferSite = &self;
- let user = get_user_safe_settings_from_jwt(&data.auth, context.pool()).await?;
+ let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
- is_admin(context.pool(), user.id).await?;
+ is_admin(&local_user_view)?;
let read_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
// Make sure user is the creator
- if read_site.creator_id != user.id {
- return Err(APIError::err("not_an_admin").into());
+ if read_site.creator_id != local_user_view.person.id {
+ return Err(ApiError::err("not_an_admin").into());
}
- let new_creator_id = data.user_id;
+ let new_creator_id = data.person_id;
let transfer_site = move |conn: &'_ _| Site::transfer(conn, new_creator_id);
if blocking(context.pool(), transfer_site).await?.is_err() {
- return Err(APIError::err("couldnt_update_site").into());
+ return Err(ApiError::err("couldnt_update_site").into());
};
// Mod tables
let form = ModAddForm {
- mod_user_id: user.id,
- other_user_id: data.user_id,
+ mod_person_id: local_user_view.person.id,
+ other_person_id: data.person_id,
removed: Some(false),
};
let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
- let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??;
+ let mut admins = blocking(context.pool(), move |conn| PersonViewSafe::admins(conn)).await??;
let creator_index = admins
.iter()
- .position(|r| r.user.id == site_view.creator.id)
+ .position(|r| r.person.id == site_view.creator.id)
.context(location_info!())?;
- let creator_user = admins.remove(creator_index);
- admins.insert(0, creator_user);
+ let creator_person = admins.remove(creator_index);
+ admins.insert(0, creator_person);
- let banned = blocking(context.pool(), move |conn| UserViewSafe::banned(conn)).await??;
+ let banned = blocking(context.pool(), move |conn| PersonViewSafe::banned(conn)).await??;
+ let federated_instances = build_federated_instances(context.pool()).await?;
+
+ let my_user = Some(get_local_user_settings_view_from_jwt(&data.auth, context.pool()).await?);
Ok(GetSiteResponse {
site_view: Some(site_view),
banned,
online: 0,
version: version::VERSION.to_string(),
- my_user: Some(user),
- federated_instances: linked_instances(context.pool()).await?,
+ my_user,
+ federated_instances,
})
}
}
_websocket_id: Option<ConnectionId>,
) -> Result<GetSiteConfigResponse, LemmyError> {
let data: &GetSiteConfig = &self;
- let user = get_user_from_jwt(&data.auth, context.pool()).await?;
+ let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// Only let admins read this
- is_admin(context.pool(), user.id).await?;
+ is_admin(&local_user_view)?;
let config_hjson = Settings::read_config_file()?;
_websocket_id: Option<ConnectionId>,
) -> Result<GetSiteConfigResponse, LemmyError> {
let data: &SaveSiteConfig = &self;
- let user = get_user_from_jwt(&data.auth, context.pool()).await?;
+ let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
// Only let admins read this
- let user_id = user.id;
- is_admin(context.pool(), user_id).await?;
+ is_admin(&local_user_view)?;
// Make sure docker doesn't have :ro at the end of the volume, so its not a read-only filesystem
- let config_hjson = match Settings::save_config_file(&data.config_hjson) {
- Ok(config_hjson) => config_hjson,
- Err(_e) => return Err(APIError::err("couldnt_update_site").into()),
- };
+ let config_hjson = Settings::save_config_file(&data.config_hjson)
+ .map_err(|_| ApiError::err("couldnt_update_site"))?;
Ok(GetSiteConfigResponse { config_hjson })
}