zm.conf and conf.d are set by the system owner and win over the Config
table in PHP, Perl and, since 4d7609d36, the daemons. The Options page
still offered those options for editing and showed the database value,
with a note only when the two differed.
An option a file sets is now shown with the value in effect (a boolean
word read as in configFileValue()), its input disabled, and one line
naming the file ('OptionSetInConfigFile', through translate()). That
line replaces the old "overriden via configuration files" note. A row
whose option a file sets gets no data-requires, so the page script
doesn't enable its input again, and the Requires check of other options
reads the value in effect.
actions/options.php skips options a file sets. A disabled checkbox is
left out of the form, and the action saved a missing boolean as 0, so
without the skip a save of the tab would have reset the Config row; a
hand-made POST can't change it either. The Config row keeps whatever the
admin last saved, which applies again once the file line is removed.
loadConfigFiles() is split out of loadConfig() so the view and the
action can tell which names come from a file and which file. Each entry
carries that file; loadConfig() drops the key before returning, so
configs/viewByName answers as before.
docs/userguide/configfiles.rst describes setting an option in a file.
Add three Options tabs (AI Datasets, AI Models, AI Classes) with full
CRUD, backed by the AI_* tables:
- List views (_options_ai_{datasets,models,classes}.php), edit modals
(ajax/modals/ai_{dataset,model,class}.php) and action handlers
(actions/ai_{dataset,model,class}.php).
- options.js loads the modals over ajax, wires the Add/edit buttons and
the AI Classes dataset filter.
- options.php dispatches the new tab includes; functions.php registers
the three tabs in the Options sub-menu with readable labels (they are
not Config categories, so they need explicit entries).
- actions/options.php routes object=ai_* deletes to the matching
handler; saves post directly to view=ai_*.
All tabs and actions are gated on System permission.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Port the menu customization work from the ai_server branch onto master:
- Add/edit/delete custom navbar/sidebar menu entries via Options > Menu
- Per-entry Link column (new Menu_Items.Link) with ?view= fallback derived
the same way as built-in items; custom entries render via buildMenuItem
- Live icon preview (material/font awesome) with fixed-width preview cell
- Per-row delete icon; add/reset buttons with tooltips
- Surface DB errors when saving options config: capture the swallowed PDO
error via dbLastError() and show it in the page error banner instead of
redirecting past it
Menu_Items.Link is added to zm_create.sql.in and as an idempotent ALTER in
zm_update-1.39.16.sql.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the file upload input with a text input for image icon type,
accepting a URL path relative to the web root. Remove multipart form
encoding, file upload handling, and uploaded file cleanup on reset.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add 'none' as icon type option to hide icons on individual menu items
- Display custom icons in top navbar to match left sidebar appearance
- Fix console table Columns dropdown showing raw HTML by moving icon/link
rendering to JS post-init (bootstrap-table captures th innerHTML for
dropdown labels, so icons must be injected after initialization)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Icon and IconType columns to Menu_Items table allowing admins to
override the default material icon for each menu entry. Supports three
icon types: Material Icons, Font Awesome 4.7 classes, and uploaded
image files (stored in graphics/menu/).
Add renderMenuIcon() helper and $menuIconOverride global to pass
custom icons through to buildMenuItem() and getOptionsHTML() without
changing every get*HTML() function signature.
Options > Menu tab now shows icon preview, type selector, and
text/file input per row. Upload handler validates file type and
cleans up old images on change or reset.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Menu_Items table to store per-item enabled state, custom labels,
and sort order. Admins can enable/disable menu items, set custom
labels, and reorder via drag-and-drop in Options > Menu tab.
Refactor hardcoded get*HTML() calls in buildSidebarMenu(),
getNormalNavBarHTML(), and getCollapsedNavBarHTML() to data-driven
renderMenuItems() that reads from DB with fallback for empty table.
Remove deprecated Cycle view from menu (functionality merged into
Watch view). Add reset button to restore default menu configuration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a new AUDIT logging level (-5) between PANIC (-4) and NOLOG (shifted
to -6) across C++, PHP, and Perl loggers. AUDIT entries use code 'AUD'
and syslog priority LOG_NOTICE. They record who changed what, from where,
for monitors, filters, users, config, roles, groups, zones, states,
servers, storage, events, snapshots, control caps, and login/logout.
AUDIT entries have their own retention period (ZM_LOG_AUDIT_DATABASE_LIMIT,
default 1 year) separate from regular log pruning. The log pruning in
zmstats.pl and zmaudit.pl now excludes AUDIT rows from regular pruning
and prunes them independently.
Critical safety: the C++ termination logic is changed from
'if (level <= FATAL)' to 'if (level == FATAL || level == PANIC)' to
prevent AUDIT-level log calls from killing the process.
Includes db migration zm_update-1.39.1.sql to shift any stored NOLOG
config values from -5 to -6.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a User Roles system where roles define reusable permission templates.
When a user has a role assigned, the role provides fallback permissions
(user's direct permissions take precedence; role is used when user has 'None').
Database changes:
- Add User_Roles table with same permission fields as Users
- Add Role_Groups_Permissions table for per-role group overrides
- Add Role_Monitors_Permissions table for per-role monitor overrides
- Add RoleId foreign key to Users table
Permission resolution order:
1. User's direct Monitor/Group permissions (if not 'Inherit')
2. Role's Monitor/Group permissions (if user has role)
3. Role's base permission (if user's is 'None')
4. User's base permission (fallback)
Includes:
- PHP models: User_Role, Role_Group_Permission, Role_Monitor_Permission
- Role management UI in Options > Roles tab
- Role selector in user edit form
- REST API endpoints for roles CRUD
- Translation strings for en_gb
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* experiment with namespaces on the Server class
* experiment with namespaces on the Server class
* Implement the ZM namespace on objects
* Implement the ZM namespace on objects
* Implement the ZM namespace on objects