diff --git a/src/api/v1/guilds/uuid/members.rs b/src/api/v1/guilds/uuid/members.rs index 0e1d2bc..56710af 100644 --- a/src/api/v1/guilds/uuid/members.rs +++ b/src/api/v1/guilds/uuid/members.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use ::uuid::Uuid; use axum::{ Extension, Json, - extract::{Path, Query, State}, + extract::{Path, State}, http::StatusCode, response::IntoResponse, }; @@ -12,14 +12,13 @@ use crate::{ AppState, api::v1::auth::CurrentUser, error::Error, - objects::{Me, Member, PaginationRequest}, + objects::{Me, Member}, utils::global_checks, }; pub async fn get( State(app_state): State>, Path(guild_uuid): Path, - Query(pagination): Query, Extension(CurrentUser(uuid)): Extension>, ) -> Result { let mut conn = app_state.pool.get().await?; @@ -30,14 +29,7 @@ pub async fn get( let me = Me::get(&mut conn, uuid).await?; - let members = Member::fetch_page( - &mut conn, - &app_state.cache_pool, - &me, - guild_uuid, - pagination, - ) - .await?; + let members = Member::fetch_all(&mut conn, &app_state.cache_pool, &me, guild_uuid).await?; Ok((StatusCode::OK, Json(members))) } diff --git a/src/api/v1/members/uuid/ban.rs b/src/api/v1/members/uuid/ban.rs index e828e69..888dca6 100644 --- a/src/api/v1/members/uuid/ban.rs +++ b/src/api/v1/members/uuid/ban.rs @@ -34,7 +34,7 @@ pub async fn post( global_checks(&mut conn, &app_state.config, uuid).await?; let member = - Member::fetch_one_with_uuid(&mut conn, &app_state.cache_pool, None, member_uuid).await?; + Member::fetch_one_with_member(&mut conn, &app_state.cache_pool, None, member_uuid).await?; let caller = Member::check_membership(&mut conn, uuid, member.guild_uuid).await?; diff --git a/src/api/v1/members/uuid/mod.rs b/src/api/v1/members/uuid/mod.rs index 5bfd129..0832192 100644 --- a/src/api/v1/members/uuid/mod.rs +++ b/src/api/v1/members/uuid/mod.rs @@ -32,7 +32,7 @@ pub async fn get( let me = Me::get(&mut conn, uuid).await?; let member = - Member::fetch_one_with_uuid(&mut conn, &app_state.cache_pool, Some(&me), member_uuid) + Member::fetch_one_with_member(&mut conn, &app_state.cache_pool, Some(&me), member_uuid) .await?; Member::check_membership(&mut conn, uuid, member.guild_uuid).await?; @@ -51,7 +51,7 @@ pub async fn delete( let me = Me::get(&mut conn, uuid).await?; let member = - Member::fetch_one_with_uuid(&mut conn, &app_state.cache_pool, Some(&me), member_uuid) + Member::fetch_one_with_member(&mut conn, &app_state.cache_pool, Some(&me), member_uuid) .await?; let deleter = Member::check_membership(&mut conn, uuid, member.guild_uuid).await?; diff --git a/src/objects/member.rs b/src/objects/member.rs index 1247ea2..a25bf66 100644 --- a/src/objects/member.rs +++ b/src/objects/member.rs @@ -1,7 +1,6 @@ use diesel::{ - Associations, BoolExpressionMethods, ExpressionMethods, Identifiable, Insertable, JoinOnDsl, - QueryDsl, Queryable, Selectable, SelectableHelper, define_sql_function, delete, insert_into, - sql_types::{Nullable, VarChar}, + ExpressionMethods, Identifiable, Insertable, QueryDsl, Queryable, Selectable, SelectableHelper, + delete, insert_into, }; use diesel_async::RunQueryDsl; use serde::{Deserialize, Serialize}; @@ -10,21 +9,14 @@ use uuid::Uuid; use crate::{ Conn, error::Error, - objects::PaginationRequest, - schema::{friends, guild_bans, guild_members, users}, + objects::{GuildBan, Me, Permissions, Role}, + schema::{guild_bans, guild_members}, }; -use super::{ - Friend, Guild, GuildBan, Me, Pagination, Permissions, Role, User, load_or_empty, - user::UserBuilder, -}; +use super::{User, load_or_empty}; -define_sql_function! { fn coalesce(x: Nullable, y: Nullable, z: VarChar) -> Text; } - -#[derive(Serialize, Queryable, Identifiable, Selectable, Insertable, Associations)] +#[derive(Serialize, Queryable, Identifiable, Selectable, Insertable)] #[diesel(table_name = guild_members)] -#[diesel(belongs_to(UserBuilder, foreign_key = user_uuid))] -#[diesel(belongs_to(Guild, foreign_key = guild_uuid))] #[diesel(primary_key(uuid))] #[diesel(check_for_backend(diesel::pg::Pg))] pub struct MemberBuilder { @@ -63,32 +55,6 @@ impl MemberBuilder { }) } - async fn build_with_parts( - &self, - conn: &mut Conn, - cache_pool: &redis::Client, - user_builder: UserBuilder, - friend: Option, - ) -> Result { - let mut user = user_builder.build(); - - if let Some(friend) = friend { - user.friends_since = Some(friend.accepted_at); - } - - let roles = Role::fetch_from_member(conn, cache_pool, self).await?; - - Ok(Member { - uuid: self.uuid, - nickname: self.nickname.clone(), - user_uuid: self.user_uuid, - guild_uuid: self.guild_uuid, - is_owner: self.is_owner, - user, - roles, - }) - } - pub async fn check_permission( &self, conn: &mut Conn, @@ -154,135 +120,52 @@ impl Member { user_uuid: Uuid, guild_uuid: Uuid, ) -> Result { - use friends::dsl as fdsl; use guild_members::dsl; - let (member, user, friend): (MemberBuilder, UserBuilder, Option) = - dsl::guild_members - .filter(dsl::guild_uuid.eq(guild_uuid)) - .filter(dsl::user_uuid.eq(user_uuid)) - .inner_join(users::table) - .left_join( - fdsl::friends.on(fdsl::uuid1 - .eq(me.uuid) - .and(fdsl::uuid2.eq(users::uuid)) - .or(fdsl::uuid2.eq(me.uuid).and(fdsl::uuid1.eq(users::uuid)))), - ) - .select(( - MemberBuilder::as_select(), - UserBuilder::as_select(), - Option::::as_select(), - )) - .get_result(conn) - .await?; + let member: MemberBuilder = dsl::guild_members + .filter(dsl::user_uuid.eq(user_uuid)) + .filter(dsl::guild_uuid.eq(guild_uuid)) + .select(MemberBuilder::as_select()) + .get_result(conn) + .await?; - member - .build_with_parts(conn, cache_pool, user, friend) - .await + member.build(conn, cache_pool, Some(me)).await } - pub async fn fetch_one_with_uuid( + pub async fn fetch_one_with_member( conn: &mut Conn, cache_pool: &redis::Client, me: Option<&Me>, uuid: Uuid, ) -> Result { - let member: MemberBuilder; - let user: UserBuilder; - let friend: Option; - use friends::dsl as fdsl; use guild_members::dsl; - if let Some(me) = me { - (member, user, friend) = dsl::guild_members - .filter(dsl::uuid.eq(uuid)) - .inner_join(users::table) - .left_join( - fdsl::friends.on(fdsl::uuid1 - .eq(me.uuid) - .and(fdsl::uuid2.eq(users::uuid)) - .or(fdsl::uuid2.eq(me.uuid).and(fdsl::uuid1.eq(users::uuid)))), - ) - .select(( - MemberBuilder::as_select(), - UserBuilder::as_select(), - Option::::as_select(), - )) - .get_result(conn) - .await?; - } else { - (member, user) = dsl::guild_members - .filter(dsl::uuid.eq(uuid)) - .inner_join(users::table) - .select((MemberBuilder::as_select(), UserBuilder::as_select())) - .get_result(conn) - .await?; + let member: MemberBuilder = dsl::guild_members + .filter(dsl::uuid.eq(uuid)) + .select(MemberBuilder::as_select()) + .get_result(conn) + .await?; - friend = None; - } - - member - .build_with_parts(conn, cache_pool, user, friend) - .await + member.build(conn, cache_pool, me).await } - pub async fn fetch_page( + pub async fn fetch_all( conn: &mut Conn, cache_pool: &redis::Client, me: &Me, guild_uuid: Uuid, - pagination: PaginationRequest, - ) -> Result, Error> { - let per_page = pagination.per_page.unwrap_or(50); - let page_multiplier: i64 = ((pagination.page - 1) * per_page).into(); - - if !(10..=100).contains(&per_page) { - return Err(Error::BadRequest( - "Invalid amount per page requested".to_string(), - )); - } - - use friends::dsl as fdsl; + ) -> Result, Error> { use guild_members::dsl; - let member_builders: Vec<(MemberBuilder, UserBuilder, Option)> = load_or_empty( + let member_builders: Vec = load_or_empty( dsl::guild_members .filter(dsl::guild_uuid.eq(guild_uuid)) - .inner_join(users::table) - .left_join( - fdsl::friends.on(fdsl::uuid1 - .eq(me.uuid) - .and(fdsl::uuid2.eq(users::uuid)) - .or(fdsl::uuid2.eq(me.uuid).and(fdsl::uuid1.eq(users::uuid)))), - ) - .limit(per_page.into()) - .offset(page_multiplier) - .order_by(coalesce( - dsl::nickname, - users::display_name, - users::username, - )) - .select(( - MemberBuilder::as_select(), - UserBuilder::as_select(), - Option::::as_select(), - )) + .select(MemberBuilder::as_select()) .load(conn) .await, )?; - let pages = Member::count(conn, guild_uuid).await? as f32 / per_page as f32; + let mut members = vec![]; - let mut members = Pagination:: { - objects: Vec::with_capacity(member_builders.len()), - amount: member_builders.len() as i32, - pages: pages.ceil() as i32, - page: pagination.page, - }; - - for (member, user, friend) in member_builders { - members.objects.push( - member - .build_with_parts(conn, cache_pool, user, friend) - .await?, - ); + for builder in member_builders { + members.push(builder.build(conn, cache_pool, Some(me)).await?); } Ok(members) diff --git a/src/objects/mod.rs b/src/objects/mod.rs index 5a013ca..3bcce9c 100644 --- a/src/objects/mod.rs +++ b/src/objects/mod.rs @@ -4,7 +4,7 @@ use lettre::{ transport::smtp::authentication::Credentials, }; use log::debug; -use serde::{Deserialize, Serialize}; +use serde::Deserialize; use uuid::Uuid; mod bans; @@ -76,20 +76,6 @@ impl Cookies for Request { } */ -#[derive(Serialize)] -pub struct Pagination { - objects: Vec, - amount: i32, - pages: i32, - page: i32, -} - -#[derive(Deserialize)] -pub struct PaginationRequest { - pub page: i32, - pub per_page: Option, -} - fn load_or_empty( query_result: Result, diesel::result::Error>, ) -> Result, diesel::result::Error> { diff --git a/src/objects/user.rs b/src/objects/user.rs index c91b809..e9f638a 100644 --- a/src/objects/user.rs +++ b/src/objects/user.rs @@ -22,7 +22,7 @@ pub struct UserBuilder { } impl UserBuilder { - pub fn build(self) -> User { + fn build(self) -> User { User { uuid: self.uuid, username: self.username, @@ -38,14 +38,14 @@ impl UserBuilder { #[derive(Deserialize, Serialize, Clone)] pub struct User { - pub uuid: Uuid, + uuid: Uuid, username: String, display_name: Option, avatar: Option, pronouns: Option, about: Option, online_status: i16, - pub friends_since: Option>, + friends_since: Option>, } impl User {