Yrityskohtaiset käyttäjäroolit + IP-rajoitus bugikorjaus

- Lisää role-sarake user_companies-tauluun (admin/user per yritys)
- Migraatio: kopioi vanhat admin-roolit user_companies-tauluun, muuta globaali admin → user
- Päivitä dbSaveUser/dbLoadUsers/dbGetUser/dbGetUserByUsername käsittelemään company_roles
- isCompanyAdmin() tarkistaa nyt yrityskohtaisen roolin (session company_role)
- requireAdmin() käyttää isCompanyAdmin():ia
- requireCompany() tarkistaa IP-rajoituksen (siirretty login/check_auth:sta)
- Login ei enää estä kirjautumista IP:n perusteella, vaan merkitsee ip_blocked
- check_auth näyttää kaikki yritykset, IP-estetyt merkitään ip_blocked:lla
- company_switch palauttaa company_role ja päivittää session
- Frontend: käyttäjälomakkeessa yrityskohtaiset rooli-dropdownit (admin/käyttäjä)
- Frontend: yritysvaihto päivittää admin-näkyvyyden company_rolen mukaan
- Frontend: yritysvalitsimessa IP-estetyt yritykset näkyvät "(IP-rajoitus)" -tekstillä

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 20:45:18 +02:00
parent 4c128f5c71
commit 68c9075676
4 changed files with 194 additions and 89 deletions

34
db.php
View File

@@ -591,6 +591,7 @@ function initDatabase(): void {
"ALTER TABLE mailboxes ADD COLUMN auto_reply_body TEXT AFTER auto_reply_enabled",
"ALTER TABLE companies ADD COLUMN allowed_ips TEXT DEFAULT '' AFTER enabled_modules",
"ALTER TABLE todos ADD COLUMN category VARCHAR(30) DEFAULT '' AFTER priority",
"ALTER TABLE user_companies ADD COLUMN role VARCHAR(20) DEFAULT 'user' AFTER company_id",
];
foreach ($alters as $sql) {
try { $db->query($sql); } catch (\Throwable $e) { /* sarake on jo olemassa / jo ajettu */ }
@@ -604,6 +605,17 @@ function initDatabase(): void {
$db->query("UPDATE users SET role = 'superadmin' WHERE role = 'admin'");
}
} catch (\Throwable $e) { /* ohitetaan */ }
// Migraatio: kopioi admin-käyttäjien rooli user_companies-tauluun
// (kun role-sarake lisätty, olemassa olevat admin-käyttäjät saavat admin-roolin kaikkiin yrityksiinsä)
try {
$db->query("UPDATE user_companies uc JOIN users u ON u.id = uc.user_id SET uc.role = 'admin' WHERE u.role = 'admin' AND uc.role = 'user'");
} catch (\Throwable $e) { /* ohitetaan */ }
// Migraatio: muuta globaali 'admin' → 'user' (admin on nyt yrityskohtainen user_companies.role)
try {
$db->query("UPDATE users SET role = 'user' WHERE role = 'admin'");
} catch (\Throwable $e) { /* ohitetaan */ }
}
// ==================== YRITYKSET ====================
@@ -730,6 +742,12 @@ function dbLoadUsers(): array {
foreach ($users as &$u) {
$u['companies'] = _dbFetchColumn("SELECT company_id FROM user_companies WHERE user_id = ?", [$u['id']]);
// Yrityskohtaiset roolit
$roleRows = _dbFetchAll("SELECT company_id, role FROM user_companies WHERE user_id = ?", [$u['id']]);
$companyRoles = [];
foreach ($roleRows as $rr) { $companyRoles[$rr['company_id']] = $rr['role'] ?? 'user'; }
$u['company_roles'] = $companyRoles;
$sigRows = _dbFetchAll("SELECT mailbox_id, signature FROM user_signatures WHERE user_id = ?", [$u['id']]);
$sigs = [];
foreach ($sigRows as $row) {
@@ -746,6 +764,11 @@ function dbGetUser(string $id): ?array {
$u['companies'] = _dbFetchColumn("SELECT company_id FROM user_companies WHERE user_id = ?", [$id]);
$roleRows = _dbFetchAll("SELECT company_id, role FROM user_companies WHERE user_id = ?", [$id]);
$companyRoles = [];
foreach ($roleRows as $rr) { $companyRoles[$rr['company_id']] = $rr['role'] ?? 'user'; }
$u['company_roles'] = $companyRoles;
$sigRows = _dbFetchAll("SELECT mailbox_id, signature FROM user_signatures WHERE user_id = ?", [$id]);
$sigs = [];
foreach ($sigRows as $row) {
@@ -762,6 +785,11 @@ function dbGetUserByUsername(string $username): ?array {
$u['companies'] = _dbFetchColumn("SELECT company_id FROM user_companies WHERE user_id = ?", [$u['id']]);
$roleRows = _dbFetchAll("SELECT company_id, role FROM user_companies WHERE user_id = ?", [$u['id']]);
$companyRoles = [];
foreach ($roleRows as $rr) { $companyRoles[$rr['company_id']] = $rr['role'] ?? 'user'; }
$u['company_roles'] = $companyRoles;
$sigRows = _dbFetchAll("SELECT mailbox_id, signature FROM user_signatures WHERE user_id = ?", [$u['id']]);
$sigs = [];
foreach ($sigRows as $row) {
@@ -792,11 +820,13 @@ function dbSaveUser(array $user): void {
'luotu' => $user['luotu'] ?? date('Y-m-d H:i:s'),
]);
// Yritykset
// Yritykset + yrityskohtaiset roolit
_dbExecute("DELETE FROM user_companies WHERE user_id = ?", [$user['id']]);
if (!empty($user['companies'])) {
$companyRoles = $user['company_roles'] ?? [];
foreach ($user['companies'] as $cid) {
_dbExecute("INSERT IGNORE INTO user_companies (user_id, company_id) VALUES (?, ?)", [$user['id'], $cid]);
$role = $companyRoles[$cid] ?? 'user';
_dbExecute("INSERT IGNORE INTO user_companies (user_id, company_id, role) VALUES (?, ?, ?)", [$user['id'], $cid, $role]);
}
}