feat: admin näkee oman yrityksen käyttäjät

- Käyttäjät-nappi näkyy nyt myös admin-roolille
- Admin näkee/hallitsee vain oman yrityksensä käyttäjiä
- Admin voi luoda admin/user-rooleja (ei superadmin)
- Admin ei voi poistaa/muokata superadmineja
- Superadmin-vaihtoehto piilotettu rooli-dropdownista adminilta
- Yritysoikeudet-osio piilotettu adminilta (lisätään automaattisesti)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 20:26:53 +02:00
parent df42fbc917
commit b7e50042b5
2 changed files with 51 additions and 8 deletions

51
api.php
View File

@@ -1068,8 +1068,16 @@ switch ($action) {
// ---------- USERS ---------- // ---------- USERS ----------
case 'users': case 'users':
requireSuperAdmin(); requireAdmin();
$users = dbLoadUsers(); $users = dbLoadUsers();
// Admin näkee vain oman yrityksensä käyttäjät, superadmin näkee kaikki
$role = $_SESSION['role'] ?? '';
$companyId = $_SESSION['company_id'] ?? '';
if ($role !== 'superadmin') {
$users = array_filter($users, function($u) use ($companyId) {
return in_array($companyId, $u['companies'] ?? []);
});
}
$safe = array_map(function($u) { $safe = array_map(function($u) {
unset($u['password_hash']); unset($u['password_hash']);
return $u; return $u;
@@ -1078,14 +1086,15 @@ switch ($action) {
break; break;
case 'user_create': case 'user_create':
requireSuperAdmin(); requireAdmin();
if ($method !== 'POST') break; if ($method !== 'POST') break;
$input = json_decode(file_get_contents('php://input'), true); $input = json_decode(file_get_contents('php://input'), true);
$username = trim($input['username'] ?? ''); $username = trim($input['username'] ?? '');
$password = $input['password'] ?? ''; $password = $input['password'] ?? '';
$nimi = trim($input['nimi'] ?? ''); $nimi = trim($input['nimi'] ?? '');
$email = trim($input['email'] ?? ''); $email = trim($input['email'] ?? '');
$validRoles = ['superadmin', 'admin', 'user']; $isSA = ($_SESSION['role'] ?? '') === 'superadmin';
$validRoles = $isSA ? ['superadmin', 'admin', 'user'] : ['admin', 'user'];
$role = in_array($input['role'] ?? '', $validRoles) ? $input['role'] : 'user'; $role = in_array($input['role'] ?? '', $validRoles) ? $input['role'] : 'user';
if (empty($username) || empty($password)) { if (empty($username) || empty($password)) {
http_response_code(400); http_response_code(400);
@@ -1104,6 +1113,11 @@ switch ($action) {
break; break;
} }
$companies = $input['companies'] ?? []; $companies = $input['companies'] ?? [];
// Admin voi lisätä käyttäjiä vain omaan yritykseensä
if (!$isSA) {
$myCompanyId = $_SESSION['company_id'] ?? '';
$companies = [$myCompanyId];
}
// Validoi yritys-IDt // Validoi yritys-IDt
$allCompanies = dbLoadCompanies(); $allCompanies = dbLoadCompanies();
$validIds = array_column($allCompanies, 'id'); $validIds = array_column($allCompanies, 'id');
@@ -1133,7 +1147,7 @@ switch ($action) {
break; break;
case 'user_update': case 'user_update':
requireSuperAdmin(); requireAdmin();
if ($method !== 'POST') break; if ($method !== 'POST') break;
$input = json_decode(file_get_contents('php://input'), true); $input = json_decode(file_get_contents('php://input'), true);
$id = $input['id'] ?? ''; $id = $input['id'] ?? '';
@@ -1143,11 +1157,24 @@ switch ($action) {
echo json_encode(['error' => 'Käyttäjää ei löydy']); echo json_encode(['error' => 'Käyttäjää ei löydy']);
break; break;
} }
$isSA = ($_SESSION['role'] ?? '') === 'superadmin';
$myCompanyId = $_SESSION['company_id'] ?? '';
// Admin voi muokata vain oman yrityksensä käyttäjiä
if (!$isSA && !in_array($myCompanyId, $u['companies'] ?? [])) {
http_response_code(403);
echo json_encode(['error' => 'Ei oikeutta muokata tätä käyttäjää']);
break;
}
if (isset($input['nimi'])) $u['nimi'] = trim($input['nimi']); if (isset($input['nimi'])) $u['nimi'] = trim($input['nimi']);
if (isset($input['email'])) $u['email'] = trim($input['email']); if (isset($input['email'])) $u['email'] = trim($input['email']);
if (isset($input['role'])) { if (isset($input['role'])) {
$validRoles = ['superadmin', 'admin', 'user']; $validRoles = $isSA ? ['superadmin', 'admin', 'user'] : ['admin', 'user'];
$u['role'] = in_array($input['role'], $validRoles) ? $input['role'] : 'user'; // Admin ei voi muuttaa superadminia
if (!$isSA && ($u['role'] === 'superadmin')) {
// Älä muuta roolia
} else {
$u['role'] = in_array($input['role'], $validRoles) ? $input['role'] : 'user';
}
} }
if (isset($input['companies'])) { if (isset($input['companies'])) {
$allCompanies = dbLoadCompanies(); $allCompanies = dbLoadCompanies();
@@ -1183,7 +1210,7 @@ switch ($action) {
break; break;
case 'user_delete': case 'user_delete':
requireSuperAdmin(); requireAdmin();
if ($method !== 'POST') break; if ($method !== 'POST') break;
$input = json_decode(file_get_contents('php://input'), true); $input = json_decode(file_get_contents('php://input'), true);
$id = $input['id'] ?? ''; $id = $input['id'] ?? '';
@@ -1193,6 +1220,16 @@ switch ($action) {
break; break;
} }
$deleted = dbGetUser($id); $deleted = dbGetUser($id);
$isSA = ($_SESSION['role'] ?? '') === 'superadmin';
$myCompanyId = $_SESSION['company_id'] ?? '';
// Admin ei voi poistaa superadmineja eikä toisen yrityksen käyttäjiä
if (!$isSA) {
if ($deleted && ($deleted['role'] === 'superadmin' || !in_array($myCompanyId, $deleted['companies'] ?? []))) {
http_response_code(403);
echo json_encode(['error' => 'Ei oikeutta poistaa tätä käyttäjää']);
break;
}
}
dbDeleteUser($id); dbDeleteUser($id);
$companyId = $_SESSION['company_id'] ?? ''; $companyId = $_SESSION['company_id'] ?? '';
if ($deleted) dbAddLog($companyId, currentUser(), 'user_delete', '', '', "Poisti käyttäjän: {$deleted['username']}"); if ($deleted) dbAddLog($companyId, currentUser(), 'user_delete', '', '', "Poisti käyttäjän: {$deleted['username']}");

View File

@@ -187,7 +187,7 @@ async function showDashboard() {
const isSuperAdmin = currentUser.role === 'superadmin'; const isSuperAdmin = currentUser.role === 'superadmin';
const isAdmin = currentUser.role === 'admin' || isSuperAdmin; const isAdmin = currentUser.role === 'admin' || isSuperAdmin;
// Näytä admin-toiminnot roolin mukaan // Näytä admin-toiminnot roolin mukaan
document.getElementById('btn-users').style.display = isSuperAdmin ? '' : 'none'; document.getElementById('btn-users').style.display = isAdmin ? '' : 'none';
document.getElementById('tab-settings').style.display = isAdmin ? '' : 'none'; document.getElementById('tab-settings').style.display = isAdmin ? '' : 'none';
document.getElementById('btn-companies').style.display = isAdmin ? '' : 'none'; document.getElementById('btn-companies').style.display = isAdmin ? '' : 'none';
// Yritysvalitsin // Yritysvalitsin
@@ -1012,6 +1012,12 @@ function openUserForm(user = null) {
document.getElementById('user-form-password').value = ''; document.getElementById('user-form-password').value = '';
document.getElementById('user-pw-hint').textContent = user ? '(jätä tyhjäksi jos ei muuteta)' : '*'; document.getElementById('user-pw-hint').textContent = user ? '(jätä tyhjäksi jos ei muuteta)' : '*';
document.getElementById('user-form-role').value = user ? user.role : 'user'; document.getElementById('user-form-role').value = user ? user.role : 'user';
// Piilota superadmin-vaihtoehto ellei ole superadmin
const saOption = document.querySelector('#user-form-role option[value="superadmin"]');
if (saOption) saOption.style.display = currentUser?.role === 'superadmin' ? '' : 'none';
// Piilota yrityscheckboxit adminilta (näkee vain oman yrityksen)
const compSection = document.getElementById('user-company-checkboxes')?.closest('.form-group');
if (compSection) compSection.style.display = currentUser?.role === 'superadmin' ? '' : 'none';
// Yrityscheckboxit // Yrityscheckboxit
const allComps = availableCompanies.length > 0 ? availableCompanies : []; const allComps = availableCompanies.length > 0 ? availableCompanies : [];
const userComps = user ? (user.companies || []) : []; const userComps = user ? (user.companies || []) : [];