Projet final V5 + Forum V2
This commit is contained in:
parent
f56ab7ba2b
commit
68972bbe6c
@ -227,7 +227,13 @@ if (empty($content) && empty($attachment_url)) {
|
||||
}
|
||||
|
||||
// Check granular permissions
|
||||
if (!Permissions::canSendInChannel($user_id, $channel_id)) {
|
||||
$can_send = Permissions::canSendInChannel($user_id, $channel_id);
|
||||
if ($thread_id) {
|
||||
// For threads, we check the specific thread permission instead of the general channel permission
|
||||
$can_send = Permissions::canDoInChannel($user_id, $channel_id, Permissions::SEND_MESSAGES_IN_THREADS);
|
||||
}
|
||||
|
||||
if (!$can_send) {
|
||||
echo json_encode(['success' => false, 'error' => 'You do not have permission to send messages in this channel.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
@ -65,7 +65,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
['value' => 4, 'name' => 'Manage Messages'],
|
||||
['value' => 8, 'name' => 'Manage Channels'],
|
||||
['value' => 16, 'name' => 'Manage Server'],
|
||||
['value' => 32, 'name' => 'Administrator']
|
||||
['value' => 32, 'name' => 'Administrator'],
|
||||
['value' => 64, 'name' => 'Create Thread'],
|
||||
['value' => 128, 'name' => 'Manage Tags'],
|
||||
['value' => 256, 'name' => 'Pin Threads'],
|
||||
['value' => 512, 'name' => 'Lock Threads'],
|
||||
['value' => 1024, 'name' => 'Send Messages in Threads']
|
||||
]
|
||||
]);
|
||||
exit;
|
||||
|
||||
@ -29,7 +29,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$stmt = db()->prepare("SELECT server_id FROM channels WHERE id = ?");
|
||||
$stmt->execute([$channel_id]);
|
||||
$chan = $stmt->fetch();
|
||||
if (!$chan || !Permissions::hasPermission($user_id, $chan['server_id'], Permissions::MANAGE_CHANNELS)) {
|
||||
if (!$chan || !Permissions::canDoInChannel($user_id, $channel_id, Permissions::MANAGE_TAGS)) {
|
||||
echo json_encode(['success' => false, 'error' => 'Unauthorized']);
|
||||
exit;
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!Permissions::canSendInChannel($user_id, $channel_id)) {
|
||||
if (!Permissions::canDoInChannel($user_id, $channel_id, Permissions::CREATE_THREAD)) {
|
||||
echo json_encode(['success' => false, 'error' => 'You do not have permission to create threads in this channel.']);
|
||||
exit;
|
||||
}
|
||||
@ -81,28 +81,41 @@ if ($_SERVER['REQUEST_METHOD'] === 'PATCH' || $_SERVER['REQUEST_METHOD'] === 'DE
|
||||
Permissions::hasPermission($user_id, $thread['server_id'], Permissions::MANAGE_MESSAGES) ||
|
||||
$server['owner_id'] == $user_id;
|
||||
|
||||
if ($thread['user_id'] != $user_id && !$is_admin) {
|
||||
echo json_encode(['success' => false, 'error' => 'Unauthorized']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
if ($action === 'solve') {
|
||||
if ($thread['user_id'] != $user_id && !$is_admin) {
|
||||
echo json_encode(['success' => false, 'error' => 'Unauthorized']); exit;
|
||||
}
|
||||
$stmt = db()->prepare("UPDATE forum_threads SET solution_message_id = ? WHERE id = ?");
|
||||
$stmt->execute([$message_id, $thread_id]);
|
||||
} elseif ($action === 'pin') {
|
||||
if (!Permissions::canDoInChannel($user_id, $thread['channel_id'], Permissions::PIN_THREADS)) {
|
||||
echo json_encode(['success' => false, 'error' => 'You do not have permission to pin threads.']); exit;
|
||||
}
|
||||
$stmt = db()->prepare("UPDATE forum_threads SET is_pinned = 1 WHERE id = ?");
|
||||
$stmt->execute([$thread_id]);
|
||||
} elseif ($action === 'unpin') {
|
||||
if (!Permissions::canDoInChannel($user_id, $thread['channel_id'], Permissions::PIN_THREADS)) {
|
||||
echo json_encode(['success' => false, 'error' => 'You do not have permission to unpin threads.']); exit;
|
||||
}
|
||||
$stmt = db()->prepare("UPDATE forum_threads SET is_pinned = 0 WHERE id = ?");
|
||||
$stmt->execute([$thread_id]);
|
||||
} elseif ($action === 'lock') {
|
||||
if (!Permissions::canDoInChannel($user_id, $thread['channel_id'], Permissions::LOCK_THREADS)) {
|
||||
echo json_encode(['success' => false, 'error' => 'You do not have permission to lock threads.']); exit;
|
||||
}
|
||||
$stmt = db()->prepare("UPDATE forum_threads SET is_locked = 1 WHERE id = ?");
|
||||
$stmt->execute([$thread_id]);
|
||||
} elseif ($action === 'unlock') {
|
||||
if (!Permissions::canDoInChannel($user_id, $thread['channel_id'], Permissions::LOCK_THREADS)) {
|
||||
echo json_encode(['success' => false, 'error' => 'You do not have permission to unlock threads.']); exit;
|
||||
}
|
||||
$stmt = db()->prepare("UPDATE forum_threads SET is_locked = 0 WHERE id = ?");
|
||||
$stmt->execute([$thread_id]);
|
||||
} elseif ($action === 'delete') {
|
||||
if ($thread['user_id'] != $user_id && !$is_admin) {
|
||||
echo json_encode(['success' => false, 'error' => 'Unauthorized']); exit;
|
||||
}
|
||||
db()->beginTransaction();
|
||||
// Delete associated tags
|
||||
$stmt = db()->prepare("DELETE FROM thread_tags WHERE thread_id = ?");
|
||||
|
||||
@ -1256,8 +1256,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
return perm.user_id == id && perm.type === 'member';
|
||||
}) || { allow_permissions: 0, deny_permissions: 0 };
|
||||
|
||||
updateToggleUI(1, p.allow_permissions, p.deny_permissions);
|
||||
updateToggleUI(2, p.allow_permissions, p.deny_permissions);
|
||||
document.querySelectorAll('.perm-tri-state').forEach(group => {
|
||||
const bit = parseInt(group.dataset.permBit);
|
||||
updateToggleUI(bit, p.allow_permissions, p.deny_permissions);
|
||||
});
|
||||
}
|
||||
|
||||
function updateToggleUI(bit, allowPerms, denyPerms) {
|
||||
@ -1311,8 +1313,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
|
||||
if (!p) {
|
||||
p = { channel_id: channelId, allow_permissions: 0, deny_permissions: 0 };
|
||||
p = { channel_id: channelId, allow_permissions: 0, deny_permissions: 0, type: type };
|
||||
if (type === 'role') p.role_id = id; else p.user_id = id;
|
||||
channelPermissionsData.push(p);
|
||||
}
|
||||
|
||||
let allow = parseInt(p.allow_permissions);
|
||||
|
||||
@ -7,6 +7,11 @@ class Permissions {
|
||||
const MANAGE_CHANNELS = 8;
|
||||
const MANAGE_SERVER = 16;
|
||||
const ADMINISTRATOR = 32;
|
||||
const CREATE_THREAD = 64;
|
||||
const MANAGE_TAGS = 128;
|
||||
const PIN_THREADS = 256;
|
||||
const LOCK_THREADS = 512;
|
||||
const SEND_MESSAGES_IN_THREADS = 1024;
|
||||
|
||||
public static function hasPermission($user_id, $server_id, $permission) {
|
||||
$stmt = db()->prepare("SELECT is_admin FROM users WHERE id = ?");
|
||||
@ -19,11 +24,12 @@ class Permissions {
|
||||
$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 SUM(r.permissions) as total_perms
|
||||
SELECT BIT_OR(r.permissions) as total_perms
|
||||
FROM roles r
|
||||
JOIN user_roles ur ON r.id = ur.role_id
|
||||
WHERE ur.user_id = ? AND r.server_id = ?
|
||||
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();
|
||||
@ -34,56 +40,14 @@ class Permissions {
|
||||
}
|
||||
|
||||
public static function canViewChannel($user_id, $channel_id) {
|
||||
$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 overrides for all roles the user has in this server
|
||||
$stmt = db()->prepare("
|
||||
SELECT cp.allow_permissions, cp.deny_permissions
|
||||
FROM channel_permissions cp
|
||||
JOIN user_roles ur ON cp.role_id = ur.role_id
|
||||
WHERE ur.user_id = ? AND cp.channel_id = ?
|
||||
");
|
||||
$stmt->execute([$user_id, $channel_id]);
|
||||
$overrides = $stmt->fetchAll();
|
||||
|
||||
// Check @everyone override specifically (even if user has no roles assigned)
|
||||
$stmt = db()->prepare("SELECT id FROM roles WHERE server_id = ? AND (name = '@everyone' OR name = 'Everyone') LIMIT 1");
|
||||
$stmt->execute([$server_id]);
|
||||
$everyone_role = $stmt->fetch();
|
||||
if ($everyone_role) {
|
||||
$stmt = db()->prepare("SELECT allow_permissions, deny_permissions FROM channel_permissions WHERE channel_id = ? AND role_id = ?");
|
||||
$stmt->execute([$channel_id, $everyone_role['id']]);
|
||||
$eo = $stmt->fetch();
|
||||
if ($eo) {
|
||||
$overrides[] = $eo;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($overrides)) {
|
||||
return true; // Default to yes
|
||||
}
|
||||
|
||||
$allow = false;
|
||||
$deny = false;
|
||||
foreach($overrides as $o) {
|
||||
if ($o['allow_permissions'] & self::VIEW_CHANNEL) $allow = true;
|
||||
if ($o['deny_permissions'] & self::VIEW_CHANNEL) $deny = true;
|
||||
}
|
||||
|
||||
if ($allow) return true;
|
||||
if ($deny) return false;
|
||||
|
||||
return true; // Default to yes
|
||||
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();
|
||||
@ -93,39 +57,68 @@ class Permissions {
|
||||
// Check if owner or admin
|
||||
if (self::hasPermission($user_id, $server_id, self::ADMINISTRATOR)) return true;
|
||||
|
||||
// Check overrides
|
||||
// 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.allow_permissions, cp.deny_permissions
|
||||
FROM channel_permissions cp
|
||||
JOIN user_roles ur ON cp.role_id = ur.role_id
|
||||
WHERE ur.user_id = ? AND cp.channel_id = ?
|
||||
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]);
|
||||
$stmt->execute([$user_id, $channel_id, $user_id]);
|
||||
$overrides = $stmt->fetchAll();
|
||||
|
||||
// Check @everyone override
|
||||
$stmt = db()->prepare("SELECT id FROM roles WHERE server_id = ? AND (name = '@everyone' OR name = 'Everyone') LIMIT 1");
|
||||
$stmt->execute([$server_id]);
|
||||
$everyone_role = $stmt->fetch();
|
||||
if ($everyone_role) {
|
||||
$stmt = db()->prepare("SELECT allow_permissions, deny_permissions FROM channel_permissions WHERE channel_id = ? AND role_id = ?");
|
||||
$stmt->execute([$channel_id, $everyone_role['id']]);
|
||||
$eo = $stmt->fetch();
|
||||
if ($eo) {
|
||||
$overrides[] = $eo;
|
||||
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'];
|
||||
}
|
||||
}
|
||||
|
||||
$allow = false;
|
||||
$deny = false;
|
||||
foreach($overrides as $o) {
|
||||
if ($o['allow_permissions'] & self::SEND_MESSAGES) $allow = true;
|
||||
if ($o['deny_permissions'] & self::SEND_MESSAGES) $deny = true;
|
||||
// 1. User specifically
|
||||
if ($user_override) {
|
||||
if ($user_override['allow_permissions'] & $permission) return true;
|
||||
if ($user_override['deny_permissions'] & $permission) return false;
|
||||
}
|
||||
|
||||
if ($allow) return true;
|
||||
if ($deny) return false;
|
||||
// 2. Roles
|
||||
if ($role_allow & $permission) return true;
|
||||
if ($role_deny & $permission) return false;
|
||||
|
||||
return self::hasPermission($user_id, $server_id, self::SEND_MESSAGES);
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
145
index.php
145
index.php
@ -719,19 +719,23 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
<div class="thread-view-container p-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<a href="?server_id=<?php echo $active_server_id; ?>&channel_id=<?php echo $active_channel_id; ?><?php echo isset($_GET['status']) ? '&status='.htmlspecialchars($_GET['status']) : ''; ?>" class="btn btn-sm btn-outline-secondary">← Back to Forum</a>
|
||||
<?php if ($active_thread['user_id'] == $current_user_id || $can_manage_server): ?>
|
||||
<div class="d-flex gap-2">
|
||||
<div class="d-flex gap-2">
|
||||
<?php if (Permissions::canDoInChannel($current_user_id, $active_channel_id, Permissions::PIN_THREADS)): ?>
|
||||
<button class="btn btn-sm <?php echo $active_thread['is_pinned'] ? 'btn-primary' : 'btn-outline-primary'; ?>" id="toggle-pin-thread" data-id="<?php echo $active_thread['id']; ?>" data-pinned="<?php echo $active_thread['is_pinned']; ?>">
|
||||
<i class="fa-solid fa-thumbtack me-1"></i> <?php echo $active_thread['is_pinned'] ? 'Unpin' : 'Pin'; ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<?php if (Permissions::canDoInChannel($current_user_id, $active_channel_id, Permissions::LOCK_THREADS)): ?>
|
||||
<button class="btn btn-sm <?php echo $active_thread['is_locked'] ? 'btn-warning' : 'btn-outline-warning'; ?>" id="toggle-lock-thread" data-id="<?php echo $active_thread['id']; ?>" data-locked="<?php echo $active_thread['is_locked']; ?>">
|
||||
<i class="fa-solid <?php echo $active_thread['is_locked'] ? 'fa-unlock' : 'fa-lock'; ?> me-1"></i> <?php echo $active_thread['is_locked'] ? 'Unlock' : 'Lock'; ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<?php if ($active_thread['user_id'] == $current_user_id || $can_manage_server): ?>
|
||||
<button class="btn btn-sm btn-outline-danger" id="delete-thread-btn" data-id="<?php echo $active_thread['id']; ?>" data-channel-id="<?php echo $active_channel_id; ?>" data-server-id="<?php echo $active_server_id; ?>">
|
||||
<i class="fa-solid fa-trash me-1"></i> Delete
|
||||
</button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<h3>
|
||||
<?php if($active_thread['is_pinned']): ?><i class="fa-solid fa-thumbtack text-primary me-2 small"></i><?php endif; ?>
|
||||
@ -934,10 +938,12 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<?php if($can_manage_channels): ?>
|
||||
<?php if(Permissions::canDoInChannel($current_user_id, $active_channel_id, Permissions::MANAGE_TAGS)): ?>
|
||||
<button class="btn btn-outline-secondary" id="manage-tags-btn">Manage Tags</button>
|
||||
<?php endif; ?>
|
||||
<button class="btn btn-primary" id="new-thread-btn">New Discussion</button>
|
||||
<?php if(Permissions::canDoInChannel($current_user_id, $active_channel_id, Permissions::CREATE_THREAD)): ?>
|
||||
<button class="btn btn-primary" id="new-thread-btn">New Discussion</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="thread-list">
|
||||
@ -1104,7 +1110,11 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
<div class="chat-input-container">
|
||||
<?php
|
||||
require_once 'includes/permissions.php';
|
||||
$can_send = Permissions::canSendInChannel($current_user_id, $active_channel_id);
|
||||
if ($active_thread) {
|
||||
$can_send = Permissions::canDoInChannel($current_user_id, $active_channel_id, Permissions::SEND_MESSAGES_IN_THREADS);
|
||||
} else {
|
||||
$can_send = Permissions::canSendInChannel($current_user_id, $active_channel_id);
|
||||
}
|
||||
$show_input = true;
|
||||
if ($channel_type === 'rules') $show_input = false;
|
||||
if ($channel_type === 'forum' && !$active_thread) $show_input = false;
|
||||
@ -2225,24 +2235,109 @@ async function handleSaveUserSettings(btn) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="permission-item mb-3 p-2 rounded" style="background: var(--separator-soft);">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="pe-3">
|
||||
<div class="fw-bold" style="color: #ffffff; font-size: 0.9em;">Send Messages</div>
|
||||
<div style="font-size: 0.75em; color: #b5bac1;">Allows members to send messages in this channel.</div>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm perm-tri-state" data-perm-bit="2">
|
||||
<input type="radio" class="btn-check" name="perm_2" id="perm_2_deny" value="deny">
|
||||
<label class="btn btn-outline-danger border-0" for="perm_2_deny" title="Deny"><i class="fa-solid fa-xmark"></i></label>
|
||||
|
||||
<input type="radio" class="btn-check" name="perm_2" id="perm_2_neutral" value="neutral" checked>
|
||||
<label class="btn btn-outline-secondary border-0" for="perm_2_neutral" title="Neutral">/</label>
|
||||
|
||||
<input type="radio" class="btn-check" name="perm_2" id="perm_2_allow" value="allow">
|
||||
<label class="btn btn-outline-success border-0" for="perm_2_allow" title="Allow"><i class="fa-solid fa-check"></i></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="permission-item mb-3 p-2 rounded" style="background: var(--separator-soft);">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="pe-3">
|
||||
<div class="fw-bold" style="color: #ffffff; font-size: 0.9em;">Send Messages</div>
|
||||
<div style="font-size: 0.75em; color: #b5bac1;">Allows members to send messages in this channel.</div>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm perm-tri-state" data-perm-bit="2">
|
||||
<input type="radio" class="btn-check" name="perm_2" id="perm_2_deny" value="deny">
|
||||
<label class="btn btn-outline-danger border-0" for="perm_2_deny" title="Deny"><i class="fa-solid fa-xmark"></i></label>
|
||||
|
||||
<input type="radio" class="btn-check" name="perm_2" id="perm_2_neutral" value="neutral" checked>
|
||||
<label class="btn btn-outline-secondary border-0" for="perm_2_neutral" title="Neutral">/</label>
|
||||
|
||||
<input type="radio" class="btn-check" name="perm_2" id="perm_2_allow" value="allow">
|
||||
<label class="btn btn-outline-success border-0" for="perm_2_allow" title="Allow"><i class="fa-solid fa-check"></i></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="permission-item mb-3 p-2 rounded" style="background: var(--separator-soft);">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="pe-3">
|
||||
<div class="fw-bold" style="color: #ffffff; font-size: 0.9em;">Create Thread</div>
|
||||
<div style="font-size: 0.75em; color: #b5bac1;">Allows members to create new discussions.</div>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm perm-tri-state" data-perm-bit="64">
|
||||
<input type="radio" class="btn-check" name="perm_64" id="perm_64_deny" value="deny">
|
||||
<label class="btn btn-outline-danger border-0" for="perm_64_deny" title="Deny"><i class="fa-solid fa-xmark"></i></label>
|
||||
<input type="radio" class="btn-check" name="perm_64" id="perm_64_neutral" value="neutral" checked>
|
||||
<label class="btn btn-outline-secondary border-0" for="perm_64_neutral" title="Neutral">/</label>
|
||||
<input type="radio" class="btn-check" name="perm_64" id="perm_64_allow" value="allow">
|
||||
<label class="btn btn-outline-success border-0" for="perm_64_allow" title="Allow"><i class="fa-solid fa-check"></i></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="permission-item mb-3 p-2 rounded" style="background: var(--separator-soft);">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="pe-3">
|
||||
<div class="fw-bold" style="color: #ffffff; font-size: 0.9em;">Manage Tags</div>
|
||||
<div style="font-size: 0.75em; color: #b5bac1;">Allows adding/modifying forum tags.</div>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm perm-tri-state" data-perm-bit="128">
|
||||
<input type="radio" class="btn-check" name="perm_128" id="perm_128_deny" value="deny">
|
||||
<label class="btn btn-outline-danger border-0" for="perm_128_deny" title="Deny"><i class="fa-solid fa-xmark"></i></label>
|
||||
<input type="radio" class="btn-check" name="perm_128" id="perm_128_neutral" value="neutral" checked>
|
||||
<label class="btn btn-outline-secondary border-0" for="perm_128_neutral" title="Neutral">/</label>
|
||||
<input type="radio" class="btn-check" name="perm_128" id="perm_128_allow" value="allow">
|
||||
<label class="btn btn-outline-success border-0" for="perm_128_allow" title="Allow"><i class="fa-solid fa-check"></i></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="permission-item mb-3 p-2 rounded" style="background: var(--separator-soft);">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="pe-3">
|
||||
<div class="fw-bold" style="color: #ffffff; font-size: 0.9em;">Pin Threads</div>
|
||||
<div style="font-size: 0.75em; color: #b5bac1;">Allows pinning/unpinning threads.</div>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm perm-tri-state" data-perm-bit="256">
|
||||
<input type="radio" class="btn-check" name="perm_256" id="perm_256_deny" value="deny">
|
||||
<label class="btn btn-outline-danger border-0" for="perm_256_deny" title="Deny"><i class="fa-solid fa-xmark"></i></label>
|
||||
<input type="radio" class="btn-check" name="perm_256" id="perm_256_neutral" value="neutral" checked>
|
||||
<label class="btn btn-outline-secondary border-0" for="perm_256_neutral" title="Neutral">/</label>
|
||||
<input type="radio" class="btn-check" name="perm_256" id="perm_256_allow" value="allow">
|
||||
<label class="btn btn-outline-success border-0" for="perm_256_allow" title="Allow"><i class="fa-solid fa-check"></i></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="permission-item mb-3 p-2 rounded" style="background: var(--separator-soft);">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="pe-3">
|
||||
<div class="fw-bold" style="color: #ffffff; font-size: 0.9em;">Lock Threads</div>
|
||||
<div style="font-size: 0.75em; color: #b5bac1;">Allows locking/unlocking threads.</div>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm perm-tri-state" data-perm-bit="512">
|
||||
<input type="radio" class="btn-check" name="perm_512" id="perm_512_deny" value="deny">
|
||||
<label class="btn btn-outline-danger border-0" for="perm_512_deny" title="Deny"><i class="fa-solid fa-xmark"></i></label>
|
||||
<input type="radio" class="btn-check" name="perm_512" id="perm_512_neutral" value="neutral" checked>
|
||||
<label class="btn btn-outline-secondary border-0" for="perm_512_neutral" title="Neutral">/</label>
|
||||
<input type="radio" class="btn-check" name="perm_512" id="perm_512_allow" value="allow">
|
||||
<label class="btn btn-outline-success border-0" for="perm_512_allow" title="Allow"><i class="fa-solid fa-check"></i></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="permission-item mb-3 p-2 rounded" style="background: var(--separator-soft);">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="pe-3">
|
||||
<div class="fw-bold" style="color: #ffffff; font-size: 0.9em;">Send Messages in Threads</div>
|
||||
<div style="font-size: 0.75em; color: #b5bac1;">Allows posting in unlocked threads.</div>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm perm-tri-state" data-perm-bit="1024">
|
||||
<input type="radio" class="btn-check" name="perm_1024" id="perm_1024_deny" value="deny">
|
||||
<label class="btn btn-outline-danger border-0" for="perm_1024_deny" title="Deny"><i class="fa-solid fa-xmark"></i></label>
|
||||
<input type="radio" class="btn-check" name="perm_1024" id="perm_1024_neutral" value="neutral" checked>
|
||||
<label class="btn btn-outline-secondary border-0" for="perm_1024_neutral" title="Neutral">/</label>
|
||||
<input type="radio" class="btn-check" name="perm_1024" id="perm_1024_allow" value="allow">
|
||||
<label class="btn btn-outline-success border-0" for="perm_1024_allow" title="Allow"><i class="fa-solid fa-check"></i></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- More permissions can be added here -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
111
requests.log
111
requests.log
@ -807,3 +807,114 @@
|
||||
2026-02-19 12:41:48 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
|
||||
2026-02-19 12:41:52 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 12:41:56 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 12:43:11 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 12:43:25 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 12:43:45 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 12:44:28 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 12:44:41 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 12:52:27 - GET /?fl_project=38443 - POST: []
|
||||
2026-02-19 12:52:31 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 12:53:05 - GET /index.php - POST: []
|
||||
2026-02-19 12:53:07 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 12:53:11 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 12:53:22 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 12:53:31 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 12:53:37 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 12:53:43 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 12:53:46 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 12:53:51 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 12:53:53 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
|
||||
2026-02-19 12:54:03 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
|
||||
2026-02-19 12:54:07 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
|
||||
2026-02-19 12:54:10 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 12:54:12 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 12:54:22 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 12:54:23 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 12:54:30 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 12:54:32 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 12:54:35 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 12:54:45 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 12:54:51 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 12:54:56 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 12:55:11 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 12:55:21 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 12:55:23 - GET /index.php?server_id=1&channel_id=13&status=unresolved - POST: []
|
||||
2026-02-19 12:55:25 - GET /index.php?server_id=1&channel_id=13&status=resolved - POST: []
|
||||
2026-02-19 12:55:27 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 12:55:44 - GET /index.php?server_id=1&channel_id=13&thread_id=2&status=all - POST: []
|
||||
2026-02-19 12:56:08 - GET /index.php?server_id=1&channel_id=13&thread_id=2&status=all - POST: []
|
||||
2026-02-19 12:56:11 - GET /index.php?server_id=1&channel_id=13&thread_id=2&status=all - POST: []
|
||||
2026-02-19 12:56:13 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 12:56:19 - GET /index.php?server_id=1&channel_id=13&thread_id=2&status=all - POST: []
|
||||
2026-02-19 12:56:39 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 12:56:41 - GET /index.php?server_id=1&channel_id=13&thread_id=3&status=all - POST: []
|
||||
2026-02-19 12:56:49 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 12:57:00 - GET /index.php?server_id=1&channel_id=13&thread_id=3&status=all - POST: []
|
||||
2026-02-19 12:57:10 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 12:57:20 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 13:01:56 - GET /?fl_project=38443 - POST: []
|
||||
2026-02-19 13:03:44 - GET /?fl_project=38443 - POST: []
|
||||
2026-02-19 13:04:14 - GET /?fl_project=38443 - POST: []
|
||||
2026-02-19 13:09:42 - GET /?fl_project=38443 - POST: []
|
||||
2026-02-19 13:09:49 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 13:09:53 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:10:00 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 13:10:09 - GET /index.php?server_id=1&channel_id=13&thread_id=3&status=all - POST: []
|
||||
2026-02-19 13:10:12 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 13:10:17 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:10:19 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 13:10:34 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 13:10:46 - GET /index.php?server_id=1&channel_id=21 - POST: []
|
||||
2026-02-19 13:10:54 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 13:11:06 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 13:11:18 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 13:11:37 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 13:11:49 - GET /index.php?server_id=1&channel_id=13&status=all - POST: []
|
||||
2026-02-19 13:11:51 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:11:51 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 13:11:54 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:11:57 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 13:11:59 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:12:03 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
|
||||
2026-02-19 13:12:05 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:12:07 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 13:12:23 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 13:12:26 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:12:28 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
|
||||
2026-02-19 13:12:31 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:12:32 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 13:12:34 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:12:44 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:12:45 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
|
||||
2026-02-19 13:12:48 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:12:49 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 13:12:54 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 13:12:58 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 13:13:01 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:13:03 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
|
||||
2026-02-19 13:13:05 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
|
||||
2026-02-19 13:13:07 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:13:12 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
|
||||
2026-02-19 13:13:14 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:13:21 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:13:30 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:13:45 - GET /index.php?server_id=1&channel_id=13&thread_id=5 - POST: []
|
||||
2026-02-19 13:13:48 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:14:34 - GET /index.php?server_id=1&channel_id=17 - POST: []
|
||||
2026-02-19 13:14:36 - GET /index.php?server_id=1&channel_id=17 - POST: []
|
||||
2026-02-19 13:14:38 - GET /index.php?server_id=1&channel_id=17 - POST: []
|
||||
2026-02-19 13:15:06 - GET /index.php?server_id=1&channel_id=17 - POST: []
|
||||
2026-02-19 13:15:08 - GET /index.php?server_id=1&channel_id=1 - POST: []
|
||||
2026-02-19 13:15:12 - GET /index.php?server_id=1&channel_id=1 - POST: []
|
||||
2026-02-19 13:15:30 - GET /index.php - POST: []
|
||||
2026-02-19 13:15:33 - GET /index.php - POST: []
|
||||
2026-02-19 13:15:34 - GET /index.php - POST: []
|
||||
{"date":"2026-02-19 13:16:18","method":"POST","post":{"avatar_url":"","display_name":"swefpifh \u1d47\u02b0\u1da0\u02b3","theme":"dark","voice_input_device":"OPTIyYzx3bNI0gtW62vaTCb7SxzY5rNnwOw5G42w36M=","voice_output_device":"znHy1zh6U7iZkBs7ovKSXvb3r4k0jk0DBbg\/TtaWmwk=","voice_input_volume":"1","voice_output_volume":"1","voice_echo_cancellation":"1","voice_noise_suppression":"1","voice_mode":"vox","voice_ptt_key":"v","voice_vox_threshold":"0.11","dnd_mode":"1","sound_notifications":"1"},"session":{"user_id":2},"user_id":2,"db_success":true}
|
||||
{"date":"2026-02-19 13:17:25","method":"POST","post":{"avatar_url":"","display_name":"swefheim","theme":"light","voice_input_device":"default","voice_output_device":"default","voice_input_volume":"1","voice_output_volume":"1","voice_echo_cancellation":"1","voice_noise_suppression":"1","voice_mode":"ptt","voice_ptt_key":"v","voice_vox_threshold":"0.06","dnd_mode":"0","sound_notifications":"0"},"session":{"user_id":3},"user_id":3,"db_success":true}
|
||||
2026-02-19 13:19:38 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:19:56 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 13:19:59 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
|
||||
2026-02-19 13:20:01 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
2026-02-19 13:20:10 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 13:20:12 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
|
||||
2026-02-19 13:20:13 - GET /index.php?server_id=1&channel_id=13 - POST: []
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user