# /lib/MyApp/Controller/Settings.pm package MyApp::Controller::Settings; use Mojo::Base 'Mojolicious::Controller'; use Mojo::Util qw(trim); # Controller for Application Configuration Management. # Features: # - Centralized settings display interface for admins # - Handles updates for Pushover, Gotify, Unsplash, App Secret, and Email settings # Integration points: # - Uses DB::Settings for retrieving and updating configuration # - Admin-only access enforced via is_admin helper # Renders the settings management interface. # Route: GET /settings # Parameters: None # Returns: # Rendered HTML template 'settings' with current configuration sub index { my $c = shift; return $c->redirect_to('/noperm') unless $c->is_admin; my $settings = $c->db->get_all_settings(); my $email_settings = $c->db->get_email_settings(); $c->stash( settings => $settings, email_settings => $email_settings ); $c->render('settings'); } # Processes updates for a specific configuration section. # Route: POST /settings/update # Parameters: # section : The configuration block to update ('pushover', 'gotify', 'app_secret', 'unsplash', 'email') # pushover_token : (If section=pushover) API Token # pushover_user : (If section=pushover) User Key # gotify_token : (If section=gotify) App Token # app_secret : (If section=app_secret) New session signature key (min 32 chars) # unsplash_key : (If section=unsplash) API Access Key # gmail_email : (If section=email) Gmail account address # gmail_app_password : (If section=email) Gmail app-specific password # gmail_from_name : (If section=email) Display name for From header (optional) # Returns: # Redirects to settings page with flash message (Success/Error) sub update { my $c = shift; return $c->redirect_to('/noperm') unless $c->is_admin; my $section = $c->param('section'); if ($section eq 'pushover') { my $token = trim($c->param('pushover_token') // ''); my $user = trim($c->param('pushover_user') // ''); if ($token && $user) { $c->db->update_pushover($token, $user); $c->flash(message => 'Pushover settings updated successfully'); } else { $c->flash(error => 'Pushover token and user are required'); } } elsif ($section eq 'gotify') { my $token = trim($c->param('gotify_token') // ''); if ($token) { $c->db->update_gotify($token); $c->flash(message => 'Gotify settings updated successfully'); } else { $c->flash(error => 'Gotify token is required'); } } elsif ($section eq 'app_secret') { my $secret = trim($c->param('app_secret') // ''); if ($secret && length($secret) >= 32) { $c->db->update_app_secret($secret); $c->flash(message => 'App secret updated successfully. Restart required.'); } else { $c->flash(error => 'App secret must be at least 32 characters'); } } elsif ($section eq 'unsplash') { my $api_key = trim($c->param('unsplash_key') // ''); $c->db->update_unsplash_key($api_key); if ($api_key) { $c->flash(message => 'Unsplash API key updated successfully'); } else { $c->flash(message => 'Unsplash API key cleared (will use Picsum fallback)'); } } elsif ($section eq 'email') { my $gmail_email = trim($c->param('gmail_email') // ''); my $gmail_password = trim($c->param('gmail_app_password') // ''); $gmail_password =~ s/\s+//g; my $from_name = trim($c->param('gmail_from_name') // ''); if ($gmail_email && $gmail_password) { unless ($gmail_email =~ /^[a-zA-Z0-9._%+-]+\@gmail\.com$/) { $c->flash(error => 'Invalid Gmail address (must be @gmail.com)'); return $c->redirect_to('/settings'); } $c->db->update_email_settings($gmail_email, $gmail_password, $from_name); $c->flash(message => 'Email settings updated successfully'); } else { $c->flash(error => 'Gmail email and app password are required'); } } return $c->redirect_to('/settings'); } 1;