rootspring revisó este gist . Ir a la revisión
1 file changed, 179 insertions
member.rs(archivo creado)
@@ -0,0 +1,179 @@ | |||
1 | + | use kittycat::perms::Permission; | |
2 | + | use serenity::all::{GuildId, RoleId, UserId}; | |
3 | + | ||
4 | + | /// Rederive permissions rederives the permissions given a member id and a list of roles | |
5 | + | /// | |
6 | + | /// Calling rederive_perms has some side-effects | |
7 | + | /// | |
8 | + | /// 0. The member will automatically be added to the guild_members table if they are not already in it | |
9 | + | /// 1. Resolved_perms_cache will be updated in the guild_members table | |
10 | + | pub async fn rederive_perms( | |
11 | + | pool: &sqlx::PgPool, | |
12 | + | guild_id: GuildId, | |
13 | + | user_id: UserId, | |
14 | + | roles: &[RoleId], | |
15 | + | ) -> Result<Vec<Permission>, crate::Error> { | |
16 | + | let roles_str = { | |
17 | + | let mut r = Vec::new(); | |
18 | + | ||
19 | + | for role in roles { | |
20 | + | r.push(role.to_string()); | |
21 | + | } | |
22 | + | ||
23 | + | r.push(guild_id.everyone_role().to_string()); | |
24 | + | ||
25 | + | r | |
26 | + | }; | |
27 | + | ||
28 | + | let mut tx = pool.begin().await?; | |
29 | + | ||
30 | + | let rec = sqlx::query!( | |
31 | + | "SELECT perm_overrides FROM guild_members WHERE guild_id = $1 AND user_id = $2", | |
32 | + | guild_id.to_string(), | |
33 | + | user_id.to_string() | |
34 | + | ) | |
35 | + | .fetch_optional(&mut *tx) | |
36 | + | .await?; | |
37 | + | ||
38 | + | // Rederive permissions for the new perms | |
39 | + | let role_perms = sqlx::query!( | |
40 | + | "SELECT role_id, perms, index FROM guild_roles WHERE guild_id = $1 AND role_id = ANY($2)", | |
41 | + | guild_id.to_string(), | |
42 | + | &roles_str | |
43 | + | ) | |
44 | + | .fetch_all(&mut *tx) | |
45 | + | .await?; | |
46 | + | ||
47 | + | let mut user_positions = Vec::new(); | |
48 | + | ||
49 | + | for role in role_perms { | |
50 | + | user_positions.push(kittycat::perms::PartialStaffPosition { | |
51 | + | id: role.role_id, | |
52 | + | perms: role | |
53 | + | .perms | |
54 | + | .iter() | |
55 | + | .map(|x| Permission::from_string(x)) | |
56 | + | .collect(), | |
57 | + | index: role.index, | |
58 | + | }) | |
59 | + | } | |
60 | + | ||
61 | + | let (in_db, perm_overrides) = if let Some(rec) = rec { | |
62 | + | ( | |
63 | + | true, | |
64 | + | rec.perm_overrides | |
65 | + | .iter() | |
66 | + | .map(|x| Permission::from_string(x)) | |
67 | + | .collect(), | |
68 | + | ) | |
69 | + | } else { | |
70 | + | (false, Vec::new()) | |
71 | + | }; | |
72 | + | ||
73 | + | let resolved_perms = kittycat::perms::StaffPermissions { | |
74 | + | user_positions, | |
75 | + | perm_overrides, | |
76 | + | } | |
77 | + | .resolve(); | |
78 | + | ||
79 | + | let resolved_perms_str = resolved_perms | |
80 | + | .iter() | |
81 | + | .map(|x| x.to_string()) | |
82 | + | .collect::<Vec<String>>(); | |
83 | + | ||
84 | + | if in_db { | |
85 | + | sqlx::query!( | |
86 | + | "UPDATE guild_members SET roles = $1, resolved_perms_cache = $2, needs_perm_rederive = false WHERE guild_id = $3 AND user_id = $4", | |
87 | + | &roles_str, | |
88 | + | &resolved_perms_str, | |
89 | + | guild_id.to_string(), | |
90 | + | user_id.to_string() | |
91 | + | ) | |
92 | + | .execute(&mut *tx) | |
93 | + | .await?; | |
94 | + | } else { | |
95 | + | // Check if guild is in the guilds table | |
96 | + | let guild_exists = sqlx::query!( | |
97 | + | "SELECT COUNT(*) FROM guilds WHERE id = $1", | |
98 | + | guild_id.to_string() | |
99 | + | ) | |
100 | + | .fetch_one(&mut *tx) | |
101 | + | .await?; | |
102 | + | ||
103 | + | if guild_exists.count.unwrap_or_default() == 0 { | |
104 | + | sqlx::query!("INSERT INTO guilds (id) VALUES ($1)", guild_id.to_string()) | |
105 | + | .execute(&mut *tx) | |
106 | + | .await?; | |
107 | + | } | |
108 | + | ||
109 | + | sqlx::query!( | |
110 | + | "INSERT INTO guild_members (guild_id, user_id, roles, resolved_perms_cache) VALUES ($1, $2, $3, $4)", | |
111 | + | guild_id.to_string(), | |
112 | + | user_id.to_string(), | |
113 | + | &roles_str, | |
114 | + | &resolved_perms_str | |
115 | + | ) | |
116 | + | .execute(&mut *tx) | |
117 | + | .await?; | |
118 | + | } | |
119 | + | ||
120 | + | tx.commit().await?; | |
121 | + | ||
122 | + | Ok(resolved_perms) | |
123 | + | } | |
124 | + | ||
125 | + | /// Returns the kittycat permissions of a user. This function also takes into account permission overrides etc. | |
126 | + | pub async fn get_kittycat_perms( | |
127 | + | pool: &sqlx::PgPool, | |
128 | + | guild_id: GuildId, | |
129 | + | guild_owner_id: UserId, | |
130 | + | user_id: UserId, | |
131 | + | roles: &[RoleId], | |
132 | + | ) -> Result<Vec<Permission>, crate::Error> { | |
133 | + | // For now, owners have full permission, this may change in the future (maybe??) | |
134 | + | if guild_owner_id == user_id { | |
135 | + | return Ok(vec!["global.*".into()]); | |
136 | + | } | |
137 | + | ||
138 | + | let everyone_role = guild_id.everyone_role(); | |
139 | + | ||
140 | + | let rec = sqlx::query!("SELECT roles, needs_perm_rederive, resolved_perms_cache, perm_overrides FROM guild_members WHERE guild_id = $1 AND user_id = $2", guild_id.to_string(), user_id.to_string()) | |
141 | + | .fetch_optional(pool) | |
142 | + | .await?; | |
143 | + | ||
144 | + | if let Some(rec) = rec { | |
145 | + | if rec.needs_perm_rederive { | |
146 | + | return rederive_perms(pool, guild_id, user_id, roles).await; | |
147 | + | } | |
148 | + | ||
149 | + | // Check user roles against db roles | |
150 | + | let db_roles = rec.roles; | |
151 | + | ||
152 | + | let mut roles_changed = false; | |
153 | + | ||
154 | + | for role in roles { | |
155 | + | if !db_roles.contains(&role.to_string()) { | |
156 | + | roles_changed = true; | |
157 | + | break; | |
158 | + | } | |
159 | + | } | |
160 | + | ||
161 | + | // Check everyone role too | |
162 | + | if !db_roles.contains(&everyone_role.to_string()) { | |
163 | + | roles_changed = true; | |
164 | + | } | |
165 | + | ||
166 | + | if !roles_changed { | |
167 | + | Ok(rec | |
168 | + | .resolved_perms_cache | |
169 | + | .iter() | |
170 | + | .map(|x| Permission::from_string(x)) | |
171 | + | .collect::<Vec<Permission>>()) // Then use the resolved perms cache | |
172 | + | } else { | |
173 | + | Ok(rederive_perms(pool, guild_id, user_id, roles).await?) | |
174 | + | } | |
175 | + | } else { | |
176 | + | // They have no column in db, we cannot have a fast-path as the everyone role may have permissions | |
177 | + | Ok(rederive_perms(pool, guild_id, user_id, roles).await?) | |
178 | + | } | |
179 | + | } |
Siguiente
Anterior