1use std::borrow::Cow;
2
3use revolt_permissions::{
4 calculate_user_permissions, ChannelType, Override, PermissionQuery, PermissionValue,
5 RelationshipStatus, DEFAULT_PERMISSION_DIRECT_MESSAGE,
6};
7
8use crate::{Channel, Database, Member, Server, User};
9
10#[derive(Clone)]
12pub struct DatabasePermissionQuery<'a> {
13 #[allow(dead_code)]
14 database: &'a Database,
15
16 perspective: &'a User,
17 user: Option<Cow<'a, User>>,
18 channel: Option<Cow<'a, Channel>>,
19 server: Option<Cow<'a, Server>>,
20 member: Option<Cow<'a, Member>>,
21
22 cached_user_permission: Option<PermissionValue>,
24 cached_mutual_connection: Option<bool>,
25 cached_permission: Option<u64>,
26}
27
28#[async_trait]
29impl PermissionQuery for DatabasePermissionQuery<'_> {
30 async fn are_we_privileged(&mut self) -> bool {
34 self.perspective.privileged
35 }
36
37 async fn are_we_a_bot(&mut self) -> bool {
39 self.perspective.bot.is_some()
40 }
41
42 async fn are_the_users_same(&mut self) -> bool {
44 if let Some(other_user) = &self.user {
45 self.perspective.id == other_user.id
46 } else {
47 false
48 }
49 }
50
51 async fn user_relationship(&mut self) -> RelationshipStatus {
53 if let Some(other_user) = &self.user {
54 if self.perspective.id == other_user.id {
55 return RelationshipStatus::User;
56 } else if let Some(bot) = &other_user.bot {
57 if self.perspective.id == bot.owner {
60 return RelationshipStatus::User;
61 }
62 }
63
64 if let Some(relations) = &self.perspective.relations {
65 for entry in relations {
66 if entry.id == other_user.id {
67 return match entry.status {
68 crate::RelationshipStatus::None => RelationshipStatus::None,
69 crate::RelationshipStatus::User => RelationshipStatus::User,
70 crate::RelationshipStatus::Friend => RelationshipStatus::Friend,
71 crate::RelationshipStatus::Outgoing => RelationshipStatus::Outgoing,
72 crate::RelationshipStatus::Incoming => RelationshipStatus::Incoming,
73 crate::RelationshipStatus::Blocked => RelationshipStatus::Blocked,
74 crate::RelationshipStatus::BlockedOther => {
75 RelationshipStatus::BlockedOther
76 }
77 };
78 }
79 }
80 }
81 }
82
83 RelationshipStatus::None
84 }
85
86 async fn user_is_bot(&mut self) -> bool {
88 if let Some(other_user) = &self.user {
89 other_user.bot.is_some()
90 } else {
91 false
92 }
93 }
94
95 async fn have_mutual_connection(&mut self) -> bool {
97 if let Some(value) = self.cached_mutual_connection {
98 value
99 } else if let Some(user) = &self.user {
100 let value = self
101 .perspective
102 .has_mutual_connection(self.database, &user.id)
103 .await
104 .unwrap_or_default();
105
106 self.cached_mutual_connection = Some(value);
107 value
108 } else {
109 false
110 }
111 }
112
113 async fn are_we_server_owner(&mut self) -> bool {
117 if let Some(server) = &self.server {
118 server.owner == self.perspective.id
119 } else {
120 false
121 }
122 }
123
124 async fn are_we_a_member(&mut self) -> bool {
126 if let Some(server) = &self.server {
127 if self.member.is_some() {
128 true
129 } else if let Ok(member) = self
130 .database
131 .fetch_member(&server.id, &self.perspective.id)
132 .await
133 {
134 self.member = Some(Cow::Owned(member));
135 true
136 } else {
137 false
138 }
139 } else {
140 false
141 }
142 }
143
144 async fn get_default_server_permissions(&mut self) -> u64 {
146 if let Some(server) = &self.server {
147 server.default_permissions as u64
148 } else {
149 0
150 }
151 }
152
153 async fn get_our_server_role_overrides(&mut self) -> Vec<Override> {
155 if let Some(server) = &self.server {
156 let member_roles = self
157 .member
158 .as_ref()
159 .map(|member| member.roles.clone())
160 .unwrap_or_default();
161
162 let mut roles = server
163 .roles
164 .iter()
165 .filter(|(id, _)| member_roles.contains(id))
166 .map(|(_, role)| {
167 let v: Override = role.permissions.into();
168 (role.rank, v)
169 })
170 .collect::<Vec<(i64, Override)>>();
171
172 roles.sort_by(|a, b| b.0.cmp(&a.0));
173 roles.into_iter().map(|(_, v)| v).collect()
174 } else {
175 vec![]
176 }
177 }
178
179 async fn are_we_timed_out(&mut self) -> bool {
181 if let Some(member) = &self.member {
182 member.in_timeout()
183 } else {
184 false
185 }
186 }
187
188 async fn do_we_have_publish_overwrites(&mut self) -> bool {
189 if let Some(member) = &self.member {
190 member.can_publish
191 } else {
192 true
193 }
194 }
195
196 async fn do_we_have_receive_overwrites(&mut self) -> bool {
197 if let Some(member) = &self.member {
198 member.can_receive
199 } else {
200 true
201 }
202 }
203
204 #[allow(deprecated)]
208 async fn get_channel_type(&mut self) -> ChannelType {
209 if let Some(channel) = &self.channel {
210 match channel {
211 Cow::Borrowed(Channel::DirectMessage { .. })
212 | Cow::Owned(Channel::DirectMessage { .. }) => ChannelType::DirectMessage,
213 Cow::Borrowed(Channel::Group { .. }) | Cow::Owned(Channel::Group { .. }) => {
214 ChannelType::Group
215 }
216 Cow::Borrowed(Channel::SavedMessages { .. })
217 | Cow::Owned(Channel::SavedMessages { .. }) => ChannelType::SavedMessages,
218 Cow::Borrowed(Channel::TextChannel { .. })
219 | Cow::Owned(Channel::TextChannel { .. }) => ChannelType::ServerChannel,
220 }
221 } else {
222 ChannelType::Unknown
223 }
224 }
225
226 async fn get_default_channel_permissions(&mut self) -> Override {
229 if let Some(channel) = &self.channel {
230 match channel {
231 Cow::Borrowed(Channel::Group { permissions, .. })
232 | Cow::Owned(Channel::Group { permissions, .. }) => Override {
233 allow: permissions.unwrap_or(*DEFAULT_PERMISSION_DIRECT_MESSAGE as i64) as u64,
234 deny: 0,
235 },
236 Cow::Borrowed(Channel::TextChannel {
237 default_permissions,
238 ..
239 })
240 | Cow::Owned(Channel::TextChannel {
241 default_permissions,
242 ..
243 }) => default_permissions.unwrap_or_default().into(),
244 _ => Default::default(),
245 }
246 } else {
247 Default::default()
248 }
249 }
250
251 async fn get_our_channel_role_overrides(&mut self) -> Vec<Override> {
253 if let Some(channel) = &self.channel {
254 match channel {
255 Cow::Borrowed(Channel::TextChannel {
256 role_permissions, ..
257 })
258 | Cow::Owned(Channel::TextChannel {
259 role_permissions, ..
260 }) => {
261 if let Some(server) = &self.server {
262 let member_roles = self
263 .member
264 .as_ref()
265 .map(|member| member.roles.clone())
266 .unwrap_or_default();
267
268 let mut roles = role_permissions
269 .iter()
270 .filter(|(id, _)| member_roles.contains(id))
271 .filter_map(|(id, permission)| {
272 server.roles.get(id).map(|role| {
273 let v: Override = (*permission).into();
274 (role.rank, v)
275 })
276 })
277 .collect::<Vec<(i64, Override)>>();
278
279 roles.sort_by(|a, b| b.0.cmp(&a.0));
280 roles.into_iter().map(|(_, v)| v).collect()
281 } else {
282 vec![]
283 }
284 }
285 _ => vec![],
286 }
287 } else {
288 vec![]
289 }
290 }
291
292 async fn do_we_own_the_channel(&mut self) -> bool {
294 if let Some(channel) = &self.channel {
295 match channel {
296 Cow::Borrowed(Channel::Group { owner, .. })
297 | Cow::Owned(Channel::Group { owner, .. }) => owner == &self.perspective.id,
298 Cow::Borrowed(Channel::SavedMessages { user, .. })
299 | Cow::Owned(Channel::SavedMessages { user, .. }) => user == &self.perspective.id,
300 _ => false,
301 }
302 } else {
303 false
304 }
305 }
306
307 async fn are_we_part_of_the_channel(&mut self) -> bool {
309 if let Some(
310 Cow::Borrowed(Channel::DirectMessage { recipients, .. })
311 | Cow::Owned(Channel::DirectMessage { recipients, .. })
312 | Cow::Borrowed(Channel::Group { recipients, .. })
313 | Cow::Owned(Channel::Group { recipients, .. }),
314 ) = &self.channel
315 {
316 recipients.contains(&self.perspective.id)
317 } else {
318 false
319 }
320 }
321
322 async fn set_recipient_as_user(&mut self) {
325 if let Some(channel) = &self.channel {
326 match channel {
327 Cow::Borrowed(Channel::DirectMessage { recipients, .. })
328 | Cow::Owned(Channel::DirectMessage { recipients, .. }) => {
329 let recipient_id = recipients
330 .iter()
331 .find(|recipient| recipient != &&self.perspective.id)
332 .expect("Missing recipient for DM");
333
334 if let Ok(user) = self.database.fetch_user(recipient_id).await {
335 self.user.replace(Cow::Owned(user));
336 }
337 }
338 _ => unimplemented!(),
339 }
340 }
341 }
342
343 async fn set_server_from_channel(&mut self) {
346 if let Some(channel) = &self.channel {
347 #[allow(deprecated)]
348 match channel {
349 Cow::Borrowed(Channel::TextChannel { server, .. })
350 | Cow::Owned(Channel::TextChannel { server, .. }) => {
351 if let Some(known_server) =
352 if let Some(Cow::Borrowed(known_server)) = self.server {
355 Some(known_server)
356 } else if let Some(Cow::Owned(ref known_server)) = self.server {
357 Some(known_server)
358 } else {
359 None
360 }
361 {
362 if server == &known_server.id {
363 return;
365 }
366 }
367
368 if let Ok(server) = self.database.fetch_server(server).await {
369 self.server.replace(Cow::Owned(server));
370 }
371 }
372 _ => unimplemented!(),
373 }
374 }
375 }
376}
377
378impl<'a> DatabasePermissionQuery<'a> {
379 pub fn new(database: &'a Database, perspective: &'a User) -> DatabasePermissionQuery<'a> {
381 DatabasePermissionQuery {
382 database,
383 perspective,
384 user: None,
385 channel: None,
386 server: None,
387 member: None,
388
389 cached_mutual_connection: None,
390 cached_user_permission: None,
391 cached_permission: None,
392 }
393 }
394
395 pub async fn calc_user(mut self) -> DatabasePermissionQuery<'a> {
397 if self.cached_user_permission.is_some() {
398 return self;
399 }
400
401 if self.user.is_none() {
402 panic!("Expected `PermissionCalculator.user to exist.");
403 }
404
405 DatabasePermissionQuery {
406 cached_user_permission: Some(calculate_user_permissions(&mut self).await),
407 ..self
408 }
409 }
410
411 pub async fn calc(self) -> DatabasePermissionQuery<'a> {
413 if self.cached_permission.is_some() {
414 return self;
415 }
416
417 self
418 }
419
420 pub fn user(self, user: &'a User) -> DatabasePermissionQuery<'a> {
422 DatabasePermissionQuery {
423 user: Some(Cow::Borrowed(user)),
424 ..self
425 }
426 }
427
428 pub fn channel(self, channel: &'a Channel) -> DatabasePermissionQuery<'a> {
430 DatabasePermissionQuery {
431 channel: Some(Cow::Borrowed(channel)),
432 ..self
433 }
434 }
435
436 pub fn server(self, server: &'a Server) -> DatabasePermissionQuery<'a> {
438 DatabasePermissionQuery {
439 server: Some(Cow::Borrowed(server)),
440 ..self
441 }
442 }
443
444 pub fn member(self, member: &'a Member) -> DatabasePermissionQuery<'a> {
446 DatabasePermissionQuery {
447 member: Some(Cow::Borrowed(member)),
448 ..self
449 }
450 }
451
452 pub fn user_ref(&self) -> &Option<Cow<User>> {
454 &self.user
455 }
456
457 pub fn channel_ref(&self) -> &Option<Cow<Channel>> {
459 &self.channel
460 }
461
462 pub fn server_ref(&self) -> &Option<Cow<Server>> {
464 &self.server
465 }
466
467 pub fn member_ref(&self) -> &Option<Cow<Member>> {
469 &self.member
470 }
471
472 pub fn get_member_rank(&self) -> Option<i64> {
474 self.member
475 .as_ref()
476 .map(|member| member.get_ranking(self.server.as_ref().unwrap()))
477 }
478}
479
480pub fn perms<'a>(database: &'a Database, perspective: &'a User) -> DatabasePermissionQuery<'a> {
482 DatabasePermissionQuery::new(database, perspective)
483}