mirror of
https://github.com/itflow-org/itflow
synced 2026-07-26 10:17:15 +00:00
Feature: Add Deny Client Access to Client Access Permssions - BREAKS UI, MUST UPDATE DB USING php scripts/cli_update.php --db_update
This commit is contained in:
11
admin/database_updates/2.4.6.php
Normal file
11
admin/database_updates/2.4.6.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* ITFlow - Database update to version 2.4.6 (from 2.4.5)
|
||||
* Included by admin/database_updates.php - do not access directly
|
||||
*/
|
||||
|
||||
defined('FROM_DB_UPDATER') || die("Direct file access is not allowed");
|
||||
|
||||
// Add Allow Deny Client Access to the Enforce Client Permissions
|
||||
mysqli_query($mysqli, "ALTER TABLE `user_client_permissions` ADD COLUMN `permission_type` ENUM('allow','deny') NOT NULL DEFAULT 'allow'");
|
||||
@@ -115,35 +115,53 @@ ob_start();
|
||||
<div class="tab-pane fade" id="pills-user-access">
|
||||
|
||||
<div class="alert alert-info">
|
||||
Check boxes to authorize user client access. No boxes grant full client access. Admin users are unaffected.
|
||||
<strong>Allow</strong> restricts the user to the selected clients (no Allow = full access). <strong>Deny</strong> blocks a client regardless of Allow. Admin users are unaffected.
|
||||
</div>
|
||||
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item bg-dark">
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" onclick="this.closest('.tab-pane').querySelectorAll('.client-checkbox').forEach(checkbox => checkbox.checked = this.checked);">
|
||||
<label class="form-check-label ml-3"><strong>Restrict Access to Clients</strong></label>
|
||||
</div>
|
||||
</li>
|
||||
<div class="mb-2">
|
||||
<small class="text-muted mr-2">Set all:</small>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="document.querySelectorAll('#accessTable .perm-none').forEach(r => r.checked = true);">No Rule</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-success" onclick="document.querySelectorAll('#accessTable .perm-allow').forEach(r => r.checked = true);">Allow</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-danger" onclick="document.querySelectorAll('#accessTable .perm-deny').forEach(r => r.checked = true);">Deny</button>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-hover mb-0" id="accessTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th class="text-center" style="width: 90px;">No Rule</th>
|
||||
<th class="text-center text-success" style="width: 90px;">Allow</th>
|
||||
<th class="text-center text-danger" style="width: 90px;">Deny</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
$sql_client_select = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_archived_at IS NULL ORDER BY client_name ASC");
|
||||
while ($row = mysqli_fetch_assoc($sql_client_select)) {
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = escapeHtml($row['client_name']);
|
||||
<?php
|
||||
$sql_client_select = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_archived_at IS NULL ORDER BY client_name ASC");
|
||||
while ($row = mysqli_fetch_assoc($sql_client_select)) {
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = escapeHtml($row['client_name']);
|
||||
?>
|
||||
|
||||
?>
|
||||
<li class="list-group-item">
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input client-checkbox" name="clients[]" value="<?php echo $client_id; ?>">
|
||||
<label class="form-check-label ml-3"><?php echo $client_name; ?></label>
|
||||
</div>
|
||||
</li>
|
||||
<tr>
|
||||
<td class="align-middle"><?php echo $client_name; ?></td>
|
||||
<td class="text-center align-middle">
|
||||
<input type="radio" class="perm-none" name="client_permission[<?php echo $client_id; ?>]" value="" checked>
|
||||
</td>
|
||||
<td class="text-center align-middle">
|
||||
<input type="radio" class="perm-allow" name="client_permission[<?php echo $client_id; ?>]" value="allow">
|
||||
</td>
|
||||
<td class="text-center align-middle">
|
||||
<input type="radio" class="perm-deny" name="client_permission[<?php echo $client_id; ?>]" value="deny">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
|
||||
</ul>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -18,16 +18,22 @@ $user_config_force_mfa = intval($row['user_config_force_mfa']);
|
||||
$user_role_id = intval($row['user_role_id']);
|
||||
$user_initials = escapeHtml(initials($user_name));
|
||||
|
||||
// Get User Client Access Permissions
|
||||
$user_client_access_sql = mysqli_query($mysqli,"SELECT client_id FROM user_client_permissions WHERE user_id = $user_id");
|
||||
$client_access_array = [];
|
||||
// Get User Client Access Permissions (allow + deny)
|
||||
$user_client_access_sql = mysqli_query($mysqli,"SELECT client_id, permission_type FROM user_client_permissions WHERE user_id = $user_id");
|
||||
$client_allow_array = []; // allow
|
||||
$client_deny_array = []; // deny
|
||||
while ($row = mysqli_fetch_assoc($user_client_access_sql)) {
|
||||
$client_access_array[] = intval($row['client_id']);
|
||||
if ($row['permission_type'] === 'deny') {
|
||||
$client_deny_array[] = intval($row['client_id']);
|
||||
} else {
|
||||
$client_allow_array[] = intval($row['client_id']);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
|
||||
<div class="modal-header bg-dark">
|
||||
<h5 class="modal-title"><i class="fas fa-fw fa-user-edit mr-2"></i>Editing user:
|
||||
<strong><?php echo $user_name; ?></strong></h5>
|
||||
@@ -161,37 +167,55 @@ ob_start();
|
||||
<div class="tab-pane fade" id="pills-user-access<?php echo $user_id; ?>">
|
||||
|
||||
<div class="alert alert-info">
|
||||
Check boxes to authorize user client access. No boxes grant full client access. Admin users are unaffected.
|
||||
<strong>Allow</strong> restricts the user to the selected clients (no Allow = full access). <strong>Deny</strong> blocks a client regardless of Allow. Admin users are unaffected.
|
||||
</div>
|
||||
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item bg-dark">
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" onclick="this.closest('.tab-pane').querySelectorAll('.client-checkbox').forEach(checkbox => checkbox.checked = this.checked);">
|
||||
<label class="form-check-label ml-3"><strong>Restrict Access to Clients</strong></label>
|
||||
</div>
|
||||
</li>
|
||||
<div class="mb-2">
|
||||
<small class="text-muted mr-2">Set all:</small>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="document.querySelectorAll('#accessTable<?php echo $user_id; ?> .perm-none').forEach(r => r.checked = true);">No Rule</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-success" onclick="document.querySelectorAll('#accessTable<?php echo $user_id; ?> .perm-allow').forEach(r => r.checked = true);">Allow</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-danger" onclick="document.querySelectorAll('#accessTable<?php echo $user_id; ?> .perm-deny').forEach(r => r.checked = true);">Deny</button>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-hover mb-0" id="accessTable<?php echo $user_id; ?>">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th class="text-center" style="width: 90px;">No Rule</th>
|
||||
<th class="text-center text-success" style="width: 90px;">Allow</th>
|
||||
<th class="text-center text-danger" style="width: 90px;">Deny</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
$sql_client_select = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_archived_at IS NULL ORDER BY client_name ASC");
|
||||
while ($row = mysqli_fetch_assoc($sql_client_select)) {
|
||||
$client_id_select = intval($row['client_id']);
|
||||
$client_name_select = escapeHtml($row['client_name']);
|
||||
<?php
|
||||
$sql_client_select = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_archived_at IS NULL ORDER BY client_name ASC");
|
||||
while ($row = mysqli_fetch_assoc($sql_client_select)) {
|
||||
$client_id_select = intval($row['client_id']);
|
||||
$client_name_select = escapeHtml($row['client_name']);
|
||||
$client_is_allow = in_array($client_id_select, $client_allow_array);
|
||||
$client_is_deny = in_array($client_id_select, $client_deny_array);
|
||||
?>
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<td class="align-middle"><?php echo $client_name_select; ?></td>
|
||||
<td class="text-center align-middle">
|
||||
<input type="radio" class="perm-none" name="client_permission[<?php echo $client_id_select; ?>]" value="" <?php if (!$client_is_allow && !$client_is_deny) { echo "checked"; } ?>>
|
||||
</td>
|
||||
<td class="text-center align-middle">
|
||||
<input type="radio" class="perm-allow" name="client_permission[<?php echo $client_id_select; ?>]" value="allow" <?php if ($client_is_allow) { echo "checked"; } ?>>
|
||||
</td>
|
||||
<td class="text-center align-middle">
|
||||
<input type="radio" class="perm-deny" name="client_permission[<?php echo $client_id_select; ?>]" value="deny" <?php if ($client_is_deny) { echo "checked"; } ?>>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<li class="list-group-item">
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input client-checkbox" name="clients[]" value="<?php echo $client_id_select; ?>" <?php if (in_array($client_id_select, $client_access_array)) { echo "checked"; } ?>>
|
||||
<label class="form-check-label ml-2"><?php echo $client_name_select; ?></label>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
</ul>
|
||||
<?php } ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -19,11 +19,13 @@ if (isset($_POST['add_user'])) {
|
||||
|
||||
$user_id = mysqli_insert_id($mysqli);
|
||||
|
||||
// Add Client Access Permissions if set
|
||||
if (isset($_POST['clients'])) {
|
||||
foreach($_POST['clients'] as $client_id) {
|
||||
$client_id = intval($client_id);
|
||||
mysqli_query($mysqli,"INSERT INTO user_client_permissions SET user_id = $user_id, client_id = $client_id");
|
||||
// Add Client Access (allow / deny per client)
|
||||
if (isset($_POST['client_permission'])) {
|
||||
foreach ($_POST['client_permission'] as $perm_client_id => $perm_type) {
|
||||
$perm_client_id = intval($perm_client_id);
|
||||
if ($perm_type === 'allow' || $perm_type === 'deny') {
|
||||
mysqli_query($mysqli, "INSERT INTO user_client_permissions SET user_id = $user_id, client_id = $perm_client_id, permission_type = '$perm_type'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,12 +109,14 @@ if (isset($_POST['edit_user'])) {
|
||||
$user_id = intval($_POST['user_id']);
|
||||
$new_password = trim($_POST['new_password']);
|
||||
|
||||
// Update Client Access
|
||||
// Update Client Access (allow / deny per client)
|
||||
mysqli_query($mysqli,"DELETE FROM user_client_permissions WHERE user_id = $user_id");
|
||||
if (isset($_POST['clients'])) {
|
||||
foreach($_POST['clients'] as $client_id) {
|
||||
$client_id = intval($client_id);
|
||||
mysqli_query($mysqli,"INSERT INTO user_client_permissions SET user_id = $user_id, client_id = $client_id");
|
||||
if (isset($_POST['client_permission'])) {
|
||||
foreach ($_POST['client_permission'] as $perm_client_id => $perm_type) {
|
||||
$perm_client_id = intval($perm_client_id);
|
||||
if ($perm_type === 'allow' || $perm_type === 'deny') {
|
||||
mysqli_query($mysqli, "INSERT INTO user_client_permissions SET user_id = $user_id, client_id = $perm_client_id, permission_type = '$perm_type'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
3
db.sql
3
db.sql
@@ -2785,6 +2785,7 @@ DROP TABLE IF EXISTS `user_client_permissions`;
|
||||
CREATE TABLE `user_client_permissions` (
|
||||
`user_id` int(11) NOT NULL,
|
||||
`client_id` int(11) NOT NULL,
|
||||
`permission_type` enum('allow','deny') NOT NULL DEFAULT 'allow',
|
||||
PRIMARY KEY (`user_id`,`client_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
@@ -2995,4 +2996,4 @@ CREATE TABLE `vendors` (
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
-- Dump completed on 2026-07-22 17:36:39
|
||||
-- Dump completed on 2026-07-25 13:20:49
|
||||
|
||||
@@ -82,10 +82,25 @@ function enforceClientAccess($client_id = null) {
|
||||
redirect('clients.php');
|
||||
}
|
||||
|
||||
// Deny list wins: an explicit deny blocks access regardless of any allow rule
|
||||
$deny_sql = "SELECT client_id
|
||||
FROM user_client_permissions
|
||||
WHERE user_id = $session_user_id
|
||||
AND client_id = $client_id
|
||||
AND permission_type = 'deny'
|
||||
LIMIT 1";
|
||||
$deny_result = mysqli_query($mysqli, $deny_sql);
|
||||
if ($deny_result && mysqli_num_rows($deny_result) > 0) {
|
||||
logAudit('Client', 'Access', "$session_name was denied permission from accessing client", $client_id, $client_id);
|
||||
flashAlert('Access Denied - You do not have permission to access that client!', 'error');
|
||||
redirect('clients.php');
|
||||
}
|
||||
|
||||
// Check if this user has any client permissions set
|
||||
$permissions_sql = "SELECT client_id
|
||||
FROM user_client_permissions
|
||||
WHERE user_id = $session_user_id
|
||||
AND permission_type = 'allow'
|
||||
LIMIT 1";
|
||||
|
||||
$permissions_result = mysqli_query($mysqli, $permissions_sql);
|
||||
@@ -100,6 +115,7 @@ function enforceClientAccess($client_id = null) {
|
||||
FROM user_client_permissions
|
||||
WHERE user_id = $session_user_id
|
||||
AND client_id = $client_id
|
||||
AND permission_type = 'allow'
|
||||
LIMIT 1";
|
||||
|
||||
$access_result = mysqli_query($mysqli, $access_sql);
|
||||
|
||||
@@ -49,17 +49,30 @@ if ($session_user_archived_at !== null) {
|
||||
redirect("/login.php");
|
||||
}
|
||||
|
||||
// Load user client permissions
|
||||
$user_client_access_sql = "SELECT client_id FROM user_client_permissions WHERE user_id = $session_user_id";
|
||||
// Load user client permissions (allow + deny lists)
|
||||
$user_client_access_sql = "SELECT client_id, permission_type FROM user_client_permissions WHERE user_id = $session_user_id";
|
||||
$user_client_access_result = mysqli_query($mysqli, $user_client_access_sql);
|
||||
|
||||
$client_access_array = [];
|
||||
$client_access_array = []; // allow
|
||||
$client_deny_array = []; // deny
|
||||
while ($row = mysqli_fetch_assoc($user_client_access_result)) {
|
||||
$client_access_array[] = $row['client_id'];
|
||||
if ($row['permission_type'] === 'deny') {
|
||||
$client_deny_array[] = (int) $row['client_id'];
|
||||
} else {
|
||||
$client_access_array[] = (int) $row['client_id'];
|
||||
}
|
||||
}
|
||||
|
||||
$client_access_string = implode(',', $client_access_array);
|
||||
$client_deny_string = implode(',', $client_deny_array);
|
||||
|
||||
$access_permission_query = "";
|
||||
if ($client_access_string && !$session_is_admin) {
|
||||
$access_permission_query = "AND clients.client_id IN ($client_access_string)";
|
||||
if (!$session_is_admin) {
|
||||
// Restrict to the allow list (if any), then subtract the deny list
|
||||
if ($client_access_string) {
|
||||
$access_permission_query .= " AND clients.client_id IN ($client_access_string)";
|
||||
}
|
||||
if ($client_deny_string) {
|
||||
$access_permission_query .= " AND clients.client_id NOT IN ($client_deny_string)";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user