mirror of
https://github.com/itflow-org/itflow
synced 2026-08-17 04:55:13 +00:00
Feature: Designate a client record as your organization currently only provdes a direct link when you click company name in top of the side nav
This commit is contained in:
17
admin/database_updates/2.7.1.php
Normal file
17
admin/database_updates/2.7.1.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ITFlow - Database update to version 2.7.1 (from 2.7.0)
|
||||||
|
* Included by admin/database_updates.php - do not access directly
|
||||||
|
*/
|
||||||
|
|
||||||
|
defined('FROM_DB_UPDATER') || die("Direct file access is not allowed");
|
||||||
|
|
||||||
|
// Which client record, if any, is the MSP's own company. Most installs create one to
|
||||||
|
// hold their internal tickets, documentation, assets and credentials, but nothing in
|
||||||
|
// the app knew that record was special. Admin > Settings > Company Details sets it.
|
||||||
|
//
|
||||||
|
// 0 means no client is designated, which is every existing install - nothing changes
|
||||||
|
// until an administrator chooses one.
|
||||||
|
mysqli_query($mysqli, "ALTER TABLE `settings`
|
||||||
|
ADD COLUMN `config_internal_client_id` int(11) NOT NULL DEFAULT 0");
|
||||||
@@ -42,8 +42,18 @@ if (isset($_POST['edit_company'])) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The client record standing in for this company. Verified against the clients table
|
||||||
|
// rather than trusted from the POST, so a stale or hand-made value cannot leave the
|
||||||
|
// sidebar pointing at a client that no longer exists. 0 clears the designation.
|
||||||
|
$internal_client_id = intval($_POST['internal_client_id'] ?? 0);
|
||||||
|
if ($internal_client_id !== 0 && !mysqli_num_rows(mysqli_query($mysqli, "SELECT client_id FROM clients WHERE client_id = $internal_client_id LIMIT 1"))) {
|
||||||
|
$internal_client_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
mysqli_query($mysqli,"UPDATE companies SET company_name = '$name', company_address = '$address', company_city = '$city', company_state = '$state', company_zip = '$zip', company_country = '$country', company_phone_country_code = '$phone_country_code', company_phone = '$phone', company_email = '$email', company_website = '$website', company_tax_id = '$tax_id' WHERE company_id = 1");
|
mysqli_query($mysqli,"UPDATE companies SET company_name = '$name', company_address = '$address', company_city = '$city', company_state = '$state', company_zip = '$zip', company_country = '$country', company_phone_country_code = '$phone_country_code', company_phone = '$phone', company_email = '$email', company_website = '$website', company_tax_id = '$tax_id' WHERE company_id = 1");
|
||||||
|
|
||||||
|
mysqli_query($mysqli,"UPDATE settings SET config_internal_client_id = $internal_client_id WHERE company_id = 1");
|
||||||
|
|
||||||
logAudit("Settings", "Edit", "$session_name edited company details");
|
logAudit("Settings", "Edit", "$session_name edited company details");
|
||||||
|
|
||||||
flashAlert("Company <strong>$name</strong> edited");
|
flashAlert("Company <strong>$name</strong> edited");
|
||||||
|
|||||||
@@ -141,6 +141,27 @@ $company_initials = escapeHtml(initials($company_name));
|
|||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label>My Company's Client Record</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="fa fa-fw fa-house-user"></i></span>
|
||||||
|
<select class="form-select select2" name="internal_client_id">
|
||||||
|
<option value="0">None</option>
|
||||||
|
<?php
|
||||||
|
$sql_internal_clients = mysqli_query($mysqli, "SELECT client_id, client_name FROM clients WHERE client_archived_at IS NULL ORDER BY client_name ASC");
|
||||||
|
while ($row_internal_client = mysqli_fetch_assoc($sql_internal_clients)) {
|
||||||
|
$internal_client_id_select = intval($row_internal_client['client_id']);
|
||||||
|
$internal_client_name_select = escapeHtml($row_internal_client['client_name']);
|
||||||
|
?>
|
||||||
|
<option <?php if ($config_internal_client_id == $internal_client_id_select) { echo "selected"; } ?> value="<?= $internal_client_id_select ?>"><?= $internal_client_name_select ?></option>
|
||||||
|
<?php } ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<small class="text-muted">If you keep a client record for your own company - for internal tickets, documentation, assets and credentials - point it out here. Your company name in the sidebar then links straight to it.</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
<button type="submit" name="edit_company" class="btn btn-primary text-bold"><i class="fas fa-check me-2"></i>Save</button>
|
<button type="submit" name="edit_company" class="btn btn-primary text-bold"><i class="fas fa-check me-2"></i>Save</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,21 @@
|
|||||||
<!-- Main Sidebar Container -->
|
<!-- Main Sidebar Container -->
|
||||||
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
<aside class="app-sidebar shadow d-print-none" data-bs-theme="dark">
|
||||||
|
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* The company name goes to your own company's client record once one is designated in
|
||||||
|
* Admin > Settings > Company Details, and falls back to the dashboard otherwise. The
|
||||||
|
* access check keeps a restricted agent from being sent to a client they would only be
|
||||||
|
* bounced off, and costs no query - the permission arrays are already in the session.
|
||||||
|
*/
|
||||||
|
$brand_link = "/agent/dashboard.php";
|
||||||
|
if (!empty($config_internal_client_id) && lookupUserPermission("module_client") >= 1 && hasClientAccess($config_internal_client_id)) {
|
||||||
|
$brand_link = "/agent/client_overview.php?client_id=" . intval($config_internal_client_id);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
<div class="sidebar-brand">
|
<div class="sidebar-brand">
|
||||||
<a class="brand-link" href="/agent/dashboard.php">
|
<a class="brand-link" href="<?= $brand_link ?>">
|
||||||
<span class="brand-text h4 mb-0"><?= escapeHtml($session_company_name) ?></span>
|
<span class="brand-text h4 mb-0"><?= escapeHtml($session_company_name) ?></span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -348,6 +348,9 @@ if (isset($_GET['delete_client'])) {
|
|||||||
//Finally Remove the Client
|
//Finally Remove the Client
|
||||||
mysqli_query($mysqli, "DELETE FROM clients WHERE client_id = $client_id");
|
mysqli_query($mysqli, "DELETE FROM clients WHERE client_id = $client_id");
|
||||||
|
|
||||||
|
// Don't leave the company's own-client designation pointing at a client that is gone
|
||||||
|
mysqli_query($mysqli, "UPDATE settings SET config_internal_client_id = 0 WHERE config_internal_client_id = $client_id");
|
||||||
|
|
||||||
logAudit("Client", "Deleted", "$session_name deleted Client $client_name and all associated data");
|
logAudit("Client", "Deleted", "$session_name deleted Client $client_name and all associated data");
|
||||||
|
|
||||||
flashAlert("Client <strong>$client_name</strong> deleted along with all associated data", 'error');
|
flashAlert("Client <strong>$client_name</strong> deleted along with all associated data", 'error');
|
||||||
|
|||||||
3
db.sql
3
db.sql
@@ -2327,6 +2327,7 @@ CREATE TABLE `settings` (
|
|||||||
`config_backup_retention_count` int(11) NOT NULL DEFAULT 5,
|
`config_backup_retention_count` int(11) NOT NULL DEFAULT 5,
|
||||||
`config_backup_cron_type` varchar(20) NOT NULL DEFAULT 'full',
|
`config_backup_cron_type` varchar(20) NOT NULL DEFAULT 'full',
|
||||||
`config_update_queued_at` datetime DEFAULT NULL,
|
`config_update_queued_at` datetime DEFAULT NULL,
|
||||||
|
`config_internal_client_id` int(11) NOT NULL DEFAULT 0,
|
||||||
PRIMARY KEY (`company_id`)
|
PRIMARY KEY (`company_id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
@@ -3171,4 +3172,4 @@ CREATE TABLE `vendors` (
|
|||||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||||
|
|
||||||
-- Dump completed on 2026-08-15 19:56:27
|
-- Dump completed on 2026-08-15 20:35:12
|
||||||
|
|||||||
@@ -98,6 +98,36 @@ function clientScopeSql($column) {
|
|||||||
return $sql;
|
return $sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Can this user reach this client? Answers yes or no instead of redirecting, for places
|
||||||
|
* that need to decide whether to render something - enforceClientAccess() below is the
|
||||||
|
* gate that protects the page itself and still has to be called there.
|
||||||
|
*
|
||||||
|
* Reads the permission arrays that includes/load_user_session.php already loaded, so this
|
||||||
|
* costs no query and can be called from the sidebar on every page. The rules match
|
||||||
|
* clientScopeSql() above: a deny wins, an allow list restricts to its members, and no
|
||||||
|
* rules at all means unrestricted.
|
||||||
|
*/
|
||||||
|
function hasClientAccess($client_id) {
|
||||||
|
global $session_is_admin, $client_access_array, $client_deny_array;
|
||||||
|
|
||||||
|
$client_id = intval($client_id);
|
||||||
|
|
||||||
|
if ($session_is_admin) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($client_id, array_map('intval', $client_deny_array))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($client_access_array)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in_array($client_id, array_map('intval', $client_access_array));
|
||||||
|
}
|
||||||
|
|
||||||
function enforceClientAccess($client_id = null) {
|
function enforceClientAccess($client_id = null) {
|
||||||
global $mysqli, $session_user_id, $session_is_admin, $session_name;
|
global $mysqli, $session_user_id, $session_is_admin, $session_name;
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ $sql_settings = mysqli_query($mysqli, "SELECT config_azure_client_id, config_azu
|
|||||||
config_invoice_from_email, config_invoice_from_name, config_invoice_late_fee_enable,
|
config_invoice_from_email, config_invoice_from_name, config_invoice_late_fee_enable,
|
||||||
config_invoice_late_fee_percent, config_invoice_next_number,
|
config_invoice_late_fee_percent, config_invoice_next_number,
|
||||||
config_invoice_paid_notification_email, config_invoice_prefix, config_invoice_show_tax_id,
|
config_invoice_paid_notification_email, config_invoice_prefix, config_invoice_show_tax_id,
|
||||||
|
config_internal_client_id,
|
||||||
config_log_retention, config_login_key_required, config_login_key_secret,
|
config_log_retention, config_login_key_required, config_login_key_secret,
|
||||||
config_login_message, config_login_remember_me_expire, config_mail_from_email,
|
config_login_message, config_login_remember_me_expire, config_mail_from_email,
|
||||||
config_mail_from_name, config_mail_oauth_access_token,
|
config_mail_from_name, config_mail_oauth_access_token,
|
||||||
@@ -136,6 +137,9 @@ $config_module_enable_ticketing = intval($row['config_module_enable_ticketing'])
|
|||||||
$config_module_enable_accounting = intval($row['config_module_enable_accounting']);
|
$config_module_enable_accounting = intval($row['config_module_enable_accounting']);
|
||||||
$config_client_portal_enable = intval($row['config_client_portal_enable']);
|
$config_client_portal_enable = intval($row['config_client_portal_enable']);
|
||||||
|
|
||||||
|
// The client record that represents this MSP's own company, or 0 for none
|
||||||
|
$config_internal_client_id = intval($row['config_internal_client_id']);
|
||||||
|
|
||||||
// Login
|
// Login
|
||||||
$config_login_message = $row['config_login_message'];
|
$config_login_message = $row['config_login_message'];
|
||||||
$config_login_key_required = $row['config_login_key_required'];
|
$config_login_key_required = $row['config_login_key_required'];
|
||||||
|
|||||||
Reference in New Issue
Block a user