feat: custom fields by device or subnet

This commit is contained in:
2025-12-27 22:07:49 +00:00
parent 53dc19a549
commit b23cda48af
11 changed files with 1786 additions and 26 deletions
+45 -2
View File
@@ -299,6 +299,39 @@ def init_db(app=None):
)
''')
# Create CustomFieldDefinition table
cursor.execute('''
CREATE TABLE IF NOT EXISTS CustomFieldDefinition (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
entity_type ENUM('device', 'subnet') NOT NULL,
name VARCHAR(255) NOT NULL,
field_key VARCHAR(255) NOT NULL UNIQUE,
field_type VARCHAR(50) NOT NULL,
required BOOLEAN DEFAULT FALSE,
default_value TEXT,
help_text TEXT,
display_order INTEGER DEFAULT 0,
validation_rules TEXT,
searchable BOOLEAN DEFAULT FALSE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
''')
# Add custom_fields column to Device table if it doesn't exist
cursor.execute("SHOW COLUMNS FROM Device LIKE 'custom_fields'")
if not cursor.fetchone():
cursor.execute('ALTER TABLE Device ADD COLUMN custom_fields TEXT DEFAULT NULL')
# Initialize existing records with empty JSON object
cursor.execute("UPDATE Device SET custom_fields = '{}' WHERE custom_fields IS NULL")
# Add custom_fields column to Subnet table if it doesn't exist
cursor.execute("SHOW COLUMNS FROM Subnet LIKE 'custom_fields'")
if not cursor.fetchone():
cursor.execute('ALTER TABLE Subnet ADD COLUMN custom_fields TEXT DEFAULT NULL')
# Initialize existing records with empty JSON object
cursor.execute("UPDATE Subnet SET custom_fields = '{}' WHERE custom_fields IS NULL")
# Define all permissions with categories
permissions = [
# View permissions
@@ -354,6 +387,10 @@ def init_db(app=None):
('assign_device_tag', 'Assign tag to device', 'Tag'),
('remove_device_tag', 'Remove tag from device', 'Tag'),
# Custom Fields permissions
('view_custom_fields', 'View custom fields', 'Custom Fields'),
('manage_custom_fields', 'Manage custom fields (add, edit, delete)', 'Custom Fields'),
# Admin permissions
('manage_users', 'Manage users (add, edit, delete)', 'Admin'),
('manage_roles', 'Manage roles and permissions', 'Admin'),
@@ -415,7 +452,8 @@ def init_db(app=None):
'add_nonnet_device_to_rack', 'export_rack_csv',
'configure_dhcp',
'add_device_type', 'edit_device_type', 'delete_device_type',
'view_tags', 'add_tag', 'edit_tag', 'delete_tag', 'assign_device_tag', 'remove_device_tag'
'view_tags', 'add_tag', 'edit_tag', 'delete_tag', 'assign_device_tag', 'remove_device_tag',
'view_custom_fields', 'manage_custom_fields'
]
for perm_name in non_admin_permissions:
@@ -434,7 +472,7 @@ def init_db(app=None):
view_only_permissions = [
'view_index', 'view_devices', 'view_device', 'view_subnet', 'view_racks', 'view_rack',
'view_audit', 'view_device_types', 'view_device_type_stats', 'view_devices_by_type',
'view_dhcp', 'view_help', 'view_tags'
'view_dhcp', 'view_help', 'view_tags', 'view_custom_fields'
]
for perm_name in view_only_permissions:
@@ -527,6 +565,11 @@ def init_db(app=None):
# User table indexes (api_key already has UNIQUE index)
create_index_if_not_exists(cursor, 'idx_user_role_id', 'User', 'role_id')
# CustomFieldDefinition table indexes
create_index_if_not_exists(cursor, 'idx_customfield_entity_type', 'CustomFieldDefinition', 'entity_type')
create_index_if_not_exists(cursor, 'idx_customfield_field_key', 'CustomFieldDefinition', 'field_key')
create_index_if_not_exists(cursor, 'idx_customfield_entity_order', 'CustomFieldDefinition', 'entity_type, display_order')
logging.info("Database indexes created successfully")
conn.commit()
conn.close()