fix: 🐛 invalidate linked cache
This commit is contained in:
@@ -133,6 +133,7 @@ def init_db(app=None):
|
|||||||
FOREIGN KEY (device_id) REFERENCES Device(id) ON DELETE CASCADE
|
FOREIGN KEY (device_id) REFERENCES Device(id) ON DELETE CASCADE
|
||||||
)
|
)
|
||||||
''')
|
''')
|
||||||
|
# Initialize default device types only if table is empty
|
||||||
cursor.execute('SELECT COUNT(*) FROM DeviceType')
|
cursor.execute('SELECT COUNT(*) FROM DeviceType')
|
||||||
if cursor.fetchone()[0] == 0:
|
if cursor.fetchone()[0] == 0:
|
||||||
cursor.executemany('INSERT INTO DeviceType (name, icon_class) VALUES (%s, %s)', [
|
cursor.executemany('INSERT INTO DeviceType (name, icon_class) VALUES (%s, %s)', [
|
||||||
@@ -144,12 +145,20 @@ def init_db(app=None):
|
|||||||
('Printer', 'fa-print'),
|
('Printer', 'fa-print'),
|
||||||
('Other', 'fa-question')
|
('Other', 'fa-question')
|
||||||
])
|
])
|
||||||
|
conn.commit() # Commit the inserts before querying
|
||||||
|
|
||||||
|
# Add device_type_id column if it doesn't exist
|
||||||
cursor.execute("SHOW COLUMNS FROM Device LIKE 'device_type_id'")
|
cursor.execute("SHOW COLUMNS FROM Device LIKE 'device_type_id'")
|
||||||
if not cursor.fetchone():
|
if not cursor.fetchone():
|
||||||
cursor.execute('ALTER TABLE Device ADD COLUMN device_type_id INTEGER DEFAULT NULL')
|
cursor.execute('ALTER TABLE Device ADD COLUMN device_type_id INTEGER DEFAULT NULL')
|
||||||
cursor.execute("SELECT id FROM DeviceType WHERE name='Other'")
|
|
||||||
other_id = cursor.fetchone()[0]
|
# Set default device_type_id for devices that don't have one
|
||||||
cursor.execute('UPDATE Device SET device_type_id = %s WHERE device_type_id IS NULL', (other_id,))
|
# Use the first available device type, or leave NULL if no types exist
|
||||||
|
cursor.execute('SELECT id FROM DeviceType ORDER BY id LIMIT 1')
|
||||||
|
first_type_result = cursor.fetchone()
|
||||||
|
if first_type_result:
|
||||||
|
first_type_id = first_type_result[0]
|
||||||
|
cursor.execute('UPDATE Device SET device_type_id = %s WHERE device_type_id IS NULL', (first_type_id,))
|
||||||
try:
|
try:
|
||||||
cursor.execute('ALTER TABLE Device ADD CONSTRAINT fk_device_type FOREIGN KEY (device_type_id) REFERENCES DeviceType(id)')
|
cursor.execute('ALTER TABLE Device ADD CONSTRAINT fk_device_type FOREIGN KEY (device_type_id) REFERENCES DeviceType(id)')
|
||||||
except mysql.connector.Error as e:
|
except mysql.connector.Error as e:
|
||||||
|
|||||||
@@ -1285,6 +1285,9 @@ def register_routes(app):
|
|||||||
(name, color, description))
|
(name, color, description))
|
||||||
add_audit_log(session['user_id'], 'add_tag', f"Added tag '{name}'", conn=conn)
|
add_audit_log(session['user_id'], 'add_tag', f"Added tag '{name}'", conn=conn)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
# Invalidate device caches since they contain tags
|
||||||
|
cache.clear('device:')
|
||||||
|
cache.clear('devices')
|
||||||
except mysql.connector.IntegrityError:
|
except mysql.connector.IntegrityError:
|
||||||
error = 'Tag name already exists.'
|
error = 'Tag name already exists.'
|
||||||
|
|
||||||
@@ -1305,6 +1308,9 @@ def register_routes(app):
|
|||||||
(name, color, description, tag_id))
|
(name, color, description, tag_id))
|
||||||
add_audit_log(session['user_id'], 'edit_tag', f"Updated tag '{name}'", conn=conn)
|
add_audit_log(session['user_id'], 'edit_tag', f"Updated tag '{name}'", conn=conn)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
# Invalidate device caches since they contain tags
|
||||||
|
cache.clear('device:')
|
||||||
|
cache.clear('devices')
|
||||||
except mysql.connector.IntegrityError:
|
except mysql.connector.IntegrityError:
|
||||||
error = 'Tag name already exists.'
|
error = 'Tag name already exists.'
|
||||||
|
|
||||||
@@ -1318,6 +1324,9 @@ def register_routes(app):
|
|||||||
cursor.execute('DELETE FROM Tag WHERE id = %s', (tag_id,))
|
cursor.execute('DELETE FROM Tag WHERE id = %s', (tag_id,))
|
||||||
add_audit_log(session['user_id'], 'delete_tag', f"Deleted tag '{tag_name}'", conn=conn)
|
add_audit_log(session['user_id'], 'delete_tag', f"Deleted tag '{tag_name}'", conn=conn)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
# Invalidate device caches since they contain tags
|
||||||
|
cache.clear('device:')
|
||||||
|
cache.clear('devices')
|
||||||
|
|
||||||
# Get all tags with device counts
|
# Get all tags with device counts
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
@@ -1890,6 +1899,10 @@ def register_routes(app):
|
|||||||
conn.commit()
|
conn.commit()
|
||||||
dhcp_pool = None
|
dhcp_pool = None
|
||||||
add_audit_log(session['user_id'], 'dhcp_pool_remove', f"Removed DHCP pool for subnet {subnet[1]} ({subnet[2]})", subnet_id, conn=conn)
|
add_audit_log(session['user_id'], 'dhcp_pool_remove', f"Removed DHCP pool for subnet {subnet[1]} ({subnet[2]})", subnet_id, conn=conn)
|
||||||
|
# Invalidate subnet cache and related caches
|
||||||
|
cache.invalidate_subnet(subnet_id)
|
||||||
|
cache.clear('index')
|
||||||
|
cache.clear('admin')
|
||||||
else:
|
else:
|
||||||
start_ip = request.form['start_ip']
|
start_ip = request.form['start_ip']
|
||||||
end_ip = request.form['end_ip']
|
end_ip = request.form['end_ip']
|
||||||
@@ -1920,6 +1933,10 @@ def register_routes(app):
|
|||||||
conn.commit()
|
conn.commit()
|
||||||
dhcp_pool = {'start_ip': start_ip, 'end_ip': end_ip, 'excluded_ips': excluded_ips}
|
dhcp_pool = {'start_ip': start_ip, 'end_ip': end_ip, 'excluded_ips': excluded_ips}
|
||||||
add_audit_log(session['user_id'], action, details, subnet_id, conn=conn)
|
add_audit_log(session['user_id'], action, details, subnet_id, conn=conn)
|
||||||
|
# Invalidate subnet cache and related caches
|
||||||
|
cache.invalidate_subnet(subnet_id)
|
||||||
|
cache.clear('index')
|
||||||
|
cache.clear('admin')
|
||||||
return render_with_user('dhcp.html', subnet={'id': subnet[0], 'name': subnet[1]}, dhcp_pool=dhcp_pool, error=error)
|
return render_with_user('dhcp.html', subnet={'id': subnet[0], 'name': subnet[1]}, dhcp_pool=dhcp_pool, error=error)
|
||||||
|
|
||||||
@app.route('/device_type_stats')
|
@app.route('/device_type_stats')
|
||||||
@@ -3117,6 +3134,10 @@ def register_routes(app):
|
|||||||
conn=conn
|
conn=conn
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
# Invalidate subnet cache and related caches
|
||||||
|
cache.invalidate_subnet(subnet_id)
|
||||||
|
cache.clear('index')
|
||||||
|
cache.clear('admin')
|
||||||
return jsonify({'message': 'DHCP pool removed successfully'})
|
return jsonify({'message': 'DHCP pool removed successfully'})
|
||||||
|
|
||||||
pools = data.get('pools')
|
pools = data.get('pools')
|
||||||
@@ -3167,6 +3188,10 @@ def register_routes(app):
|
|||||||
|
|
||||||
add_audit_log(request.api_user['id'], action, details, subnet_id, conn=conn)
|
add_audit_log(request.api_user['id'], action, details, subnet_id, conn=conn)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
# Invalidate subnet cache and related caches
|
||||||
|
cache.invalidate_subnet(subnet_id)
|
||||||
|
cache.clear('index')
|
||||||
|
cache.clear('admin')
|
||||||
return jsonify({'message': 'DHCP pools configured successfully', 'pool': {'start_ip': start_ip, 'end_ip': end_ip, 'excluded_ips': excluded_list}})
|
return jsonify({'message': 'DHCP pools configured successfully', 'pool': {'start_ip': start_ip, 'end_ip': end_ip, 'excluded_ips': excluded_list}})
|
||||||
|
|
||||||
# Tags API
|
# Tags API
|
||||||
@@ -3207,6 +3232,9 @@ def register_routes(app):
|
|||||||
tag_id = cursor.lastrowid
|
tag_id = cursor.lastrowid
|
||||||
add_audit_log(request.api_user['id'], 'add_tag', f"Added tag '{name}'", conn=conn)
|
add_audit_log(request.api_user['id'], 'add_tag', f"Added tag '{name}'", conn=conn)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
# Invalidate device caches since they contain tags
|
||||||
|
cache.clear('device:')
|
||||||
|
cache.clear('devices')
|
||||||
return jsonify({'id': tag_id, 'name': name, 'color': color, 'description': description}), 201
|
return jsonify({'id': tag_id, 'name': name, 'color': color, 'description': description}), 201
|
||||||
except mysql.connector.IntegrityError:
|
except mysql.connector.IntegrityError:
|
||||||
return jsonify({'error': 'Tag name already exists'}), 400
|
return jsonify({'error': 'Tag name already exists'}), 400
|
||||||
@@ -3276,6 +3304,9 @@ def register_routes(app):
|
|||||||
cursor.execute(f'UPDATE Tag SET {", ".join(updates)} WHERE id = %s', values)
|
cursor.execute(f'UPDATE Tag SET {", ".join(updates)} WHERE id = %s', values)
|
||||||
add_audit_log(request.api_user['id'], 'edit_tag', f"Updated tag '{current_name}'", conn=conn)
|
add_audit_log(request.api_user['id'], 'edit_tag', f"Updated tag '{current_name}'", conn=conn)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
# Invalidate device caches since they contain tags
|
||||||
|
cache.clear('device:')
|
||||||
|
cache.clear('devices')
|
||||||
return jsonify({'message': 'Tag updated successfully'})
|
return jsonify({'message': 'Tag updated successfully'})
|
||||||
except mysql.connector.IntegrityError:
|
except mysql.connector.IntegrityError:
|
||||||
return jsonify({'error': 'Tag name already exists'}), 400
|
return jsonify({'error': 'Tag name already exists'}), 400
|
||||||
@@ -3295,6 +3326,9 @@ def register_routes(app):
|
|||||||
cursor.execute('DELETE FROM Tag WHERE id = %s', (tag_id,))
|
cursor.execute('DELETE FROM Tag WHERE id = %s', (tag_id,))
|
||||||
add_audit_log(request.api_user['id'], 'delete_tag', f"Deleted tag '{tag_name}'", conn=conn)
|
add_audit_log(request.api_user['id'], 'delete_tag', f"Deleted tag '{tag_name}'", conn=conn)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
# Invalidate device caches since they contain tags
|
||||||
|
cache.clear('device:')
|
||||||
|
cache.clear('devices')
|
||||||
return jsonify({'message': 'Tag deleted successfully'})
|
return jsonify({'message': 'Tag deleted successfully'})
|
||||||
|
|
||||||
@app.route('/api/v1/devices/<int:device_id>/tags', methods=['GET'])
|
@app.route('/api/v1/devices/<int:device_id>/tags', methods=['GET'])
|
||||||
@@ -3348,6 +3382,8 @@ def register_routes(app):
|
|||||||
cursor.execute('INSERT INTO DeviceTag (device_id, tag_id) VALUES (%s, %s)', (device_id, tag_id))
|
cursor.execute('INSERT INTO DeviceTag (device_id, tag_id) VALUES (%s, %s)', (device_id, tag_id))
|
||||||
add_audit_log(request.api_user['id'], 'assign_device_tag', f"Assigned tag '{tag_name}' to device '{device_name}'", conn=conn)
|
add_audit_log(request.api_user['id'], 'assign_device_tag', f"Assigned tag '{tag_name}' to device '{device_name}'", conn=conn)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
invalidate_cache_for_device(device_id)
|
||||||
|
cache.clear('devices')
|
||||||
return jsonify({'message': 'Tag assigned successfully'})
|
return jsonify({'message': 'Tag assigned successfully'})
|
||||||
|
|
||||||
@app.route('/api/v1/devices/<int:device_id>/tags/<int:tag_id>', methods=['DELETE'])
|
@app.route('/api/v1/devices/<int:device_id>/tags/<int:tag_id>', methods=['DELETE'])
|
||||||
@@ -3376,6 +3412,8 @@ def register_routes(app):
|
|||||||
cursor.execute('DELETE FROM DeviceTag WHERE device_id = %s AND tag_id = %s', (device_id, tag_id))
|
cursor.execute('DELETE FROM DeviceTag WHERE device_id = %s AND tag_id = %s', (device_id, tag_id))
|
||||||
add_audit_log(request.api_user['id'], 'remove_device_tag', f"Removed tag '{tag_name}' from device '{device_name}'", conn=conn)
|
add_audit_log(request.api_user['id'], 'remove_device_tag', f"Removed tag '{tag_name}' from device '{device_name}'", conn=conn)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
invalidate_cache_for_device(device_id)
|
||||||
|
cache.clear('devices')
|
||||||
return jsonify({'message': 'Tag removed successfully'})
|
return jsonify({'message': 'Tag removed successfully'})
|
||||||
|
|
||||||
@app.route('/api/v1/devices/by-tag/<tag_identifier>', methods=['GET'])
|
@app.route('/api/v1/devices/by-tag/<tag_identifier>', methods=['GET'])
|
||||||
@@ -3599,6 +3637,7 @@ def register_routes(app):
|
|||||||
results = {'success': [], 'failed': []}
|
results = {'success': [], 'failed': []}
|
||||||
|
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
subnet_ids_to_invalidate = set()
|
||||||
with get_db_connection(current_app) as conn:
|
with get_db_connection(current_app) as conn:
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute('SELECT name FROM Device WHERE id = %s', (device_id,))
|
cursor.execute('SELECT name FROM Device WHERE id = %s', (device_id,))
|
||||||
@@ -3617,6 +3656,7 @@ def register_routes(app):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
ip, subnet_id = ip_row[0], ip_row[1]
|
ip, subnet_id = ip_row[0], ip_row[1]
|
||||||
|
subnet_ids_to_invalidate.add(subnet_id)
|
||||||
|
|
||||||
# Check if IP is already assigned
|
# Check if IP is already assigned
|
||||||
cursor.execute('SELECT id FROM DeviceIPAddress WHERE ip_id = %s', (ip_id,))
|
cursor.execute('SELECT id FROM DeviceIPAddress WHERE ip_id = %s', (ip_id,))
|
||||||
@@ -3661,6 +3701,10 @@ def register_routes(app):
|
|||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
# Invalidate device and subnet caches
|
||||||
|
invalidate_cache_for_device(device_id)
|
||||||
|
for subnet_id in subnet_ids_to_invalidate:
|
||||||
|
cache.invalidate_subnet(subnet_id)
|
||||||
return jsonify(results)
|
return jsonify(results)
|
||||||
|
|
||||||
@app.route('/bulk/create_devices', methods=['POST'])
|
@app.route('/bulk/create_devices', methods=['POST'])
|
||||||
@@ -3687,6 +3731,9 @@ def register_routes(app):
|
|||||||
results['failed'].append({'name': name, 'reason': str(e)})
|
results['failed'].append({'name': name, 'reason': str(e)})
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
# Invalidate devices cache
|
||||||
|
cache.clear('devices')
|
||||||
|
cache.clear('device_list')
|
||||||
logging.info(f"User {user_name} bulk created {len(results['success'])} devices.")
|
logging.info(f"User {user_name} bulk created {len(results['success'])} devices.")
|
||||||
return jsonify(results)
|
return jsonify(results)
|
||||||
|
|
||||||
@@ -3729,6 +3776,10 @@ def register_routes(app):
|
|||||||
results['failed'].append({'device_id': device_id, 'tag_id': tag_id, 'reason': str(e)})
|
results['failed'].append({'device_id': device_id, 'tag_id': tag_id, 'reason': str(e)})
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
# Invalidate device caches for all affected devices
|
||||||
|
for device_id in device_ids:
|
||||||
|
invalidate_cache_for_device(device_id)
|
||||||
|
cache.clear('devices')
|
||||||
logging.info(f"User {user_name} bulk assigned tags to {len(device_ids)} devices.")
|
logging.info(f"User {user_name} bulk assigned tags to {len(device_ids)} devices.")
|
||||||
return jsonify(results)
|
return jsonify(results)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user