prepare("SELECT is_admin FROM users WHERE id = ?"); $stmt->execute([$user_id]); $user = $stmt->fetch(); if ($user && $user['is_admin']) return true; $stmt = db()->prepare("SELECT owner_id FROM servers WHERE id = ?"); $stmt->execute([$server_id]); $server = $stmt->fetch(); if ($server && $server['owner_id'] == $user_id) return true; // Aggregate permissions from user's roles AND the @everyone role $stmt = db()->prepare(" SELECT BIT_OR(r.permissions) as total_perms FROM roles r LEFT JOIN user_roles ur ON r.id = ur.role_id AND ur.user_id = ? WHERE r.server_id = ? AND (ur.user_id IS NOT NULL OR r.name = '@everyone' OR r.name = 'Everyone') "); $stmt->execute([$user_id, $server_id]); $row = $stmt->fetch(); $perms = (int)($row['total_perms'] ?? 0); if ($perms & self::ADMINISTRATOR) return true; return ($perms & $permission) === $permission; } public static function canViewChannel($user_id, $channel_id) { return self::canDoInChannel($user_id, $channel_id, self::VIEW_CHANNEL); } public static function canSendInChannel($user_id, $channel_id) { return self::canDoInChannel($user_id, $channel_id, self::SEND_MESSAGES); } public static function canDoInChannel($user_id, $channel_id, $permission) { $stmt = db()->prepare("SELECT server_id FROM channels WHERE id = ?"); $stmt->execute([$channel_id]); $c = $stmt->fetch(); if (!$c) return false; $server_id = $c['server_id']; // Check if owner or admin if (self::hasPermission($user_id, $server_id, self::ADMINISTRATOR)) return true; // Fetch all relevant overrides // 1. @everyone role // 2. User's roles // 3. User specifically // Use a single query to get all relevant overrides $stmt = db()->prepare(" SELECT cp.user_id, cp.role_id, cp.allow_permissions, cp.deny_permissions, r.name as role_name FROM channel_permissions cp LEFT JOIN roles r ON cp.role_id = r.id LEFT JOIN user_roles ur ON cp.role_id = ur.role_id AND ur.user_id = ? WHERE cp.channel_id = ? AND ( cp.user_id = ? OR ur.user_id IS NOT NULL OR r.name = '@everyone' OR r.name = 'Everyone' ) "); $stmt->execute([$user_id, $channel_id, $user_id]); $overrides = $stmt->fetchAll(); if (empty($overrides)) { // No overrides, fallback to global permissions return self::hasPermission($user_id, $server_id, $permission); } // Resolution order (simplified but effective): // User overrides > Role overrides > @everyone $user_override = null; $role_allow = 0; $role_deny = 0; $everyone_override = null; foreach($overrides as $o) { if ($o['user_id'] == $user_id) { $user_override = $o; } elseif ($o['role_name'] === '@everyone' || $o['role_name'] === 'Everyone') { $everyone_override = $o; } else { $role_allow |= (int)$o['allow_permissions']; $role_deny |= (int)$o['deny_permissions']; } } // 1. User specifically if ($user_override) { if ($user_override['allow_permissions'] & $permission) return true; if ($user_override['deny_permissions'] & $permission) return false; } // 2. Roles if ($role_allow & $permission) return true; if ($role_deny & $permission) return false; // 3. @everyone if ($everyone_override) { if ($everyone_override['allow_permissions'] & $permission) return true; if ($everyone_override['deny_permissions'] & $permission) return false; } // Fallback to base permissions return self::hasPermission($user_id, $server_id, $permission); } }