feat: moduulijärjestelmä + käyttäjäroolit + suhteellinen aika
- Moduulijärjestelmä: yrityskohtaiset tabit (customers, support, leads, archive, changelog, settings) valittavissa checkboxeina yrityksen asetuksissa - Käyttäjäroolit: superadmin (pääkäyttäjä), admin (yritysadmin), user (käyttäjä) - Superadmin: kaikki oikeudet kuten ennen - Yritysadmin: muokkaa oman yrityksen asetuksia, moduuleita, postilaatikoita - Käyttäjä: peruskäyttö ilman hallintaoikeuksia - Päivitetty-kenttä näyttää suhteellista aikaa (15min sitten, 2h sitten, 3pv sitten) - DB: enabled_modules sarake companies-tauluun, role ENUM laajennettu - Automaattinen migraatio: vanhat admin → superadmin Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
74
db.php
74
db.php
@@ -137,7 +137,7 @@ function initDatabase(): void {
|
||||
username VARCHAR(100) NOT NULL UNIQUE,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
nimi VARCHAR(255) NOT NULL,
|
||||
role ENUM('admin','user') DEFAULT 'user',
|
||||
role ENUM('superadmin','admin','user') DEFAULT 'user',
|
||||
email VARCHAR(255) DEFAULT '',
|
||||
luotu DATETIME
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
|
||||
@@ -375,10 +375,21 @@ function initDatabase(): void {
|
||||
"ALTER TABLE tickets ADD COLUMN cc TEXT DEFAULT '' AFTER mailbox_id",
|
||||
"ALTER TABLE tickets ADD COLUMN priority VARCHAR(20) DEFAULT 'normaali' AFTER cc",
|
||||
"ALTER TABLE customers ADD COLUMN priority_emails TEXT DEFAULT '' AFTER lisatiedot",
|
||||
"ALTER TABLE companies ADD COLUMN enabled_modules TEXT DEFAULT '' AFTER cors_origins",
|
||||
"ALTER TABLE users MODIFY COLUMN role ENUM('superadmin','admin','user') DEFAULT 'user'",
|
||||
];
|
||||
foreach ($alters as $sql) {
|
||||
try { $db->query($sql); } catch (\Throwable $e) { /* sarake on jo olemassa */ }
|
||||
try { $db->query($sql); } catch (\Throwable $e) { /* sarake on jo olemassa / jo ajettu */ }
|
||||
}
|
||||
// Kertaluontoinen migraatio: päivitä vanhat admin-käyttäjät superadminiksi
|
||||
// (vain jos yhtään superadminia ei vielä ole)
|
||||
try {
|
||||
$result = $db->query("SELECT COUNT(*) AS cnt FROM users WHERE role = 'superadmin'");
|
||||
$row = $result->fetch_assoc();
|
||||
if ((int)($row['cnt'] ?? 0) === 0) {
|
||||
$db->query("UPDATE users SET role = 'superadmin' WHERE role = 'admin'");
|
||||
}
|
||||
} catch (\Throwable $e) { /* ohitetaan */ }
|
||||
}
|
||||
|
||||
// ==================== YRITYKSET ====================
|
||||
@@ -389,6 +400,9 @@ function dbLoadCompanies(): array {
|
||||
foreach ($companies as &$c) {
|
||||
$c['domains'] = _dbFetchColumn("SELECT domain FROM company_domains WHERE company_id = ?", [$c['id']]);
|
||||
$c['aktiivinen'] = (bool)$c['aktiivinen'];
|
||||
// enabled_modules: JSON-array tai tyhjä (= kaikki päällä)
|
||||
$raw = $c['enabled_modules'] ?? '';
|
||||
$c['enabled_modules'] = $raw ? (json_decode($raw, true) ?: []) : [];
|
||||
}
|
||||
return $companies;
|
||||
}
|
||||
@@ -397,23 +411,27 @@ function dbSaveCompany(array $company): void {
|
||||
$db = getDb();
|
||||
$db->begin_transaction();
|
||||
try {
|
||||
$enabledModules = $company['enabled_modules'] ?? [];
|
||||
$enabledModulesJson = is_array($enabledModules) ? json_encode($enabledModules) : ($enabledModules ?: '');
|
||||
_dbExecute("
|
||||
INSERT INTO companies (id, nimi, luotu, aktiivinen, primary_color, subtitle, logo_file, api_key, cors_origins)
|
||||
VALUES (:id, :nimi, :luotu, :aktiivinen, :primary_color, :subtitle, :logo_file, :api_key, :cors_origins)
|
||||
INSERT INTO companies (id, nimi, luotu, aktiivinen, primary_color, subtitle, logo_file, api_key, cors_origins, enabled_modules)
|
||||
VALUES (:id, :nimi, :luotu, :aktiivinen, :primary_color, :subtitle, :logo_file, :api_key, :cors_origins, :enabled_modules)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
nimi = VALUES(nimi), aktiivinen = VALUES(aktiivinen),
|
||||
primary_color = VALUES(primary_color), subtitle = VALUES(subtitle),
|
||||
logo_file = VALUES(logo_file), api_key = VALUES(api_key), cors_origins = VALUES(cors_origins)
|
||||
logo_file = VALUES(logo_file), api_key = VALUES(api_key), cors_origins = VALUES(cors_origins),
|
||||
enabled_modules = VALUES(enabled_modules)
|
||||
", [
|
||||
'id' => $company['id'],
|
||||
'nimi' => $company['nimi'],
|
||||
'luotu' => $company['luotu'] ?? date('Y-m-d H:i:s'),
|
||||
'aktiivinen' => $company['aktiivinen'] ?? true,
|
||||
'primary_color' => $company['primary_color'] ?? '#0f3460',
|
||||
'subtitle' => $company['subtitle'] ?? '',
|
||||
'logo_file' => $company['logo_file'] ?? '',
|
||||
'api_key' => $company['api_key'] ?? '',
|
||||
'cors_origins' => $company['cors_origins'] ?? '',
|
||||
'id' => $company['id'],
|
||||
'nimi' => $company['nimi'],
|
||||
'luotu' => $company['luotu'] ?? date('Y-m-d H:i:s'),
|
||||
'aktiivinen' => $company['aktiivinen'] ?? true,
|
||||
'primary_color' => $company['primary_color'] ?? '#0f3460',
|
||||
'subtitle' => $company['subtitle'] ?? '',
|
||||
'logo_file' => $company['logo_file'] ?? '',
|
||||
'api_key' => $company['api_key'] ?? '',
|
||||
'cors_origins' => $company['cors_origins'] ?? '',
|
||||
'enabled_modules' => $enabledModulesJson,
|
||||
]);
|
||||
|
||||
// Päivitä domainit
|
||||
@@ -451,23 +469,27 @@ function dbGetBranding(string $host): array {
|
||||
$logoUrl = !empty($company['logo_file'])
|
||||
? "api.php?action=company_logo&company_id=" . urlencode($company['id'])
|
||||
: '';
|
||||
$rawModules = $company['enabled_modules'] ?? '';
|
||||
$enabledModules = $rawModules ? (json_decode($rawModules, true) ?: []) : [];
|
||||
return [
|
||||
'found' => true,
|
||||
'company_id' => $company['id'],
|
||||
'nimi' => $company['nimi'],
|
||||
'primary_color' => $company['primary_color'] ?? '#0f3460',
|
||||
'subtitle' => $company['subtitle'] ?? '',
|
||||
'logo_url' => $logoUrl,
|
||||
'found' => true,
|
||||
'company_id' => $company['id'],
|
||||
'nimi' => $company['nimi'],
|
||||
'primary_color' => $company['primary_color'] ?? '#0f3460',
|
||||
'subtitle' => $company['subtitle'] ?? '',
|
||||
'logo_url' => $logoUrl,
|
||||
'enabled_modules' => $enabledModules,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'found' => false,
|
||||
'company_id' => '',
|
||||
'nimi' => 'Noxus Intra',
|
||||
'primary_color' => '#0f3460',
|
||||
'subtitle' => 'Hallintapaneeli',
|
||||
'logo_url' => '',
|
||||
'found' => false,
|
||||
'company_id' => '',
|
||||
'nimi' => 'Noxus Intra',
|
||||
'primary_color' => '#0f3460',
|
||||
'subtitle' => 'Hallintapaneeli',
|
||||
'logo_url' => '',
|
||||
'enabled_modules' => [],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user