Security: defense-in-depth company isolation for all operations
Critical fixes: - company_logo_upload: validate user has access to target company - All delete functions (db.php): accept optional company_id parameter for defense-in-depth filtering (customers, devices, ipam, guides, leads, tickets, archives, mailboxes, rules, templates, todos) - All API delete calls now pass company_id to db layer - ticket_bulk_delete: per-ticket company_id filtering - todo_comment/time/subtask operations: verify todo belongs to company - dbGetMailbox: optional company_id scoping, used in smtp_test - requireCompanyOrParam: no longer mutates session permanently - Fix _dbFetch typo in zammad_attachment (was runtime error) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
93
api.php
93
api.php
@@ -122,16 +122,19 @@ function requireCompany(): string {
|
|||||||
|
|
||||||
// Kuten requireCompany(), mutta sallii company_id:n overriden GET-parametrista
|
// Kuten requireCompany(), mutta sallii company_id:n overriden GET-parametrista
|
||||||
// Käytetään tiketti-endpointeissa jotta toisen yrityksen tikettejä voi avata
|
// Käytetään tiketti-endpointeissa jotta toisen yrityksen tikettejä voi avata
|
||||||
|
// EI muuta sessiota pysyvästi — palauttaa vain company_id:n
|
||||||
function requireCompanyOrParam(): string {
|
function requireCompanyOrParam(): string {
|
||||||
$paramCompany = $_GET['company_id'] ?? '';
|
$paramCompany = $_GET['company_id'] ?? '';
|
||||||
if (!empty($paramCompany)) {
|
if (!empty($paramCompany)) {
|
||||||
$userCompanies = $_SESSION['companies'] ?? [];
|
$userCompanies = $_SESSION['companies'] ?? [];
|
||||||
if (!in_array($paramCompany, $userCompanies)) {
|
$isSuperadmin = ($_SESSION['role'] ?? '') === 'superadmin';
|
||||||
|
if (!$isSuperadmin && !in_array($paramCompany, $userCompanies)) {
|
||||||
http_response_code(403);
|
http_response_code(403);
|
||||||
echo json_encode(['error' => 'Ei oikeutta tähän yritykseen']);
|
echo json_encode(['error' => 'Ei oikeutta tähän yritykseen']);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
$_SESSION['company_id'] = $paramCompany;
|
// Palauta parametrin company_id ILMAN session muutosta
|
||||||
|
return $paramCompany;
|
||||||
}
|
}
|
||||||
return requireCompany();
|
return requireCompany();
|
||||||
}
|
}
|
||||||
@@ -1487,6 +1490,14 @@ switch ($action) {
|
|||||||
echo json_encode(['error' => 'Virheellinen company_id']);
|
echo json_encode(['error' => 'Virheellinen company_id']);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Tarkista yrityksen oikeudet (vain superadmin tai oman yrityksen admin)
|
||||||
|
$isSA = ($_SESSION['role'] ?? '') === 'superadmin';
|
||||||
|
$userCompanies = $_SESSION['companies'] ?? [];
|
||||||
|
if (!$isSA && !in_array($companyId, $userCompanies)) {
|
||||||
|
http_response_code(403);
|
||||||
|
echo json_encode(['error' => 'Ei oikeutta tähän yritykseen']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (!isset($_FILES['logo']) || $_FILES['logo']['error'] !== UPLOAD_ERR_OK) {
|
if (!isset($_FILES['logo']) || $_FILES['logo']['error'] !== UPLOAD_ERR_OK) {
|
||||||
http_response_code(400);
|
http_response_code(400);
|
||||||
echo json_encode(['error' => 'Logotiedosto puuttuu tai virhe uploadissa']);
|
echo json_encode(['error' => 'Logotiedosto puuttuu tai virhe uploadissa']);
|
||||||
@@ -2210,7 +2221,7 @@ switch ($action) {
|
|||||||
}
|
}
|
||||||
if ($archived) {
|
if ($archived) {
|
||||||
dbArchiveCustomer($companyId, $archived);
|
dbArchiveCustomer($companyId, $archived);
|
||||||
dbDeleteCustomer($id);
|
dbDeleteCustomer($id, $companyId);
|
||||||
dbAddLog($companyId, currentUser(), 'customer_archive', $archived['id'], $archived['yritys'], 'Arkistoi asiakkaan');
|
dbAddLog($companyId, currentUser(), 'customer_archive', $archived['id'], $archived['yritys'], 'Arkistoi asiakkaan');
|
||||||
}
|
}
|
||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
@@ -2314,7 +2325,7 @@ switch ($action) {
|
|||||||
$devices = dbLoadDevices($companyId);
|
$devices = dbLoadDevices($companyId);
|
||||||
$deviceName = '';
|
$deviceName = '';
|
||||||
foreach ($devices as $d) { if ($d['id'] === $id) { $deviceName = $d['nimi']; break; } }
|
foreach ($devices as $d) { if ($d['id'] === $id) { $deviceName = $d['nimi']; break; } }
|
||||||
dbDeleteDevice($id);
|
dbDeleteDevice($id, $companyId);
|
||||||
dbAddLog($companyId, currentUser(), 'device_delete', $id, $deviceName, 'Poisti laitteen');
|
dbAddLog($companyId, currentUser(), 'device_delete', $id, $deviceName, 'Poisti laitteen');
|
||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
break;
|
break;
|
||||||
@@ -2416,7 +2427,7 @@ switch ($action) {
|
|||||||
$all = dbLoadIpam($companyId);
|
$all = dbLoadIpam($companyId);
|
||||||
$entryName = '';
|
$entryName = '';
|
||||||
foreach ($all as $e) { if ($e['id'] === $id) { $entryName = ($e['tyyppi'] === 'vlan' ? 'VLAN ' . $e['vlan_id'] : $e['verkko']) . ' ' . $e['nimi']; break; } }
|
foreach ($all as $e) { if ($e['id'] === $id) { $entryName = ($e['tyyppi'] === 'vlan' ? 'VLAN ' . $e['vlan_id'] : $e['verkko']) . ' ' . $e['nimi']; break; } }
|
||||||
dbDeleteIpam($id);
|
dbDeleteIpam($id, $companyId);
|
||||||
dbAddLog($companyId, currentUser(), 'ipam_delete', $id, $entryName, 'Poisti IPAM-merkinnän');
|
dbAddLog($companyId, currentUser(), 'ipam_delete', $id, $entryName, 'Poisti IPAM-merkinnän');
|
||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
break;
|
break;
|
||||||
@@ -2474,7 +2485,7 @@ switch ($action) {
|
|||||||
$input = json_decode(file_get_contents('php://input'), true);
|
$input = json_decode(file_get_contents('php://input'), true);
|
||||||
$id = $input['id'] ?? '';
|
$id = $input['id'] ?? '';
|
||||||
$guide = dbLoadGuide($id);
|
$guide = dbLoadGuide($id);
|
||||||
dbDeleteGuide($id);
|
dbDeleteGuide($id, $companyId);
|
||||||
dbAddLog($companyId, currentUser(), 'guide_delete', $id, $guide ? $guide['title'] : '', 'Poisti ohjeen');
|
dbAddLog($companyId, currentUser(), 'guide_delete', $id, $guide ? $guide['title'] : '', 'Poisti ohjeen');
|
||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
break;
|
break;
|
||||||
@@ -2511,7 +2522,7 @@ switch ($action) {
|
|||||||
$companyId = requireCompany();
|
$companyId = requireCompany();
|
||||||
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);
|
||||||
dbDeleteGuideCategory($input['id'] ?? '');
|
dbDeleteGuideCategory($input['id'] ?? '', $companyId);
|
||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2649,7 +2660,7 @@ switch ($action) {
|
|||||||
$id = $input['id'] ?? '';
|
$id = $input['id'] ?? '';
|
||||||
$todo = dbLoadTodo($id);
|
$todo = dbLoadTodo($id);
|
||||||
if ($todo) {
|
if ($todo) {
|
||||||
dbDeleteTodo($id);
|
dbDeleteTodo($id, $companyId);
|
||||||
dbAddLog($companyId, currentUser(), 'todo_delete', $id, $todo['title'] ?? '', '');
|
dbAddLog($companyId, currentUser(), 'todo_delete', $id, $todo['title'] ?? '', '');
|
||||||
}
|
}
|
||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
@@ -2719,6 +2730,13 @@ switch ($action) {
|
|||||||
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);
|
||||||
$todoId = $input['todo_id'] ?? '';
|
$todoId = $input['todo_id'] ?? '';
|
||||||
|
// Tarkista kuuluuko todo yritykseen
|
||||||
|
$todoCheck = _dbFetchOne("SELECT company_id FROM todos WHERE id = ?", [$todoId]);
|
||||||
|
if (!$todoCheck || $todoCheck['company_id'] !== $companyId) {
|
||||||
|
http_response_code(403);
|
||||||
|
echo json_encode(['error' => 'Ei oikeutta']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
$body = trim($input['body'] ?? '');
|
$body = trim($input['body'] ?? '');
|
||||||
if (empty($body)) {
|
if (empty($body)) {
|
||||||
http_response_code(400);
|
http_response_code(400);
|
||||||
@@ -2741,8 +2759,13 @@ switch ($action) {
|
|||||||
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);
|
||||||
$commentId = $input['id'] ?? '';
|
$commentId = $input['id'] ?? '';
|
||||||
// Tarkista onko oma kommentti tai admin
|
// Tarkista onko oma kommentti tai admin + kuuluuko todo yritykseen
|
||||||
$rows = _dbFetchAll("SELECT author FROM todo_comments WHERE id = ?", [$commentId]);
|
$rows = _dbFetchAll("SELECT tc.author, t.company_id FROM todo_comments tc JOIN todos t ON t.id = tc.todo_id WHERE tc.id = ?", [$commentId]);
|
||||||
|
if (!empty($rows) && $rows[0]['company_id'] !== $companyId) {
|
||||||
|
http_response_code(403);
|
||||||
|
echo json_encode(['error' => 'Ei oikeutta']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (!empty($rows) && ($rows[0]['author'] === currentUser() || isCompanyAdmin())) {
|
if (!empty($rows) && ($rows[0]['author'] === currentUser() || isCompanyAdmin())) {
|
||||||
dbDeleteTodoComment($commentId);
|
dbDeleteTodoComment($commentId);
|
||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
@@ -2758,6 +2781,13 @@ switch ($action) {
|
|||||||
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);
|
||||||
$todoId = $input['todo_id'] ?? '';
|
$todoId = $input['todo_id'] ?? '';
|
||||||
|
// Tarkista kuuluuko todo yritykseen
|
||||||
|
$todoCheck = _dbFetchOne("SELECT company_id FROM todos WHERE id = ?", [$todoId]);
|
||||||
|
if (!$todoCheck || $todoCheck['company_id'] !== $companyId) {
|
||||||
|
http_response_code(403);
|
||||||
|
echo json_encode(['error' => 'Ei oikeutta']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
$hours = floatval($input['hours'] ?? 0);
|
$hours = floatval($input['hours'] ?? 0);
|
||||||
if ($hours <= 0) {
|
if ($hours <= 0) {
|
||||||
http_response_code(400);
|
http_response_code(400);
|
||||||
@@ -2782,7 +2812,12 @@ switch ($action) {
|
|||||||
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);
|
||||||
$entryId = $input['id'] ?? '';
|
$entryId = $input['id'] ?? '';
|
||||||
$rows = _dbFetchAll("SELECT user FROM todo_time_entries WHERE id = ?", [$entryId]);
|
$rows = _dbFetchAll("SELECT te.user, t.company_id FROM todo_time_entries te JOIN todos t ON t.id = te.todo_id WHERE te.id = ?", [$entryId]);
|
||||||
|
if (!empty($rows) && $rows[0]['company_id'] !== $companyId) {
|
||||||
|
http_response_code(403);
|
||||||
|
echo json_encode(['error' => 'Ei oikeutta']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (!empty($rows) && ($rows[0]['user'] === currentUser() || isCompanyAdmin())) {
|
if (!empty($rows) && ($rows[0]['user'] === currentUser() || isCompanyAdmin())) {
|
||||||
dbDeleteTodoTimeEntry($entryId);
|
dbDeleteTodoTimeEntry($entryId);
|
||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
@@ -2818,12 +2853,15 @@ switch ($action) {
|
|||||||
|
|
||||||
case 'todo_subtask_toggle':
|
case 'todo_subtask_toggle':
|
||||||
requireAuth();
|
requireAuth();
|
||||||
requireCompany();
|
$companyId = requireCompany();
|
||||||
if ($method !== 'POST') { echo json_encode(['error' => 'POST required']); break; }
|
if ($method !== 'POST') { echo json_encode(['error' => 'POST required']); break; }
|
||||||
try {
|
try {
|
||||||
$input = json_decode(file_get_contents('php://input'), true);
|
$input = json_decode(file_get_contents('php://input'), true);
|
||||||
$subtaskId = $input['id'] ?? '';
|
$subtaskId = $input['id'] ?? '';
|
||||||
if (!$subtaskId) { echo json_encode(['error' => 'id vaaditaan']); break; }
|
if (!$subtaskId) { echo json_encode(['error' => 'id vaaditaan']); break; }
|
||||||
|
// Tarkista kuuluuko subtaskin todo yritykseen
|
||||||
|
$stCheck = _dbFetchOne("SELECT t.company_id FROM todo_subtasks s JOIN todos t ON t.id = s.todo_id WHERE s.id = ?", [$subtaskId]);
|
||||||
|
if (!$stCheck || $stCheck['company_id'] !== $companyId) { http_response_code(403); echo json_encode(['error' => 'Ei oikeutta']); break; }
|
||||||
$completed = dbToggleTodoSubtask($subtaskId);
|
$completed = dbToggleTodoSubtask($subtaskId);
|
||||||
echo json_encode(['success' => true, 'completed' => $completed]);
|
echo json_encode(['success' => true, 'completed' => $completed]);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
@@ -2834,12 +2872,15 @@ switch ($action) {
|
|||||||
|
|
||||||
case 'todo_subtask_delete':
|
case 'todo_subtask_delete':
|
||||||
requireAuth();
|
requireAuth();
|
||||||
requireCompany();
|
$companyId = requireCompany();
|
||||||
if ($method !== 'POST') { echo json_encode(['error' => 'POST required']); break; }
|
if ($method !== 'POST') { echo json_encode(['error' => 'POST required']); break; }
|
||||||
try {
|
try {
|
||||||
$input = json_decode(file_get_contents('php://input'), true);
|
$input = json_decode(file_get_contents('php://input'), true);
|
||||||
$subtaskId = $input['id'] ?? '';
|
$subtaskId = $input['id'] ?? '';
|
||||||
if (!$subtaskId) { echo json_encode(['error' => 'id vaaditaan']); break; }
|
if (!$subtaskId) { echo json_encode(['error' => 'id vaaditaan']); break; }
|
||||||
|
// Tarkista kuuluuko subtaskin todo yritykseen
|
||||||
|
$stCheck = _dbFetchOne("SELECT t.company_id FROM todo_subtasks s JOIN todos t ON t.id = s.todo_id WHERE s.id = ?", [$subtaskId]);
|
||||||
|
if (!$stCheck || $stCheck['company_id'] !== $companyId) { http_response_code(403); echo json_encode(['error' => 'Ei oikeutta']); break; }
|
||||||
$rows = _dbFetchAll("SELECT created_by FROM todo_subtasks WHERE id = ?", [$subtaskId]);
|
$rows = _dbFetchAll("SELECT created_by FROM todo_subtasks WHERE id = ?", [$subtaskId]);
|
||||||
if (!empty($rows) && ($rows[0]['created_by'] === currentUser() || isCompanyAdmin())) {
|
if (!empty($rows) && ($rows[0]['created_by'] === currentUser() || isCompanyAdmin())) {
|
||||||
dbDeleteTodoSubtask($subtaskId);
|
dbDeleteTodoSubtask($subtaskId);
|
||||||
@@ -2888,7 +2929,7 @@ switch ($action) {
|
|||||||
foreach ($archive as $c) {
|
foreach ($archive as $c) {
|
||||||
if ($c['id'] === $id) { $deleted = $c; break; }
|
if ($c['id'] === $id) { $deleted = $c; break; }
|
||||||
}
|
}
|
||||||
dbDeleteArchive($id);
|
dbDeleteArchive($id, $companyId);
|
||||||
$filesDir = getCompanyDir() . '/files/' . $id;
|
$filesDir = getCompanyDir() . '/files/' . $id;
|
||||||
if (is_dir($filesDir)) {
|
if (is_dir($filesDir)) {
|
||||||
array_map('unlink', glob($filesDir . '/*'));
|
array_map('unlink', glob($filesDir . '/*'));
|
||||||
@@ -2973,7 +3014,7 @@ switch ($action) {
|
|||||||
foreach ($leads as $l) {
|
foreach ($leads as $l) {
|
||||||
if ($l['id'] === $id) { $deleted = $l; break; }
|
if ($l['id'] === $id) { $deleted = $l; break; }
|
||||||
}
|
}
|
||||||
dbDeleteLead($id);
|
dbDeleteLead($id, $companyId);
|
||||||
if ($deleted) dbAddLog($companyId, currentUser(), 'lead_delete', $id, $deleted['yritys'] ?? '', 'Poisti liidin');
|
if ($deleted) dbAddLog($companyId, currentUser(), 'lead_delete', $id, $deleted['yritys'] ?? '', 'Poisti liidin');
|
||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
break;
|
break;
|
||||||
@@ -3014,7 +3055,7 @@ switch ($action) {
|
|||||||
];
|
];
|
||||||
dbSaveCustomer($companyId, $customer);
|
dbSaveCustomer($companyId, $customer);
|
||||||
// Poista liidi
|
// Poista liidi
|
||||||
dbDeleteLead($id);
|
dbDeleteLead($id, $companyId);
|
||||||
dbAddLog($companyId, currentUser(), 'lead_to_customer', $customer['id'], $customer['yritys'], 'Muutti liidin asiakkaaksi');
|
dbAddLog($companyId, currentUser(), 'lead_to_customer', $customer['id'], $customer['yritys'], 'Muutti liidin asiakkaaksi');
|
||||||
echo json_encode($customer);
|
echo json_encode($customer);
|
||||||
break;
|
break;
|
||||||
@@ -3828,7 +3869,7 @@ switch ($action) {
|
|||||||
foreach ($tickets as $t) {
|
foreach ($tickets as $t) {
|
||||||
if ($t['id'] === $id) { $deleted = $t; break; }
|
if ($t['id'] === $id) { $deleted = $t; break; }
|
||||||
}
|
}
|
||||||
dbDeleteTicket($id);
|
dbDeleteTicket($id, $companyId);
|
||||||
if ($deleted) dbAddLog($companyId, currentUser(), 'ticket_delete', $id, $deleted['subject'] ?? '', 'Poisti tiketin');
|
if ($deleted) dbAddLog($companyId, currentUser(), 'ticket_delete', $id, $deleted['subject'] ?? '', 'Poisti tiketin');
|
||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
break;
|
break;
|
||||||
@@ -3935,7 +3976,7 @@ switch ($action) {
|
|||||||
$ids = $input['ids'] ?? [];
|
$ids = $input['ids'] ?? [];
|
||||||
$deleted = 0;
|
$deleted = 0;
|
||||||
foreach ($ids as $ticketId) {
|
foreach ($ids as $ticketId) {
|
||||||
dbDeleteTicket($ticketId);
|
dbDeleteTicket($ticketId, $companyId);
|
||||||
$deleted++;
|
$deleted++;
|
||||||
}
|
}
|
||||||
dbAddLog($companyId, currentUser(), 'ticket_delete', '', '', "Massapoisto: $deleted tikettiä");
|
dbAddLog($companyId, currentUser(), 'ticket_delete', '', '', "Massapoisto: $deleted tikettiä");
|
||||||
@@ -3948,7 +3989,7 @@ switch ($action) {
|
|||||||
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);
|
||||||
$ruleId = $input['id'] ?? '';
|
$ruleId = $input['id'] ?? '';
|
||||||
dbDeleteTicketRule($ruleId);
|
dbDeleteTicketRule($ruleId, $companyId);
|
||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -4065,7 +4106,7 @@ switch ($action) {
|
|||||||
$companyId = requireCompany();
|
$companyId = requireCompany();
|
||||||
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);
|
||||||
dbDeleteTemplate($input['id'] ?? '');
|
dbDeleteTemplate($input['id'] ?? '', $companyId);
|
||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -4362,7 +4403,7 @@ switch ($action) {
|
|||||||
// Delete all existing mailboxes and re-save
|
// Delete all existing mailboxes and re-save
|
||||||
$existingMailboxes = dbLoadMailboxes($companyId);
|
$existingMailboxes = dbLoadMailboxes($companyId);
|
||||||
foreach ($existingMailboxes as $existing) {
|
foreach ($existingMailboxes as $existing) {
|
||||||
dbDeleteMailbox($existing['id']);
|
dbDeleteMailbox($existing['id'], $companyId);
|
||||||
}
|
}
|
||||||
foreach ($input['mailboxes'] as $mb) {
|
foreach ($input['mailboxes'] as $mb) {
|
||||||
if (empty($mb['id'])) $mb['id'] = generateId();
|
if (empty($mb['id'])) $mb['id'] = generateId();
|
||||||
@@ -4373,7 +4414,7 @@ switch ($action) {
|
|||||||
// Delete all existing rules and re-save
|
// Delete all existing rules and re-save
|
||||||
$existingRules = dbLoadTicketRules($companyId);
|
$existingRules = dbLoadTicketRules($companyId);
|
||||||
foreach ($existingRules as $existing) {
|
foreach ($existingRules as $existing) {
|
||||||
dbDeleteTicketRule($existing['id']);
|
dbDeleteTicketRule($existing['id'], $companyId);
|
||||||
}
|
}
|
||||||
foreach ($input['ticket_rules'] as $rule) {
|
foreach ($input['ticket_rules'] as $rule) {
|
||||||
if (empty($rule['id'])) $rule['id'] = generateId();
|
if (empty($rule['id'])) $rule['id'] = generateId();
|
||||||
@@ -4402,7 +4443,7 @@ switch ($action) {
|
|||||||
$companyId = requireCompany();
|
$companyId = requireCompany();
|
||||||
$input = json_decode(file_get_contents('php://input'), true);
|
$input = json_decode(file_get_contents('php://input'), true);
|
||||||
$mailboxId = $input['mailbox_id'] ?? '';
|
$mailboxId = $input['mailbox_id'] ?? '';
|
||||||
$mailbox = dbGetMailbox($mailboxId);
|
$mailbox = dbGetMailbox($mailboxId, $companyId);
|
||||||
if (!$mailbox) {
|
if (!$mailbox) {
|
||||||
echo json_encode(['error' => 'Postilaatikkoa ei löydy']);
|
echo json_encode(['error' => 'Postilaatikkoa ei löydy']);
|
||||||
break;
|
break;
|
||||||
@@ -4571,7 +4612,7 @@ switch ($action) {
|
|||||||
'auto_reply_body' => trim($input['auto_reply_body'] ?? ''),
|
'auto_reply_body' => trim($input['auto_reply_body'] ?? ''),
|
||||||
];
|
];
|
||||||
// Hae vanha mailbox salasanojen vertailua varten
|
// Hae vanha mailbox salasanojen vertailua varten
|
||||||
$existingMb = dbGetMailbox($mb['id']);
|
$existingMb = dbGetMailbox($mb['id'], $companyId);
|
||||||
// IMAP-salasana: jos ******** -> pidä vanha, muuten päivitä
|
// IMAP-salasana: jos ******** -> pidä vanha, muuten päivitä
|
||||||
if (isset($input['imap_password']) && $input['imap_password'] !== '********') {
|
if (isset($input['imap_password']) && $input['imap_password'] !== '********') {
|
||||||
$mb['imap_password'] = $input['imap_password'];
|
$mb['imap_password'] = $input['imap_password'];
|
||||||
@@ -4608,7 +4649,7 @@ switch ($action) {
|
|||||||
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);
|
||||||
$mbId = $input['id'] ?? '';
|
$mbId = $input['id'] ?? '';
|
||||||
dbDeleteMailbox($mbId);
|
dbDeleteMailbox($mbId, $companyId);
|
||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -5597,7 +5638,7 @@ switch ($action) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Varmista että tiketti kuuluu yritykselle
|
// Varmista että tiketti kuuluu yritykselle
|
||||||
$ticket = _dbFetch("SELECT * FROM tickets WHERE id = ? AND company_id = ?", [$ticketId, $companyId]);
|
$ticket = _dbFetchOne("SELECT * FROM tickets WHERE id = ? AND company_id = ?", [$ticketId, $companyId]);
|
||||||
if (!$ticket || empty($ticket['zammad_ticket_id'])) {
|
if (!$ticket || empty($ticket['zammad_ticket_id'])) {
|
||||||
http_response_code(404);
|
http_response_code(404);
|
||||||
echo json_encode(['error' => 'Tikettiä ei löydy']);
|
echo json_encode(['error' => 'Tikettiä ei löydy']);
|
||||||
|
|||||||
66
db.php
66
db.php
@@ -1171,8 +1171,9 @@ function dbSaveCustomer(string $companyId, array $customer): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbDeleteCustomer(string $customerId): void {
|
function dbDeleteCustomer(string $customerId, string $companyId = ''): void {
|
||||||
_dbExecute("DELETE FROM customers WHERE id = ?", [$customerId]);
|
if ($companyId) _dbExecute("DELETE FROM customers WHERE id = ? AND company_id = ?", [$customerId, $companyId]);
|
||||||
|
else _dbExecute("DELETE FROM customers WHERE id = ?", [$customerId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== SIJAINNIT (SITES) — POISTETTU, KÄYTETÄÄN LAITETILOJA ====================
|
// ==================== SIJAINNIT (SITES) — POISTETTU, KÄYTETÄÄN LAITETILOJA ====================
|
||||||
@@ -1224,8 +1225,9 @@ function dbSaveDevice(string $companyId, array $device): void {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbDeleteDevice(string $deviceId): void {
|
function dbDeleteDevice(string $deviceId, string $companyId = ''): void {
|
||||||
_dbExecute("DELETE FROM devices WHERE id = ?", [$deviceId]);
|
if ($companyId) _dbExecute("DELETE FROM devices WHERE id = ? AND company_id = ?", [$deviceId, $companyId]);
|
||||||
|
else _dbExecute("DELETE FROM devices WHERE id = ?", [$deviceId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== IPAM ====================
|
// ==================== IPAM ====================
|
||||||
@@ -1270,8 +1272,9 @@ function dbSaveIpam(string $companyId, array $entry): void {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbDeleteIpam(string $id): void {
|
function dbDeleteIpam(string $id, string $companyId = ''): void {
|
||||||
_dbExecute("DELETE FROM ipam WHERE id = ?", [$id]);
|
if ($companyId) _dbExecute("DELETE FROM ipam WHERE id = ? AND company_id = ?", [$id, $companyId]);
|
||||||
|
else _dbExecute("DELETE FROM ipam WHERE id = ?", [$id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== OHJEET (GUIDES) ====================
|
// ==================== OHJEET (GUIDES) ====================
|
||||||
@@ -1288,8 +1291,9 @@ function dbSaveGuideCategory(string $companyId, array $cat): void {
|
|||||||
", [$cat['id'], $companyId, $cat['nimi'] ?? '', $cat['sort_order'] ?? 0]);
|
", [$cat['id'], $companyId, $cat['nimi'] ?? '', $cat['sort_order'] ?? 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbDeleteGuideCategory(string $catId): void {
|
function dbDeleteGuideCategory(string $catId, string $companyId = ''): void {
|
||||||
_dbExecute("DELETE FROM guide_categories WHERE id = ?", [$catId]);
|
if ($companyId) _dbExecute("DELETE FROM guide_categories WHERE id = ? AND company_id = ?", [$catId, $companyId]);
|
||||||
|
else _dbExecute("DELETE FROM guide_categories WHERE id = ?", [$catId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbLoadGuides(string $companyId): array {
|
function dbLoadGuides(string $companyId): array {
|
||||||
@@ -1334,8 +1338,9 @@ function dbSaveGuide(string $companyId, array $g): void {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbDeleteGuide(string $guideId): void {
|
function dbDeleteGuide(string $guideId, string $companyId = ''): void {
|
||||||
_dbExecute("DELETE FROM guides WHERE id = ?", [$guideId]);
|
if ($companyId) _dbExecute("DELETE FROM guides WHERE id = ? AND company_id = ?", [$guideId, $companyId]);
|
||||||
|
else _dbExecute("DELETE FROM guides WHERE id = ?", [$guideId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== LIIDIT ====================
|
// ==================== LIIDIT ====================
|
||||||
@@ -1376,8 +1381,9 @@ function dbSaveLead(string $companyId, array $lead): void {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbDeleteLead(string $leadId): void {
|
function dbDeleteLead(string $leadId, string $companyId = ''): void {
|
||||||
_dbExecute("DELETE FROM leads WHERE id = ?", [$leadId]);
|
if ($companyId) _dbExecute("DELETE FROM leads WHERE id = ? AND company_id = ?", [$leadId, $companyId]);
|
||||||
|
else _dbExecute("DELETE FROM leads WHERE id = ?", [$leadId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== TIKETIT ====================
|
// ==================== TIKETIT ====================
|
||||||
@@ -1508,8 +1514,9 @@ function dbSaveTicket(string $companyId, array $ticket): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbDeleteTicket(string $ticketId): void {
|
function dbDeleteTicket(string $ticketId, string $companyId = ''): void {
|
||||||
_dbExecute("DELETE FROM tickets WHERE id = ?", [$ticketId]);
|
if ($companyId) _dbExecute("DELETE FROM tickets WHERE id = ? AND company_id = ?", [$ticketId, $companyId]);
|
||||||
|
else _dbExecute("DELETE FROM tickets WHERE id = ?", [$ticketId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbFindTicketByMessageId(string $companyId, string $messageId): ?array {
|
function dbFindTicketByMessageId(string $companyId, string $messageId): ?array {
|
||||||
@@ -1550,8 +1557,9 @@ function dbRestoreArchive(string $archiveId): ?array {
|
|||||||
return json_decode($row['data'], true);
|
return json_decode($row['data'], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbDeleteArchive(string $archiveId): void {
|
function dbDeleteArchive(string $archiveId, string $companyId = ''): void {
|
||||||
_dbExecute("DELETE FROM archives WHERE id = ?", [$archiveId]);
|
if ($companyId) _dbExecute("DELETE FROM archives WHERE id = ? AND company_id = ?", [$archiveId, $companyId]);
|
||||||
|
else _dbExecute("DELETE FROM archives WHERE id = ?", [$archiveId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== CHANGELOG ====================
|
// ==================== CHANGELOG ====================
|
||||||
@@ -1624,12 +1632,17 @@ function dbSaveMailbox(string $companyId, array $mailbox): void {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbDeleteMailbox(string $mailboxId): void {
|
function dbDeleteMailbox(string $mailboxId, string $companyId = ''): void {
|
||||||
_dbExecute("DELETE FROM mailboxes WHERE id = ?", [$mailboxId]);
|
if ($companyId) _dbExecute("DELETE FROM mailboxes WHERE id = ? AND company_id = ?", [$mailboxId, $companyId]);
|
||||||
|
else _dbExecute("DELETE FROM mailboxes WHERE id = ?", [$mailboxId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbGetMailbox(string $mailboxId): ?array {
|
function dbGetMailbox(string $mailboxId, string $companyId = ''): ?array {
|
||||||
|
if ($companyId) {
|
||||||
|
$b = _dbFetchOne("SELECT * FROM mailboxes WHERE id = ? AND company_id = ?", [$mailboxId, $companyId]);
|
||||||
|
} else {
|
||||||
$b = _dbFetchOne("SELECT * FROM mailboxes WHERE id = ?", [$mailboxId]);
|
$b = _dbFetchOne("SELECT * FROM mailboxes WHERE id = ?", [$mailboxId]);
|
||||||
|
}
|
||||||
if ($b) {
|
if ($b) {
|
||||||
$b['aktiivinen'] = (bool)$b['aktiivinen'];
|
$b['aktiivinen'] = (bool)$b['aktiivinen'];
|
||||||
$b['imap_port'] = (int)$b['imap_port'];
|
$b['imap_port'] = (int)$b['imap_port'];
|
||||||
@@ -1679,8 +1692,9 @@ function dbSaveTicketRule(string $companyId, array $rule): void {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbDeleteTicketRule(string $ruleId): void {
|
function dbDeleteTicketRule(string $ruleId, string $companyId = ''): void {
|
||||||
_dbExecute("DELETE FROM ticket_rules WHERE id = ?", [$ruleId]);
|
if ($companyId) _dbExecute("DELETE FROM ticket_rules WHERE id = ? AND company_id = ?", [$ruleId, $companyId]);
|
||||||
|
else _dbExecute("DELETE FROM ticket_rules WHERE id = ?", [$ruleId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== TIKETTITYYPIT ====================
|
// ==================== TIKETTITYYPIT ====================
|
||||||
@@ -1801,8 +1815,9 @@ function dbSaveTemplate(string $companyId, array $tpl): void {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbDeleteTemplate(string $templateId): void {
|
function dbDeleteTemplate(string $templateId, string $companyId = ''): void {
|
||||||
_dbExecute("DELETE FROM reply_templates WHERE id = ?", [$templateId]);
|
if ($companyId) _dbExecute("DELETE FROM reply_templates WHERE id = ? AND company_id = ?", [$templateId, $companyId]);
|
||||||
|
else _dbExecute("DELETE FROM reply_templates WHERE id = ?", [$templateId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== PRIORITY EMAILS (ASIAKKUUDET) ====================
|
// ==================== PRIORITY EMAILS (ASIAKKUUDET) ====================
|
||||||
@@ -1888,8 +1903,9 @@ function dbSaveTodo(string $companyId, array $todo): void {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbDeleteTodo(string $todoId): void {
|
function dbDeleteTodo(string $todoId, string $companyId = ''): void {
|
||||||
_dbExecute("DELETE FROM todos WHERE id = ?", [$todoId]);
|
if ($companyId) _dbExecute("DELETE FROM todos WHERE id = ? AND company_id = ?", [$todoId, $companyId]);
|
||||||
|
else _dbExecute("DELETE FROM todos WHERE id = ?", [$todoId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbAddTodoComment(string $todoId, array $comment): void {
|
function dbAddTodoComment(string $todoId, array $comment): void {
|
||||||
|
|||||||
Reference in New Issue
Block a user