@@ -240,8 +240,7 @@ CREATE TABLE user_permission_overrides (
240
240
PRIMARY KEY (room, " user" ),
241
241
CHECK (NOT (banned AND (moderator OR admin))) /* Mods/admins cannot be banned */
242
242
);
243
- CREATE INDEX user_permission_overrides_public_mods ON
244
- user_permission_overrides(room) WHERE moderator OR admin;
243
+ CREATE INDEX user_permission_overrides_mods ON user_permission_overrides(room) WHERE moderator;
245
244
246
245
-- Create a trigger to maintain the implication "admin implies moderator"
247
246
CREATE OR REPLACE FUNCTION trigger_user_perms_admins_are_mods ()
@@ -360,7 +359,8 @@ EXECUTE PROCEDURE trigger_room_metadata_pinned_remove();
360
359
361
360
-- View of permissions; for users with an entry in user_permissions we use those values; for null
362
361
-- values or no user_permissions entry we return the room's default read/write values (and false for
363
- -- the other fields).
362
+ -- the other fields). This view should only be used for querying individual user permissions as it
363
+ -- will involve a full table scan on `users` if not given a "user" value in the query.
364
364
CREATE VIEW user_permissions AS
365
365
SELECT
366
366
rooms .id AS room,
@@ -388,6 +388,44 @@ FROM
388
388
users CROSS JOIN rooms LEFT OUTER JOIN user_permission_overrides ON
389
389
(users .id = user_permission_overrides." user" AND rooms .id = user_permission_overrides .room );
390
390
391
+ -- Used to accesses the moderator list for a room. This view is considerably faster than querying
392
+ -- the `user_permissions` table for a list of all moderators.
393
+ CREATE VIEW room_moderators AS
394
+ SELECT session_id, mods.* FROM (
395
+ SELECT
396
+ room,
397
+ " user" ,
398
+ -- visible_mod gets priority from the per-room row if it exists, so we use 3/2 for the
399
+ -- per-room value below, 1/0 for the global value, take the max, then look for an odd value
400
+ -- to give us the visibility bit:
401
+ CAST(MAX (visible_mod) & 1 AS BOOLEAN ) AS visible_mod,
402
+ bool_or(admin) AS admin,
403
+ bool_or(room_moderator) AS room_moderator,
404
+ bool_or(global_moderator) AS global_moderator
405
+ FROM (
406
+ SELECT
407
+ room,
408
+ " user" ,
409
+ CASE WHEN visible_mod THEN 3 ELSE 2 END AS visible_mod,
410
+ admin,
411
+ TRUE AS room_moderator,
412
+ FALSE AS global_moderator
413
+ FROM user_permission_overrides WHERE moderator
414
+
415
+ UNION ALL
416
+
417
+ SELECT
418
+ rooms .id AS room,
419
+ users .id as " user" ,
420
+ CASE WHEN visible_mod THEN 1 ELSE 0 END AS visible_mod,
421
+ admin,
422
+ FALSE as room_moderator,
423
+ TRUE as global_moderator
424
+ FROM users CROSS JOIN rooms WHERE moderator
425
+ ) m GROUP BY " user" , room
426
+ ) mods JOIN users on " user" = users .id ;
427
+
428
+
391
429
-- Scheduled changes to user permissions. For example, to implement a 2-day timeout you would set
392
430
-- their user_permissions.write to false, then set a `write = true` entry with a +2d timestamp here.
393
431
-- Or to implement a join delay you could set room defaults to false then insert a value here to be
0 commit comments