200 lines
5.3 KiB
JavaScript
200 lines
5.3 KiB
JavaScript
// SupportBot | Emerald Services
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const { fullPermissions, normalizePermissions } = require("./DashboardPermissions.js");
|
|
|
|
const GROUPS_FILE = path.join(__dirname, "../Data/dashboard-groups.json");
|
|
|
|
const DEFAULT_GROUPS = [
|
|
{
|
|
id: "owner",
|
|
name: "Owner",
|
|
description: "Full system owner access to all features and configs",
|
|
color: "#10B981", // Emerald Green
|
|
discordRoleId: null,
|
|
isSystem: true,
|
|
permissions: fullPermissions(),
|
|
},
|
|
{
|
|
id: "admin",
|
|
name: "Admin",
|
|
description: "Full administrative access including user and group management",
|
|
color: "#3B82F6", // Blue
|
|
discordRoleId: null,
|
|
isSystem: true,
|
|
permissions: fullPermissions(),
|
|
},
|
|
{
|
|
id: "support",
|
|
name: "Support Staff",
|
|
description: "Access to Overview, Live Tickets, and Transcripts",
|
|
color: "#8B5CF6", // Purple
|
|
discordRoleId: null,
|
|
isSystem: false,
|
|
permissions: {
|
|
overview: true,
|
|
tickets: true,
|
|
logs: false,
|
|
transcripts: true,
|
|
settings: { view: false, update: false },
|
|
configs: {
|
|
supportbot: { view: false, edit: false },
|
|
"ticket-panel": { view: false, edit: false },
|
|
commands: { view: false, edit: false },
|
|
messages: { view: false, edit: false },
|
|
"supportbot-ai": { view: false, edit: false },
|
|
api: { view: false, edit: false },
|
|
},
|
|
users: { view: false, manage: false },
|
|
},
|
|
},
|
|
{
|
|
id: "viewer",
|
|
name: "Viewer",
|
|
description: "Read-only access to dashboard and logs",
|
|
color: "#6B7280", // Gray
|
|
discordRoleId: null,
|
|
isSystem: false,
|
|
permissions: {
|
|
overview: true,
|
|
tickets: true,
|
|
logs: true,
|
|
transcripts: true,
|
|
settings: { view: true, update: false },
|
|
configs: {
|
|
supportbot: { view: true, edit: false },
|
|
"ticket-panel": { view: true, edit: false },
|
|
commands: { view: true, edit: false },
|
|
messages: { view: true, edit: false },
|
|
"supportbot-ai": { view: true, edit: false },
|
|
api: { view: true, edit: false },
|
|
},
|
|
users: { view: false, manage: false },
|
|
},
|
|
},
|
|
];
|
|
|
|
function ensureStorage() {
|
|
const dir = path.dirname(GROUPS_FILE);
|
|
if (!fs.existsSync(dir)) {
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
}
|
|
|
|
if (!fs.existsSync(GROUPS_FILE)) {
|
|
const initialData = {
|
|
version: 1,
|
|
groups: DEFAULT_GROUPS,
|
|
};
|
|
fs.writeFileSync(GROUPS_FILE, JSON.stringify(initialData, null, 2), "utf8");
|
|
}
|
|
}
|
|
|
|
function loadStore() {
|
|
ensureStorage();
|
|
try {
|
|
const raw = fs.readFileSync(GROUPS_FILE, "utf8");
|
|
const parsed = JSON.parse(raw);
|
|
if (parsed && Array.isArray(parsed.groups)) {
|
|
return parsed.groups;
|
|
}
|
|
} catch (err) {
|
|
console.error("[GroupStore] Error loading groups file:", err.message);
|
|
}
|
|
return DEFAULT_GROUPS;
|
|
}
|
|
|
|
function saveStore(groups) {
|
|
ensureStorage();
|
|
const payload = {
|
|
version: 1,
|
|
groups,
|
|
updatedAt: Date.now(),
|
|
};
|
|
fs.writeFileSync(GROUPS_FILE, JSON.stringify(payload, null, 2), "utf8");
|
|
}
|
|
|
|
function listGroups() {
|
|
return loadStore();
|
|
}
|
|
|
|
function getGroup(id) {
|
|
const groups = loadStore();
|
|
return groups.find((g) => g.id === id) || null;
|
|
}
|
|
|
|
function createGroup(payload = {}) {
|
|
const groups = loadStore();
|
|
const name = (payload.name || "New Group").trim();
|
|
const slug = name.toLowerCase().replace(/[^a-z0-9_-]+/g, "_");
|
|
let newId = slug || `group_${Date.now()}`;
|
|
|
|
let counter = 1;
|
|
while (groups.some((g) => g.id === newId)) {
|
|
newId = `${slug}_${counter++}`;
|
|
}
|
|
|
|
const newGroup = {
|
|
id: newId,
|
|
name,
|
|
description: (payload.description || "").trim(),
|
|
color: payload.color || "#10B981",
|
|
discordRoleId: payload.discordRoleId ? String(payload.discordRoleId).trim() : null,
|
|
isSystem: false,
|
|
permissions: normalizePermissions(payload.permissions),
|
|
createdAt: Date.now(),
|
|
updatedAt: Date.now(),
|
|
};
|
|
|
|
groups.push(newGroup);
|
|
saveStore(groups);
|
|
return newGroup;
|
|
}
|
|
|
|
function updateGroup(id, payload = {}) {
|
|
const groups = loadStore();
|
|
const index = groups.findIndex((g) => g.id === id);
|
|
if (index === -1) {
|
|
throw new Error(`Group with ID "${id}" not found.`);
|
|
}
|
|
|
|
const existing = groups[index];
|
|
const updatedGroup = {
|
|
...existing,
|
|
name: payload.name !== undefined ? payload.name.trim() : existing.name,
|
|
description: payload.description !== undefined ? payload.description.trim() : existing.description,
|
|
color: payload.color || existing.color,
|
|
discordRoleId: payload.discordRoleId !== undefined ? (payload.discordRoleId ? String(payload.discordRoleId).trim() : null) : existing.discordRoleId,
|
|
permissions: payload.permissions ? normalizePermissions(payload.permissions) : existing.permissions,
|
|
updatedAt: Date.now(),
|
|
};
|
|
|
|
groups[index] = updatedGroup;
|
|
saveStore(groups);
|
|
return updatedGroup;
|
|
}
|
|
|
|
function deleteGroup(id) {
|
|
const groups = loadStore();
|
|
const group = groups.find((g) => g.id === id);
|
|
if (!group) {
|
|
throw new Error(`Group with ID "${id}" not found.`);
|
|
}
|
|
|
|
if (group.isSystem) {
|
|
throw new Error(`System group "${group.name}" cannot be deleted.`);
|
|
}
|
|
|
|
const filtered = groups.filter((g) => g.id !== id);
|
|
saveStore(filtered);
|
|
return true;
|
|
}
|
|
|
|
module.exports = {
|
|
listGroups,
|
|
getGroup,
|
|
createGroup,
|
|
updateGroup,
|
|
deleteGroup,
|
|
DEFAULT_GROUPS,
|
|
};
|