fix dashboard table layout
This commit is contained in:
12
app.py
12
app.py
@@ -330,9 +330,8 @@ def init_app():
|
||||
settings.log_level = 'WARNING'
|
||||
db.session.add(settings)
|
||||
|
||||
# Create default admin if not exists
|
||||
admin = User.query.filter_by(email='superadmin@example.com').first()
|
||||
if not admin:
|
||||
# Create default admin only if no users exist in the database
|
||||
if User.query.first() is None:
|
||||
hashed_password = bcrypt.generate_password_hash('adminsuper').decode('utf-8')
|
||||
admin = User(
|
||||
username='superadmin',
|
||||
@@ -347,12 +346,11 @@ def init_app():
|
||||
# Create initial API key for admin
|
||||
api_key = ApiKey(
|
||||
key=ApiKey.generate_key(),
|
||||
description="Initial Admin API Key",
|
||||
user_id=admin.id
|
||||
description="Initial Admin API Key"
|
||||
)
|
||||
db.session.add(api_key)
|
||||
|
||||
db.session.commit()
|
||||
db.session.commit()
|
||||
logger.info("Created initial admin account and API key")
|
||||
|
||||
# Initialize the application
|
||||
init_app()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from flask import Blueprint, render_template, request, redirect, url_for, flash, current_app
|
||||
from flask_login import login_required, current_user
|
||||
from auth.models import User, Company, UserCompany
|
||||
from auth.models import User, Company, UserCompany, ApiKey
|
||||
from api.models import Log
|
||||
from extensions import db
|
||||
from datetime import datetime, timedelta
|
||||
@@ -73,14 +73,21 @@ def dashboard():
|
||||
end_date = datetime.now(app_tz) + timedelta(hours=1) # Include 1 hour in the future
|
||||
start_date = end_date - timedelta(hours=49) # Look back 48 hours from future end time
|
||||
|
||||
# Get company filter if provided
|
||||
# Get companies for the dropdown filter based on user role, ordered by name
|
||||
if current_user.is_global_admin():
|
||||
# GlobalAdmin can see all companies
|
||||
companies = Company.query.order_by(Company.name).all()
|
||||
else:
|
||||
# Get user's companies, ordered by name
|
||||
user_company_ids = [uc.company_id for uc in current_user.companies]
|
||||
companies = Company.query.filter(Company.id.in_(user_company_ids)).order_by(Company.name).all()
|
||||
|
||||
# Get company filter if provided, otherwise use first available company
|
||||
company_id = request.args.get('company_id', type=int)
|
||||
|
||||
# Build base query with date range filter and eagerly load relationships
|
||||
from auth.models import ApiKey, Company
|
||||
|
||||
if not company_id and companies:
|
||||
company_id = companies[0].id # Default to first company
|
||||
|
||||
# Convert timezone-aware dates to naive for comparison with database timestamps
|
||||
# since the log timestamps are stored as naive datetime objects
|
||||
start_date_naive = start_date.replace(tzinfo=None)
|
||||
end_date_naive = end_date.replace(tzinfo=None)
|
||||
|
||||
@@ -90,38 +97,21 @@ def dashboard():
|
||||
db.joinedload(Log.company)
|
||||
).filter(Log.timestamp.between(start_date_naive, end_date_naive))
|
||||
|
||||
# Apply company-specific filtering based on user role
|
||||
# Apply company-specific filtering
|
||||
if current_user.is_global_admin():
|
||||
# GlobalAdmin should be allowed to see all records, no matter what company/site
|
||||
# GlobalAdmin with specific company selected
|
||||
if company_id:
|
||||
query = query.filter(Log.company_id == company_id)
|
||||
# If no company_id specified, show all logs (no additional filtering)
|
||||
else:
|
||||
# CompanyAdmin and User should see only company log events and API Keys (sites)
|
||||
# for companies they are member of
|
||||
# Regular users always need company filtering
|
||||
user_company_ids = [uc.company_id for uc in current_user.companies]
|
||||
|
||||
if not user_company_ids:
|
||||
# If user has no company associations, show no logs
|
||||
query = query.filter(Log.id == -1) # Impossible condition = no results
|
||||
if company_id and company_id in user_company_ids:
|
||||
query = query.filter(Log.company_id == company_id)
|
||||
else:
|
||||
if company_id and company_id in user_company_ids:
|
||||
# Filter by the specific company if requested and user has access
|
||||
query = query.filter(Log.company_id == company_id)
|
||||
else:
|
||||
# Show logs from all companies the user has access to
|
||||
query = query.filter(Log.company_id.in_(user_company_ids))
|
||||
query = query.filter(Log.company_id.in_(user_company_ids))
|
||||
|
||||
# Get the logs ordered by timestamp (newest first)
|
||||
logs = query.order_by(Log.timestamp.desc()).all()
|
||||
|
||||
# Get companies for the dropdown filter based on user role
|
||||
if current_user.is_global_admin():
|
||||
# GlobalAdmin can see all companies
|
||||
companies = Company.query.all()
|
||||
else:
|
||||
# CompanyAdmin and User should see only companies they are member of
|
||||
companies = current_user.get_companies()
|
||||
|
||||
return render_template('frontend/dashboard.html',
|
||||
title='Dashboard',
|
||||
|
||||
@@ -13,7 +13,8 @@ pillow
|
||||
Flask-Migrate
|
||||
|
||||
# serving the application
|
||||
waitress # Production WSGI server for Windows (better than Gunicorn for Windows)
|
||||
#waitress # Production WSGI server for Windows (better than Gunicorn for Windows)
|
||||
redis
|
||||
gunicorn # Production WSGI server (Linux/Unix only - won't work on Windows)
|
||||
#psutil # System monitoring for health checks
|
||||
#click # CLI tools (for database backups)
|
||||
|
||||
@@ -181,11 +181,9 @@
|
||||
<input type="text" id="daterange" name="daterange" class="form-control"
|
||||
value="{{ start_date.strftime('%Y-%m-%d %H:%M') if start_date else '' }} - {{ end_date.strftime('%Y-%m-%d %H:%M') if end_date else '' }}"/>
|
||||
</div>
|
||||
{% if companies %}
|
||||
<div class="col-md-3">
|
||||
<label for="company_id" class="form-label">Company:</label>
|
||||
<select class="form-select" id="company_id" name="company_id">
|
||||
<option value="">All Companies</option>
|
||||
<select class="form-select" id="company_id" name="company_id" required>
|
||||
{% for company in companies %}
|
||||
<option value="{{ company.id }}" {% if selected_company_id == company.id %}selected{% endif %}>
|
||||
{{ company.name }}
|
||||
@@ -193,7 +191,6 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="col-md-2">
|
||||
<button type="submit" class="btn btn-primary">Apply Filter</button>
|
||||
</div>
|
||||
@@ -210,9 +207,7 @@
|
||||
<th>Timestamp</th>
|
||||
<th>Event Type</th>
|
||||
<th>User Name</th>
|
||||
{% if current_user.is_global_admin() and not selected_company_id %}
|
||||
<th>Company</th>
|
||||
{% endif %}
|
||||
<th>Company</th>
|
||||
<th>Site</th>
|
||||
<th>Computer Name</th>
|
||||
<th>Local IP</th>
|
||||
@@ -227,9 +222,7 @@
|
||||
</td>
|
||||
<td>{{ log.event_type }}</td>
|
||||
<td>{{ log.user_name }}</td>
|
||||
{% if current_user.is_global_admin() and not selected_company_id %}
|
||||
<td>{{ log.company.name if log.company else '' }}</td>
|
||||
{% endif %}
|
||||
<td>{{ log.company.name if log.company else '' }}</td>
|
||||
<td>{{ log.api_key.description if log.api_key else '' }}</td>
|
||||
<td>{{ log.computer_name }}</td>
|
||||
<td>{{ log.local_ip or '' }}</td>
|
||||
@@ -317,9 +310,14 @@
|
||||
'<"row"<"col-sm-12 col-md-5"i><"col-sm-12 col-md-7"p>>',
|
||||
columnDefs: [
|
||||
{
|
||||
targets: [5, 6, 7], // Computer Name, Local IP, and Public IP columns are now at indices 5, 6, and 7
|
||||
targets: [5, 6, 7], // Computer Name, Local IP, and Public IP columns
|
||||
visible: false, // Hide by default
|
||||
searchable: true // Still allow searching in these columns
|
||||
},
|
||||
{
|
||||
targets: [3], // Company column
|
||||
visible: {% if current_user.is_global_admin() %}true{% else %}false{% endif %},
|
||||
searchable: {% if current_user.is_global_admin() %}true{% else %}false{% endif %}
|
||||
}
|
||||
],
|
||||
buttons: [
|
||||
@@ -364,11 +362,7 @@
|
||||
});
|
||||
|
||||
// Column names for the visibility controls
|
||||
var columnNames = ['Timestamp', 'Event Type', 'User Name'];
|
||||
{% if current_user.is_global_admin() and not selected_company_id %}
|
||||
columnNames.push('Company');
|
||||
{% endif %}
|
||||
columnNames.push('Site', 'Computer Name', 'Local IP', 'Public IP');
|
||||
var columnNames = ['Timestamp', 'Event Type', 'User Name', 'Company', 'Site', 'Computer Name', 'Local IP', 'Public IP'];
|
||||
|
||||
// Load saved column visibility from localStorage
|
||||
function loadColumnVisibility() {
|
||||
|
||||
@@ -129,7 +129,7 @@ class ConfigManager:
|
||||
|
||||
'logging': {
|
||||
'DB_LOGGING_ENABLED': 'true',
|
||||
'DB_LOGGING_FILTERED_LOGGERS': 'watchfiles.main,watchfiles.watcher,watchdog,uvicorn.access,__mp_main__,__main__,app',
|
||||
'DB_LOGGING_FILTERED_LOGGERS': 'watchfiles.main,watchfiles.watcher,watchdog,uvicorn.access,__mp_main__,__main__,app,werkzeug',
|
||||
'DB_LOGGING_FILTERED_PATTERNS': 'database.db,instance/,file changed,reloading',
|
||||
'FILTER_FILE_WATCHER_LOGS': 'true',
|
||||
'DB_LOGGING_DEDUPE_INTERVAL': '1',
|
||||
|
||||
Reference in New Issue
Block a user