refactor: Move audit dashboard routes to blueprints/audit
- Create new audit blueprint for user-facing audit dashboards - Move /audit/seo/<slug>, /audit/social/<slug>, /audit/gbp/<slug>, /audit/it/<slug> - Add endpoint aliases for backward compatibility - app.py: 5860 → 5520 lines (-340) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
b505427355
commit
94dd5327bc
344
app.py
344
app.py
@ -1248,350 +1248,10 @@ def api_connections():
|
||||
|
||||
|
||||
# ============================================================
|
||||
# SEO AUDIT USER-FACING DASHBOARD
|
||||
# AUDIT DASHBOARDS - MOVED TO: blueprints/audit/routes.py
|
||||
# Routes: /audit/seo/<slug>, /audit/social/<slug>, /audit/gbp/<slug>, /audit/it/<slug>
|
||||
# ============================================================
|
||||
|
||||
@app.route('/audit/seo/<slug>')
|
||||
@login_required
|
||||
def seo_audit_dashboard(slug):
|
||||
"""
|
||||
User-facing SEO audit dashboard for a specific company.
|
||||
|
||||
Displays SEO audit results with:
|
||||
- PageSpeed Insights scores (SEO, Performance, Accessibility, Best Practices)
|
||||
- Website analysis data
|
||||
- Improvement recommendations
|
||||
|
||||
Access control:
|
||||
- Admin users can view audit for any company
|
||||
- Regular users can only view audit for their own company
|
||||
|
||||
Args:
|
||||
slug: Company slug identifier
|
||||
|
||||
Returns:
|
||||
Rendered seo_audit.html template with company and audit data
|
||||
"""
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# Find company by slug
|
||||
company = db.query(Company).filter_by(slug=slug, status='active').first()
|
||||
|
||||
if not company:
|
||||
flash('Firma nie została znaleziona.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Access control: admin can view any company, member only their own
|
||||
if not current_user.is_admin:
|
||||
if current_user.company_id != company.id:
|
||||
flash('Brak uprawnień. Możesz przeglądać audyt tylko własnej firmy.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Get latest SEO analysis for this company
|
||||
analysis = db.query(CompanyWebsiteAnalysis).filter(
|
||||
CompanyWebsiteAnalysis.company_id == company.id
|
||||
).order_by(CompanyWebsiteAnalysis.seo_audited_at.desc()).first()
|
||||
|
||||
# Build SEO data dict if analysis exists
|
||||
seo_data = None
|
||||
if analysis and analysis.seo_audited_at:
|
||||
seo_data = {
|
||||
'seo_score': analysis.pagespeed_seo_score,
|
||||
'performance_score': analysis.pagespeed_performance_score,
|
||||
'accessibility_score': analysis.pagespeed_accessibility_score,
|
||||
'best_practices_score': analysis.pagespeed_best_practices_score,
|
||||
'audited_at': analysis.seo_audited_at,
|
||||
'audit_version': analysis.seo_audit_version,
|
||||
'url': analysis.website_url
|
||||
}
|
||||
|
||||
# Determine if user can run audit (admin or company owner)
|
||||
can_audit = current_user.is_admin or current_user.company_id == company.id
|
||||
|
||||
logger.info(f"SEO audit dashboard viewed by {current_user.email} for company: {company.name}")
|
||||
|
||||
return render_template('seo_audit.html',
|
||||
company=company,
|
||||
seo_data=seo_data,
|
||||
can_audit=can_audit
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# SOCIAL MEDIA AUDIT USER-FACING DASHBOARD
|
||||
# ============================================================
|
||||
|
||||
@app.route('/audit/social/<slug>')
|
||||
@login_required
|
||||
def social_audit_dashboard(slug):
|
||||
"""
|
||||
User-facing Social Media audit dashboard for a specific company.
|
||||
|
||||
Displays social media presence audit with:
|
||||
- Overall presence score (platforms found / total platforms)
|
||||
- Platform-by-platform status
|
||||
- Profile validation status
|
||||
- Recommendations for missing platforms
|
||||
|
||||
Access control:
|
||||
- Admins: Can view all companies
|
||||
- Regular users: Can only view their own company
|
||||
|
||||
Args:
|
||||
slug: Company URL slug
|
||||
|
||||
Returns:
|
||||
Rendered social_audit.html template with company and social data
|
||||
"""
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# Find company by slug
|
||||
company = db.query(Company).filter_by(slug=slug, status='active').first()
|
||||
if not company:
|
||||
flash('Firma nie została znaleziona.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Access control - admin can view all, users only their company
|
||||
if not current_user.is_admin:
|
||||
if current_user.company_id != company.id:
|
||||
flash('Brak uprawnień do wyświetlenia audytu social media tej firmy.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Get social media profiles for this company
|
||||
social_profiles = db.query(CompanySocialMedia).filter(
|
||||
CompanySocialMedia.company_id == company.id
|
||||
).all()
|
||||
|
||||
# Define all platforms we track
|
||||
all_platforms = ['facebook', 'instagram', 'linkedin', 'youtube', 'twitter', 'tiktok']
|
||||
|
||||
# Build social media data
|
||||
profiles_dict = {}
|
||||
for profile in social_profiles:
|
||||
profiles_dict[profile.platform] = {
|
||||
'url': profile.url,
|
||||
'is_valid': profile.is_valid,
|
||||
'check_status': profile.check_status,
|
||||
'page_name': profile.page_name,
|
||||
'followers_count': profile.followers_count,
|
||||
'verified_at': profile.verified_at,
|
||||
'last_checked_at': profile.last_checked_at
|
||||
}
|
||||
|
||||
# Calculate score (platforms with profiles / total platforms)
|
||||
platforms_with_profiles = len([p for p in all_platforms if p in profiles_dict])
|
||||
total_platforms = len(all_platforms)
|
||||
score = int((platforms_with_profiles / total_platforms) * 100) if total_platforms > 0 else 0
|
||||
|
||||
social_data = {
|
||||
'profiles': profiles_dict,
|
||||
'all_platforms': all_platforms,
|
||||
'platforms_count': platforms_with_profiles,
|
||||
'total_platforms': total_platforms,
|
||||
'score': score
|
||||
}
|
||||
|
||||
# Determine if user can run audit (admin or company owner)
|
||||
can_audit = current_user.is_admin or current_user.company_id == company.id
|
||||
|
||||
logger.info(f"Social Media audit dashboard viewed by {current_user.email} for company: {company.name}")
|
||||
|
||||
return render_template('social_audit.html',
|
||||
company=company,
|
||||
social_data=social_data,
|
||||
can_audit=can_audit
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# SOCIAL AUDIT API - MOVED TO: blueprints/api/routes_social_audit.py
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# GBP AUDIT USER-FACING DASHBOARD
|
||||
# ============================================================
|
||||
|
||||
@app.route('/audit/gbp/<slug>')
|
||||
@login_required
|
||||
def gbp_audit_dashboard(slug):
|
||||
"""
|
||||
User-facing GBP audit dashboard for a specific company.
|
||||
|
||||
Displays Google Business Profile completeness audit results with:
|
||||
- Overall completeness score (0-100)
|
||||
- Field-by-field status breakdown
|
||||
- AI-generated improvement recommendations
|
||||
- Historical audit data
|
||||
|
||||
Access control:
|
||||
- Admin users can view audit for any company
|
||||
- Regular users can only view audit for their own company
|
||||
|
||||
Args:
|
||||
slug: Company slug identifier
|
||||
|
||||
Returns:
|
||||
Rendered gbp_audit.html template with company and audit data
|
||||
"""
|
||||
if not GBP_AUDIT_AVAILABLE:
|
||||
flash('Usługa audytu Google Business Profile jest tymczasowo niedostępna.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# Find company by slug
|
||||
company = db.query(Company).filter_by(slug=slug, status='active').first()
|
||||
|
||||
if not company:
|
||||
flash('Firma nie została znaleziona.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Access control: admin can view any company, member only their own
|
||||
if not current_user.is_admin:
|
||||
if current_user.company_id != company.id:
|
||||
flash('Brak uprawnień. Możesz przeglądać audyt tylko własnej firmy.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Get latest audit for this company
|
||||
audit = gbp_get_company_audit(db, company.id)
|
||||
|
||||
# If no audit exists, we still render the page (template handles this)
|
||||
# The user can trigger an audit from the dashboard
|
||||
|
||||
# Determine if user can run audit (admin or company owner)
|
||||
can_audit = current_user.is_admin or current_user.company_id == company.id
|
||||
|
||||
logger.info(f"GBP audit dashboard viewed by {current_user.email} for company: {company.name}")
|
||||
|
||||
return render_template('gbp_audit.html',
|
||||
company=company,
|
||||
audit=audit,
|
||||
can_audit=can_audit,
|
||||
gbp_audit_available=GBP_AUDIT_AVAILABLE,
|
||||
gbp_audit_version=GBP_AUDIT_VERSION
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# IT AUDIT USER-FACING DASHBOARD
|
||||
# ============================================================
|
||||
|
||||
@app.route('/audit/it/<slug>')
|
||||
@login_required
|
||||
def it_audit_dashboard(slug):
|
||||
"""
|
||||
User-facing IT infrastructure audit dashboard for a specific company.
|
||||
|
||||
Displays IT audit results with:
|
||||
- Overall score and maturity level
|
||||
- Security, collaboration, and completeness sub-scores
|
||||
- Technology stack summary (Azure AD, M365, backup, monitoring)
|
||||
- AI-generated recommendations
|
||||
|
||||
Access control:
|
||||
- Admin users can view audit for any company
|
||||
- Regular users can only view audit for their own company
|
||||
|
||||
Args:
|
||||
slug: Company slug identifier
|
||||
|
||||
Returns:
|
||||
Rendered it_audit.html template with company and audit data
|
||||
"""
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# Import IT audit models
|
||||
from database import ITAudit
|
||||
|
||||
# Find company by slug
|
||||
company = db.query(Company).filter_by(slug=slug, status='active').first()
|
||||
|
||||
if not company:
|
||||
flash('Firma nie została znaleziona.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Access control: admin can view any company, member only their own
|
||||
if not current_user.is_admin:
|
||||
if current_user.company_id != company.id:
|
||||
flash('Brak uprawnień. Możesz przeglądać audyt tylko własnej firmy.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Get latest IT audit for this company
|
||||
audit = db.query(ITAudit).filter(
|
||||
ITAudit.company_id == company.id
|
||||
).order_by(ITAudit.audit_date.desc()).first()
|
||||
|
||||
# Build audit data dict if audit exists
|
||||
audit_data = None
|
||||
if audit:
|
||||
# Get maturity label
|
||||
maturity_labels = {
|
||||
'basic': 'Podstawowy',
|
||||
'developing': 'Rozwijający się',
|
||||
'established': 'Ugruntowany',
|
||||
'advanced': 'Zaawansowany'
|
||||
}
|
||||
|
||||
audit_data = {
|
||||
'id': audit.id,
|
||||
'overall_score': audit.overall_score,
|
||||
'security_score': audit.security_score,
|
||||
'collaboration_score': audit.collaboration_score,
|
||||
'completeness_score': audit.completeness_score,
|
||||
'maturity_level': audit.maturity_level,
|
||||
'maturity_label': maturity_labels.get(audit.maturity_level, 'Nieznany'),
|
||||
'audit_date': audit.audit_date,
|
||||
'audit_source': audit.audit_source,
|
||||
# Technology flags
|
||||
'has_azure_ad': audit.has_azure_ad,
|
||||
'has_m365': audit.has_m365,
|
||||
'has_google_workspace': audit.has_google_workspace,
|
||||
'has_local_ad': audit.has_local_ad,
|
||||
'has_edr': audit.has_edr,
|
||||
'has_mfa': audit.has_mfa,
|
||||
'has_vpn': audit.has_vpn,
|
||||
'has_proxmox_pbs': audit.has_proxmox_pbs,
|
||||
'has_dr_plan': audit.has_dr_plan,
|
||||
'has_mdm': audit.has_mdm,
|
||||
# Solutions
|
||||
'antivirus_solution': audit.antivirus_solution,
|
||||
'backup_solution': audit.backup_solution,
|
||||
'monitoring_solution': audit.monitoring_solution,
|
||||
'virtualization_platform': audit.virtualization_platform,
|
||||
# Collaboration flags
|
||||
'open_to_shared_licensing': audit.open_to_shared_licensing,
|
||||
'open_to_backup_replication': audit.open_to_backup_replication,
|
||||
'open_to_teams_federation': audit.open_to_teams_federation,
|
||||
'open_to_shared_monitoring': audit.open_to_shared_monitoring,
|
||||
'open_to_collective_purchasing': audit.open_to_collective_purchasing,
|
||||
'open_to_knowledge_sharing': audit.open_to_knowledge_sharing,
|
||||
# Recommendations
|
||||
'recommendations': audit.recommendations
|
||||
}
|
||||
|
||||
# Determine if user can edit audit (admin or company owner)
|
||||
can_edit = current_user.is_admin or current_user.company_id == company.id
|
||||
|
||||
logger.info(f"IT audit dashboard viewed by {current_user.email} for company: {company.name}")
|
||||
|
||||
return render_template('it_audit.html',
|
||||
company=company,
|
||||
audit_data=audit_data,
|
||||
can_edit=can_edit
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
@app.route('/api/check-email', methods=['POST'])
|
||||
def api_check_email():
|
||||
|
||||
@ -90,6 +90,25 @@ def register_blueprints(app):
|
||||
except Exception as e:
|
||||
logger.error(f"Error registering it_audit blueprint: {e}")
|
||||
|
||||
# Audit dashboards blueprint (user-facing)
|
||||
try:
|
||||
from blueprints.audit import bp as audit_bp
|
||||
app.register_blueprint(audit_bp)
|
||||
logger.info("Registered blueprint: audit")
|
||||
|
||||
# Create aliases for backward compatibility
|
||||
_create_endpoint_aliases(app, audit_bp, {
|
||||
'seo_audit_dashboard': 'audit.seo_audit_dashboard',
|
||||
'social_audit_dashboard': 'audit.social_audit_dashboard',
|
||||
'gbp_audit_dashboard': 'audit.gbp_audit_dashboard',
|
||||
'it_audit_dashboard': 'audit.it_audit_dashboard',
|
||||
})
|
||||
logger.info("Created audit endpoint aliases")
|
||||
except ImportError as e:
|
||||
logger.debug(f"Blueprint audit not yet available: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error registering audit blueprint: {e}")
|
||||
|
||||
# Phase 2: Auth + Public blueprints (with backward-compatible aliases)
|
||||
try:
|
||||
from blueprints.auth import bp as auth_bp
|
||||
|
||||
12
blueprints/audit/__init__.py
Normal file
12
blueprints/audit/__init__.py
Normal file
@ -0,0 +1,12 @@
|
||||
"""
|
||||
Audit Blueprint
|
||||
================
|
||||
|
||||
User-facing audit dashboard pages for SEO, GBP, Social Media, and IT audits.
|
||||
"""
|
||||
|
||||
from flask import Blueprint
|
||||
|
||||
bp = Blueprint('audit', __name__, url_prefix='/audit')
|
||||
|
||||
from . import routes # noqa: E402, F401
|
||||
371
blueprints/audit/routes.py
Normal file
371
blueprints/audit/routes.py
Normal file
@ -0,0 +1,371 @@
|
||||
"""
|
||||
Audit Dashboard Routes - Audit blueprint
|
||||
|
||||
Migrated from app.py as part of the blueprint refactoring.
|
||||
Contains user-facing audit dashboard pages for SEO, GBP, Social Media, and IT.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from flask import flash, redirect, render_template, url_for
|
||||
from flask_login import current_user, login_required
|
||||
|
||||
from database import (
|
||||
SessionLocal, Company, CompanyWebsiteAnalysis,
|
||||
CompanySocialMedia, ITAudit
|
||||
)
|
||||
from . import bp
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Check if GBP audit service is available
|
||||
try:
|
||||
from gbp_audit_service import (
|
||||
get_company_audit as gbp_get_company_audit
|
||||
)
|
||||
GBP_AUDIT_AVAILABLE = True
|
||||
GBP_AUDIT_VERSION = '1.0'
|
||||
except ImportError:
|
||||
GBP_AUDIT_AVAILABLE = False
|
||||
GBP_AUDIT_VERSION = None
|
||||
gbp_get_company_audit = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# SEO AUDIT USER-FACING DASHBOARD
|
||||
# ============================================================
|
||||
|
||||
@bp.route('/seo/<slug>')
|
||||
@login_required
|
||||
def seo_audit_dashboard(slug):
|
||||
"""
|
||||
User-facing SEO audit dashboard for a specific company.
|
||||
|
||||
Displays SEO audit results with:
|
||||
- PageSpeed Insights scores (SEO, Performance, Accessibility, Best Practices)
|
||||
- Website analysis data
|
||||
- Improvement recommendations
|
||||
|
||||
Access control:
|
||||
- Admin users can view audit for any company
|
||||
- Regular users can only view audit for their own company
|
||||
|
||||
Args:
|
||||
slug: Company slug identifier
|
||||
|
||||
Returns:
|
||||
Rendered seo_audit.html template with company and audit data
|
||||
"""
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# Find company by slug
|
||||
company = db.query(Company).filter_by(slug=slug, status='active').first()
|
||||
|
||||
if not company:
|
||||
flash('Firma nie została znaleziona.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Access control: admin can view any company, member only their own
|
||||
if not current_user.is_admin:
|
||||
if current_user.company_id != company.id:
|
||||
flash('Brak uprawnień. Możesz przeglądać audyt tylko własnej firmy.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Get latest SEO analysis for this company
|
||||
analysis = db.query(CompanyWebsiteAnalysis).filter(
|
||||
CompanyWebsiteAnalysis.company_id == company.id
|
||||
).order_by(CompanyWebsiteAnalysis.seo_audited_at.desc()).first()
|
||||
|
||||
# Build SEO data dict if analysis exists
|
||||
seo_data = None
|
||||
if analysis and analysis.seo_audited_at:
|
||||
seo_data = {
|
||||
'seo_score': analysis.pagespeed_seo_score,
|
||||
'performance_score': analysis.pagespeed_performance_score,
|
||||
'accessibility_score': analysis.pagespeed_accessibility_score,
|
||||
'best_practices_score': analysis.pagespeed_best_practices_score,
|
||||
'audited_at': analysis.seo_audited_at,
|
||||
'audit_version': analysis.seo_audit_version,
|
||||
'url': analysis.website_url
|
||||
}
|
||||
|
||||
# Determine if user can run audit (admin or company owner)
|
||||
can_audit = current_user.is_admin or current_user.company_id == company.id
|
||||
|
||||
logger.info(f"SEO audit dashboard viewed by {current_user.email} for company: {company.name}")
|
||||
|
||||
return render_template('seo_audit.html',
|
||||
company=company,
|
||||
seo_data=seo_data,
|
||||
can_audit=can_audit
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# SOCIAL MEDIA AUDIT USER-FACING DASHBOARD
|
||||
# ============================================================
|
||||
|
||||
@bp.route('/social/<slug>')
|
||||
@login_required
|
||||
def social_audit_dashboard(slug):
|
||||
"""
|
||||
User-facing Social Media audit dashboard for a specific company.
|
||||
|
||||
Displays social media presence audit with:
|
||||
- Overall presence score (platforms found / total platforms)
|
||||
- Platform-by-platform status
|
||||
- Profile validation status
|
||||
- Recommendations for missing platforms
|
||||
|
||||
Access control:
|
||||
- Admins: Can view all companies
|
||||
- Regular users: Can only view their own company
|
||||
|
||||
Args:
|
||||
slug: Company URL slug
|
||||
|
||||
Returns:
|
||||
Rendered social_audit.html template with company and social data
|
||||
"""
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# Find company by slug
|
||||
company = db.query(Company).filter_by(slug=slug, status='active').first()
|
||||
if not company:
|
||||
flash('Firma nie została znaleziona.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Access control - admin can view all, users only their company
|
||||
if not current_user.is_admin:
|
||||
if current_user.company_id != company.id:
|
||||
flash('Brak uprawnień do wyświetlenia audytu social media tej firmy.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Get social media profiles for this company
|
||||
social_profiles = db.query(CompanySocialMedia).filter(
|
||||
CompanySocialMedia.company_id == company.id
|
||||
).all()
|
||||
|
||||
# Define all platforms we track
|
||||
all_platforms = ['facebook', 'instagram', 'linkedin', 'youtube', 'twitter', 'tiktok']
|
||||
|
||||
# Build social media data
|
||||
profiles_dict = {}
|
||||
for profile in social_profiles:
|
||||
profiles_dict[profile.platform] = {
|
||||
'url': profile.url,
|
||||
'is_valid': profile.is_valid,
|
||||
'check_status': profile.check_status,
|
||||
'page_name': profile.page_name,
|
||||
'followers_count': profile.followers_count,
|
||||
'verified_at': profile.verified_at,
|
||||
'last_checked_at': profile.last_checked_at
|
||||
}
|
||||
|
||||
# Calculate score (platforms with profiles / total platforms)
|
||||
platforms_with_profiles = len([p for p in all_platforms if p in profiles_dict])
|
||||
total_platforms = len(all_platforms)
|
||||
score = int((platforms_with_profiles / total_platforms) * 100) if total_platforms > 0 else 0
|
||||
|
||||
social_data = {
|
||||
'profiles': profiles_dict,
|
||||
'all_platforms': all_platforms,
|
||||
'platforms_count': platforms_with_profiles,
|
||||
'total_platforms': total_platforms,
|
||||
'score': score
|
||||
}
|
||||
|
||||
# Determine if user can run audit (admin or company owner)
|
||||
can_audit = current_user.is_admin or current_user.company_id == company.id
|
||||
|
||||
logger.info(f"Social Media audit dashboard viewed by {current_user.email} for company: {company.name}")
|
||||
|
||||
return render_template('social_audit.html',
|
||||
company=company,
|
||||
social_data=social_data,
|
||||
can_audit=can_audit
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# GBP AUDIT USER-FACING DASHBOARD
|
||||
# ============================================================
|
||||
|
||||
@bp.route('/gbp/<slug>')
|
||||
@login_required
|
||||
def gbp_audit_dashboard(slug):
|
||||
"""
|
||||
User-facing GBP audit dashboard for a specific company.
|
||||
|
||||
Displays Google Business Profile completeness audit results with:
|
||||
- Overall completeness score (0-100)
|
||||
- Field-by-field status breakdown
|
||||
- AI-generated improvement recommendations
|
||||
- Historical audit data
|
||||
|
||||
Access control:
|
||||
- Admin users can view audit for any company
|
||||
- Regular users can only view audit for their own company
|
||||
|
||||
Args:
|
||||
slug: Company slug identifier
|
||||
|
||||
Returns:
|
||||
Rendered gbp_audit.html template with company and audit data
|
||||
"""
|
||||
if not GBP_AUDIT_AVAILABLE:
|
||||
flash('Usługa audytu Google Business Profile jest tymczasowo niedostępna.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# Find company by slug
|
||||
company = db.query(Company).filter_by(slug=slug, status='active').first()
|
||||
|
||||
if not company:
|
||||
flash('Firma nie została znaleziona.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Access control: admin can view any company, member only their own
|
||||
if not current_user.is_admin:
|
||||
if current_user.company_id != company.id:
|
||||
flash('Brak uprawnień. Możesz przeglądać audyt tylko własnej firmy.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Get latest audit for this company
|
||||
audit = gbp_get_company_audit(db, company.id)
|
||||
|
||||
# If no audit exists, we still render the page (template handles this)
|
||||
# The user can trigger an audit from the dashboard
|
||||
|
||||
# Determine if user can run audit (admin or company owner)
|
||||
can_audit = current_user.is_admin or current_user.company_id == company.id
|
||||
|
||||
logger.info(f"GBP audit dashboard viewed by {current_user.email} for company: {company.name}")
|
||||
|
||||
return render_template('gbp_audit.html',
|
||||
company=company,
|
||||
audit=audit,
|
||||
can_audit=can_audit,
|
||||
gbp_audit_available=GBP_AUDIT_AVAILABLE,
|
||||
gbp_audit_version=GBP_AUDIT_VERSION
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# IT AUDIT USER-FACING DASHBOARD
|
||||
# ============================================================
|
||||
|
||||
@bp.route('/it/<slug>')
|
||||
@login_required
|
||||
def it_audit_dashboard(slug):
|
||||
"""
|
||||
User-facing IT infrastructure audit dashboard for a specific company.
|
||||
|
||||
Displays IT audit results with:
|
||||
- Overall score and maturity level
|
||||
- Security, collaboration, and completeness sub-scores
|
||||
- Technology stack summary (Azure AD, M365, backup, monitoring)
|
||||
- AI-generated recommendations
|
||||
|
||||
Access control:
|
||||
- Admin users can view audit for any company
|
||||
- Regular users can only view audit for their own company
|
||||
|
||||
Args:
|
||||
slug: Company slug identifier
|
||||
|
||||
Returns:
|
||||
Rendered it_audit.html template with company and audit data
|
||||
"""
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# Find company by slug
|
||||
company = db.query(Company).filter_by(slug=slug, status='active').first()
|
||||
|
||||
if not company:
|
||||
flash('Firma nie została znaleziona.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Access control: admin can view any company, member only their own
|
||||
if not current_user.is_admin:
|
||||
if current_user.company_id != company.id:
|
||||
flash('Brak uprawnień. Możesz przeglądać audyt tylko własnej firmy.', 'error')
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
# Get latest IT audit for this company
|
||||
audit = db.query(ITAudit).filter(
|
||||
ITAudit.company_id == company.id
|
||||
).order_by(ITAudit.audit_date.desc()).first()
|
||||
|
||||
# Build audit data dict if audit exists
|
||||
audit_data = None
|
||||
if audit:
|
||||
# Get maturity label
|
||||
maturity_labels = {
|
||||
'basic': 'Podstawowy',
|
||||
'developing': 'Rozwijający się',
|
||||
'established': 'Ugruntowany',
|
||||
'advanced': 'Zaawansowany'
|
||||
}
|
||||
|
||||
audit_data = {
|
||||
'id': audit.id,
|
||||
'overall_score': audit.overall_score,
|
||||
'security_score': audit.security_score,
|
||||
'collaboration_score': audit.collaboration_score,
|
||||
'completeness_score': audit.completeness_score,
|
||||
'maturity_level': audit.maturity_level,
|
||||
'maturity_label': maturity_labels.get(audit.maturity_level, 'Nieznany'),
|
||||
'audit_date': audit.audit_date,
|
||||
'audit_source': audit.audit_source,
|
||||
# Technology flags
|
||||
'has_azure_ad': audit.has_azure_ad,
|
||||
'has_m365': audit.has_m365,
|
||||
'has_google_workspace': audit.has_google_workspace,
|
||||
'has_local_ad': audit.has_local_ad,
|
||||
'has_edr': audit.has_edr,
|
||||
'has_mfa': audit.has_mfa,
|
||||
'has_vpn': audit.has_vpn,
|
||||
'has_proxmox_pbs': audit.has_proxmox_pbs,
|
||||
'has_dr_plan': audit.has_dr_plan,
|
||||
'has_mdm': audit.has_mdm,
|
||||
# Solutions
|
||||
'antivirus_solution': audit.antivirus_solution,
|
||||
'backup_solution': audit.backup_solution,
|
||||
'monitoring_solution': audit.monitoring_solution,
|
||||
'virtualization_platform': audit.virtualization_platform,
|
||||
# Collaboration flags
|
||||
'open_to_shared_licensing': audit.open_to_shared_licensing,
|
||||
'open_to_backup_replication': audit.open_to_backup_replication,
|
||||
'open_to_teams_federation': audit.open_to_teams_federation,
|
||||
'open_to_shared_monitoring': audit.open_to_shared_monitoring,
|
||||
'open_to_collective_purchasing': audit.open_to_collective_purchasing,
|
||||
'open_to_knowledge_sharing': audit.open_to_knowledge_sharing,
|
||||
# Recommendations
|
||||
'recommendations': audit.recommendations
|
||||
}
|
||||
|
||||
# Determine if user can edit audit (admin or company owner)
|
||||
can_edit = current_user.is_admin or current_user.company_id == company.id
|
||||
|
||||
logger.info(f"IT audit dashboard viewed by {current_user.email} for company: {company.name}")
|
||||
|
||||
return render_template('it_audit.html',
|
||||
company=company,
|
||||
audit_data=audit_data,
|
||||
can_edit=can_edit
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
Loading…
Reference in New Issue
Block a user