- Created new on_mount hook :load_default_organization that automatically loads user's first organization
- Moved sites and devices routes to root path (/ sites, /devices) instead of /orgs/:org_slug
- Updated all navigation links and route references throughout the app
- Dashboard, alerts, and agents still use org-specific routes (/orgs/:org_slug)
- Users can still switch organizations via org selector for other pages
- Replace TODO comment with "Future enhancement" note
- Alias nested DeviceProfiles.Importer module
- Replace expensive length/1 check with empty list comparison
- Extract nested logic into helper functions to reduce complexity:
- import_sensor_with_states for sensor import
- walk_sensor_oid and walk_processor_oid for SNMP walks
- apply_processor_precision and determine_processor_status
- check_device_health for device monitoring
- Add auto-dismiss functionality to flash messages (30 second timeout)
- Implement AutoDismissFlash LiveView hook in TypeScript
- Update user settings page to use Tailwind Plus 3-column grid layout
- Add API token management section to user settings
- Implement organization name display in navigation menu
- Update table component to use Tailwind Plus styling across all tables
- Update flash notifications with Tailwind Plus design
- Update dropdown menus and select inputs with custom chevron styling
- Fix authentication redirect to return to original page after login
- Preserve user_return_to session key across session renewal
- Add store_return_to_for_liveview plug to browser pipeline
- Add profiles.json to gitignore
- Add Organization Settings link in top-right org menu dropdown
- Position it between Switch Org and Admin Panel
- Add gear icon for visual clarity
- Rename 'Settings' to 'User Settings' with user icon for clarity
- Organization Settings link only shows when current_organization is set
- Add compile-time @build_timestamp to Application module
- Create ToweropsWeb.TimeHelpers module for shared time formatting
- Update footer to display 'Last deployed Xm ago · YYYY-MM-DD HH:MM:SS UTC'
- Refactor AgentLive.Helpers to delegate to shared TimeHelpers
- Consolidate duplicate time formatting logic into single module
- Timestamp updates automatically on each build/deploy
Replace black ring border with lighter zinc-200/zinc-700 border on all
tables for better visual consistency across the application. Also update
tbody dividers to match the new border styling.
The admin layout was incorrectly defined as a separate .html.heex file
using @inner_content. Phoenix components should use render_slot(@inner_block).
Moved admin layout definition into layouts.ex as a proper function
component, matching the pattern used by app/1 and authenticated/1 layouts.
Replace raw HTML form with Phoenix .link helper using method="delete" to properly handle CSRF token in LiveView context. This fixes the UndefinedFunctionError when accessing /admin route.
Replace expensive length/1 comparisons with direct list comparisons or Enum.empty?/1 checks (13 instances in source code and tests). Add module aliases for Phoenix.HTML.Form and Towerops.Accounts.Scope to reduce nested module references.
Changes:
- Replace length(list) > 0 with list != [] or refute Enum.empty?(list)
- Add Phoenix.HTML.Form alias in CoreComponents
- Add Towerops.Accounts.Scope alias in ConnCase test helper
This eliminates all credo warnings and software design suggestions.
Implement comprehensive admin interface allowing designated superusers to view all users and organizations, impersonate users for debugging, and perform administrative operations. All superuser actions are tracked in audit logs for compliance.
Features:
- Superuser authentication with dedicated admin routes at /admin
- User impersonation with session state preservation
- Admin dashboard with system statistics
- User and organization management interfaces
- Comprehensive audit logging with IP tracking
- Visual impersonation banner with exit capability
- Security controls preventing self-impersonation and superuser-to-superuser impersonation
Database:
- Add is_superuser boolean field to users table
- Create audit_logs table for tracking sensitive operations
- Set graham@mcintire.me as initial superuser