feat(core): provide user profile where appropriate

This commit is contained in:
Paul Makles
2023-10-16 09:33:36 +01:00
parent 0b6e5dd9db
commit cb97004d3f
9 changed files with 96 additions and 54 deletions

View File

@@ -60,7 +60,7 @@ impl AbstractMessages for ReferenceDb {
.cloned() .cloned()
.collect(); .collect();
// TODO: sorting, etc // TODO: sorting, etc (will be required for tests)
Ok(matched_messages) Ok(matched_messages)

View File

@@ -391,14 +391,14 @@ impl User {
EventV1::UserRelationship { EventV1::UserRelationship {
id: target.id.clone(), id: target.id.clone(),
user: self.clone().into(Some(&*target)).await, user: self.clone().into(db, Some(&*target)).await,
} }
.private(target.id.clone()) .private(target.id.clone())
.await; .await;
EventV1::UserRelationship { EventV1::UserRelationship {
id: self.id.clone(), id: self.id.clone(),
user: target.clone().into(Some(&*self)).await, user: target.clone().into(db, Some(&*self)).await,
} }
.private(self.id.clone()) .private(self.id.clone())
.await; .await;

View File

@@ -1,4 +1,7 @@
use revolt_models::v0::*; use revolt_models::v0::*;
use revolt_permissions::{calculate_user_permissions, UserPermission};
use crate::{util::permissions::DatabasePermissionQuery, Database};
impl crate::Bot { impl crate::Bot {
pub fn into_public_bot(self, user: crate::User) -> PublicBot { pub fn into_public_bot(self, user: crate::User) -> PublicBot {
@@ -635,43 +638,69 @@ impl From<crate::FieldsRole> for FieldsRole {
} }
impl crate::User { impl crate::User {
pub async fn into<'a, P>(self, perspective: P) -> User pub async fn into<'a, P>(self, db: &Database, perspective: P) -> User
where where
P: Into<Option<&'a crate::User>>, P: Into<Option<&'a crate::User>>,
{ {
let relationship = if let Some(perspective) = perspective.into() { let perspective = perspective.into();
let (relationship, can_see_profile) = if self.bot.is_some() {
(RelationshipStatus::None, true)
} else if let Some(perspective) = perspective {
let mut query = DatabasePermissionQuery::new(db, perspective).user(&self);
if perspective.id == self.id { if perspective.id == self.id {
RelationshipStatus::User (RelationshipStatus::User, true)
} else { } else {
perspective (
.relations perspective
.as_ref() .relations
.map(|relations| { .as_ref()
relations .map(|relations| {
.iter() relations
.find(|relationship| relationship.id == self.id) .iter()
.map(|relationship| relationship.status.clone().into()) .find(|relationship| relationship.id == self.id)
.unwrap_or_default() .map(|relationship| relationship.status.clone().into())
}) .unwrap_or_default()
.unwrap_or_default() })
.unwrap_or_default(),
calculate_user_permissions(&mut query)
.await
.has_user_permission(UserPermission::ViewProfile),
)
} }
} else { } else {
RelationshipStatus::None (RelationshipStatus::None, false)
}; };
// do permission stuff here
// TODO: implement permissions =)
let can_see_profile = false;
User { User {
username: self.username, username: self.username,
discriminator: self.discriminator, discriminator: self.discriminator,
display_name: self.display_name, display_name: self.display_name,
avatar: self.avatar.map(|file| file.into()), avatar: self.avatar.map(|file| file.into()),
relations: vec![], relations: if let Some(crate::User { id, .. }) = perspective {
if id == &self.id {
self.relations
.unwrap_or_default()
.into_iter()
.map(|relation| relation.into())
.collect()
} else {
vec![]
}
} else {
vec![]
},
badges: self.badges.unwrap_or_default() as u32, badges: self.badges.unwrap_or_default() as u32,
status: None, status: if can_see_profile {
profile: None, self.status.map(|status| status.into())
} else {
None
},
profile: if can_see_profile {
self.profile.map(|profile| profile.into())
} else {
None
},
flags: self.flags.unwrap_or_default() as u32, flags: self.flags.unwrap_or_default() as u32,
privileged: self.privileged, privileged: self.privileged,
bot: self.bot.map(|bot| bot.into()), bot: self.bot.map(|bot| bot.into()),

View File

@@ -1,7 +1,8 @@
use std::borrow::Cow; use std::borrow::Cow;
use revolt_permissions::{ use revolt_permissions::{
calculate_user_permissions, ChannelType, Override, PermissionQuery, RelationshipStatus, calculate_user_permissions, ChannelType, Override, PermissionQuery, PermissionValue,
RelationshipStatus,
}; };
use crate::{Channel, Database, Member, Server, User}; use crate::{Channel, Database, Member, Server, User};
@@ -19,7 +20,8 @@ pub struct DatabasePermissionQuery<'a> {
member: Option<Cow<'a, Member>>, member: Option<Cow<'a, Member>>,
// flag_known_relationship: Option<&'a RelationshipStatus>, // flag_known_relationship: Option<&'a RelationshipStatus>,
cached_user_permission: Option<u32>, cached_user_permission: Option<PermissionValue>,
cached_mutual_connection: Option<bool>,
cached_permission: Option<u64>, cached_permission: Option<u64>,
} }
@@ -49,6 +51,10 @@ impl PermissionQuery for DatabasePermissionQuery<'_> {
/// Get the relationship with have with the currently selected user /// Get the relationship with have with the currently selected user
async fn user_relationship(&mut self) -> RelationshipStatus { async fn user_relationship(&mut self) -> RelationshipStatus {
if let Some(other_user) = &self.user { if let Some(other_user) = &self.user {
if self.perspective.id == other_user.id {
return RelationshipStatus::User;
}
if let Some(relations) = &self.perspective.relations { if let Some(relations) = &self.perspective.relations {
for entry in relations { for entry in relations {
if entry.id == other_user.id { if entry.id == other_user.id {
@@ -82,14 +88,17 @@ impl PermissionQuery for DatabasePermissionQuery<'_> {
/// Do we have a mutual connection with the currently selected user? /// Do we have a mutual connection with the currently selected user?
async fn have_mutual_connection(&mut self) -> bool { async fn have_mutual_connection(&mut self) -> bool {
if let Some(user) = &self.user { if let Some(value) = self.cached_mutual_connection {
// TODO: cache result? value
matches!( } else if let Some(user) = &self.user {
self.perspective let value = self
.has_mutual_connection(self.database, &user.id) .perspective
.await, .has_mutual_connection(self.database, &user.id)
Ok(true) .await
) .unwrap_or_default();
self.cached_mutual_connection = Some(value);
matches!(value, true)
} else { } else {
false false
} }
@@ -352,6 +361,7 @@ impl<'a> DatabasePermissionQuery<'a> {
server: None, server: None,
member: None, member: None,
cached_mutual_connection: None,
cached_user_permission: None, cached_user_permission: None,
cached_permission: None, cached_permission: None,
} }

View File

@@ -5,37 +5,37 @@ use crate::{
}; };
/// Calculate permissions against a user /// Calculate permissions against a user
pub async fn calculate_user_permissions<P: PermissionQuery>(query: &mut P) -> u32 { pub async fn calculate_user_permissions<P: PermissionQuery>(query: &mut P) -> PermissionValue {
if query.are_we_privileged().await { if query.are_we_privileged().await {
return u32::MAX; return u64::MAX.into();
} }
if query.are_the_users_same().await { if query.are_the_users_same().await {
return u32::MAX; return u64::MAX.into();
} }
let mut permissions = 0_u32; let mut permissions = 0_u64;
match query.user_relationship().await { match query.user_relationship().await {
RelationshipStatus::Friend => return u32::MAX, RelationshipStatus::Friend => return u64::MAX.into(),
RelationshipStatus::Blocked | RelationshipStatus::BlockedOther => { RelationshipStatus::Blocked | RelationshipStatus::BlockedOther => {
return UserPermission::Access as u32 return (UserPermission::Access as u64).into()
} }
RelationshipStatus::Incoming | RelationshipStatus::Outgoing => { RelationshipStatus::Incoming | RelationshipStatus::Outgoing => {
permissions = UserPermission::Access as u32; permissions = UserPermission::Access as u64;
} }
_ => {} _ => {}
} }
if query.have_mutual_connection().await { if query.have_mutual_connection().await {
permissions = UserPermission::Access + UserPermission::ViewProfile; permissions = UserPermission::Access as u64 + UserPermission::ViewProfile as u64;
if query.user_is_bot().await || query.are_we_a_bot().await { if query.user_is_bot().await || query.are_we_a_bot().await {
permissions += UserPermission::SendMessage as u32; permissions += UserPermission::SendMessage as u64;
} }
permissions permissions.into()
} else { } else {
permissions permissions.into()
} }
} }
@@ -81,9 +81,7 @@ pub async fn calculate_channel_permissions<P: PermissionQuery>(query: &mut P) ->
query.set_recipient_as_user().await; query.set_recipient_as_user().await;
let permissions = calculate_user_permissions(query).await; let permissions = calculate_user_permissions(query).await;
if (permissions & UserPermission::SendMessage as u32) if permissions.has_user_permission(UserPermission::SendMessage) {
== UserPermission::SendMessage as u32
{
(*DEFAULT_PERMISSION_DIRECT_MESSAGE).into() (*DEFAULT_PERMISSION_DIRECT_MESSAGE).into()
} else { } else {
(*DEFAULT_PERMISSION_VIEW_ONLY).into() (*DEFAULT_PERMISSION_VIEW_ONLY).into()

View File

@@ -8,7 +8,7 @@ pub use server::*;
pub use user::*; pub use user::*;
/// Holds a permission value to manipulate. /// Holds a permission value to manipulate.
#[derive(Debug)] #[derive(Clone, Debug)]
pub struct PermissionValue(u64); pub struct PermissionValue(u64);
impl PermissionValue { impl PermissionValue {
@@ -43,6 +43,11 @@ impl PermissionValue {
(self.0 & v) == v (self.0 & v) == v
} }
/// Check whether certain a user permission has been granted
pub fn has_user_permission(&self, permission: UserPermission) -> bool {
self.has(permission as u64)
}
/// Check whether certain a channel permission has been granted /// Check whether certain a channel permission has been granted
pub fn has_channel_permission(&self, permission: ChannelPermission) -> bool { pub fn has_channel_permission(&self, permission: ChannelPermission) -> bool {
self.has(permission as u64) self.has(permission as u64)

View File

@@ -12,7 +12,7 @@ async fn validate_user_permissions() {
let mut query = Scenario {}; let mut query = Scenario {};
let perms = calculate_user_permissions(&mut query).await; let perms = calculate_user_permissions(&mut query).await;
assert_eq!(perms, u32::MAX); assert!(perms.has(u64::MAX));
let perms = calculate_channel_permissions(&mut query).await; let perms = calculate_channel_permissions(&mut query).await;
let value: u64 = perms.into(); let value: u64 = perms.into();

View File

@@ -23,7 +23,7 @@ pub async fn fetch_bot(
} }
Ok(Json(FetchBotResponse { Ok(Json(FetchBotResponse {
user: db.fetch_user(&bot.id).await?.into(None).await, user: db.fetch_user(&bot.id).await?.into(db, None).await,
bot: bot.into(), bot: bot.into(),
})) }))
} }

View File

@@ -62,7 +62,7 @@ pub async fn message_send(
} }
// Create the message // Create the message
let author: v0::User = user.clone().into(Some(&user)).await; let author: v0::User = user.clone().into(db, Some(&user)).await;
Ok(Json( Ok(Json(
Message::create_from_api( Message::create_from_api(
db, db,