Files
UNITRONIX c2aedb10fe Enhance security and input validation across CDAP and organization routes
- Implemented input validation for `orgId` and `deviceId` in CDAP and organization detail routes using `assertSafeApiId`, returning a 400 error for invalid inputs.
- Added HTML escaping for `deviceId` and `orgId` in views to prevent XSS vulnerabilities.
- Hardened `patch-role-scope-i18n.js` against prototype pollution with a guard for unsafe nested keys.
- Updated CodeQL configuration to include new exclusions and ensure documented exclusions are applied.
2026-07-09 21:16:55 +02:00

118 lines
6.3 KiB
HTML

<%- include('layouts/main', {
title: _('organizations.detail') || 'Organization Details',
pageStyles: ['organizations'],
pageScripts: ['organizationDetail'],
currentPage: 'organizations',
breadcrumb: [
{ label: _('nav.organizations') || 'Organizations', href: '/organizations' },
{ label: _('organizations.detail') || 'Details' }
],
body: `
<div class="org-detail-page" data-org-id="${escapeHtml(orgId)}">
<!-- Header -->
<div class="org-detail-header" id="org-detail-header">
<div class="org-detail-info">
<h1 id="org-detail-name">Loading...</h1>
<span class="org-detail-slug" id="org-detail-slug"></span>
</div>
<div class="org-detail-actions">
<button class="btn btn-secondary btn-sm" id="org-edit-btn">
<span class="material-icons">edit</span> ${_('common.edit') || 'Edit'}
</button>
<button class="btn btn-danger btn-sm" id="org-delete-btn">
<span class="material-icons">delete</span> ${_('common.delete') || 'Delete'}
</button>
</div>
</div>
<!-- Tabs -->
<div class="org-tabs">
<button class="org-tab active" data-tab="users">
<span class="material-icons">group</span> ${_('organizations.users') || 'Users'}
<span class="tab-count" id="users-count">0</span>
</button>
<button class="org-tab" data-tab="devices">
<span class="material-icons">devices</span> ${_('organizations.devices') || 'Devices'}
<span class="tab-count" id="devices-count">0</span>
</button>
<button class="org-tab" data-tab="invitations">
<span class="material-icons">mail</span> ${_('organizations.invitations') || 'Invitations'}
<span class="tab-count" id="invitations-count">0</span>
</button>
<button class="org-tab" data-tab="settings">
<span class="material-icons">settings</span> ${_('organizations.settings') || 'Settings'}
</button>
<button class="org-tab" data-tab="address-book">
<span class="material-icons">contacts</span> ${_('organizations.address_book') || 'Address Book'}
</button>
<button class="org-tab" data-tab="device-groups">
<span class="material-icons">workspaces</span> ${_('organizations.device_groups_tab') || 'Device Groups'}
</button>
</div>
<!-- Tab content -->
<div class="org-tab-content" id="tab-users">
<div class="org-section-header">
<h2>${_('organizations.users') || 'Users'}</h2>
<button class="btn btn-primary btn-sm" id="add-user-btn">
<span class="material-icons">person_add</span> ${_('organizations.add_user') || 'Add User'}
</button>
</div>
<div class="org-table-container" id="users-table"></div>
</div>
<div class="org-tab-content" id="tab-devices" style="display:none;">
<div class="org-section-header">
<h2>${_('organizations.devices') || 'Devices'}</h2>
<button class="btn btn-primary btn-sm" id="assign-device-btn">
<span class="material-icons">add_circle</span> ${_('organizations.assign_device') || 'Assign Device'}
</button>
</div>
<div class="org-table-container" id="devices-table"></div>
</div>
<div class="org-tab-content" id="tab-invitations" style="display:none;">
<div class="org-section-header">
<h2>${_('organizations.invitations') || 'Invitations'}</h2>
<button class="btn btn-primary btn-sm" id="create-invite-btn">
<span class="material-icons">link</span> ${_('organizations.create_invitation') || 'Create Invitation'}
</button>
</div>
<div class="org-table-container" id="invitations-table"></div>
</div>
<div class="org-tab-content" id="tab-settings" style="display:none;">
<div class="org-section-header">
<h2>${_('organizations.settings') || 'Settings'}</h2>
</div>
<div class="org-settings-container" id="settings-container"></div>
</div>
<div class="org-tab-content" id="tab-address-book" style="display:none;">
<div class="org-section-header">
<h2>${_('organizations.address_book') || 'Address Book'}</h2>
<div class="org-section-actions">
<button class="btn btn-secondary btn-sm" id="import-org-devices-btn">
<span class="material-icons">playlist_add</span> ${_('organizations.address_book_import_devices') || 'Import org devices'}
</button>
<button class="btn btn-primary btn-sm" id="save-address-book-btn">
<span class="material-icons">save</span> ${_('organizations.address_book_save') || 'Save address book'}
</button>
</div>
</div>
<div class="org-address-book-container" id="address-book-container"></div>
</div>
<div class="org-tab-content" id="tab-device-groups" style="display:none;">
<div class="org-section-header">
<h2>${_('organizations.device_groups_tab') || 'Device Groups'}</h2>
<a href="/devices" class="btn btn-secondary btn-sm" id="org-open-devices-groups-btn">
<span class="material-icons">open_in_new</span> ${_('organizations.manage_in_devices') || 'Open Devices → Groups'}
</a>
</div>
<div class="org-settings-container" id="device-groups-container"></div>
</div>
</div>
`
}) %>