Diff -- /var/www/vhosts/3dshawn.com/admin.3dshawn.com/login.cgi
Diff
/var/www/vhosts/3dshawn.com/admin.3dshawn.com/login.cgi
added on local at 2026-06-22 16:44:16
Added
+0
lines
Removed
-0
lines
Context
101
unchanged
Blobs
from 56ec410dc6af
to 56ec410dc6af
to 56ec410dc6af
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.| 1 | 1 | #!/usr/bin/perl |
| 2 | 2 | #====================================================================== |
| 3 | 3 | # Meta-Admin -- /login.cgi |
| 4 | 4 | # |
| 5 | 5 | # Sign-in only (single-operator console; no signup, no forgot-flow). |
| 6 | 6 | # If Shawn ever forgets the password, reset directly via the |
| 7 | 7 | # _set_password.pl helper or SQL. |
| 8 | 8 | # |
| 9 | 9 | # This page does NOT render the sidebar -- it's the pre-auth screen, |
| 10 | 10 | # so we draw the brand mark + sign-in card centered on the backdrop. |
| 11 | 11 | #====================================================================== |
| 12 | 12 | use strict; |
| 13 | 13 | use warnings; |
| 14 | 14 | use lib '/var/www/vhosts/3dshawn.com/admin.3dshawn.com'; |
| 15 | 15 | use CGI; |
| 16 | 16 | use MODS::DBConnect; |
| 17 | 17 | use MODS::Login; |
| 18 | 18 | use MODS::MetaAdmin::Config; |
| 19 | 19 | |
| 20 | 20 | my $q = CGI->new; |
| 21 | 21 | my $form = $q->Vars; |
| 22 | 22 | my $auth = MODS::Login->new; |
| 23 | 23 | my $cfg = MODS::MetaAdmin::Config->new; |
| 24 | 24 | |
| 25 | 25 | # Already signed in? -> home. Except when previewing the maintenance |
| 26 | 26 | # overlay (?_preview_maintenance=1), so admins can see how it looks |
| 27 | 27 | # without signing out. |
| 28 | 28 | my $cur = $auth->login_verify; |
| 29 | 29 | if ($cur && $cur->{user_id} && !$form->{_preview_maintenance}) { |
| 30 | 30 | print "Status: 302 Found\nLocation: /index.cgi\n\n"; exit; |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | 33 | my $op = $form->{op} || ''; |
| 34 | 34 | my $err = ''; |
| 35 | 35 | |
| 36 | 36 | if ($op eq 'signin') { |
| 37 | 37 | my ($uid, $sid) = $auth->sign_in($form->{email} || '', $form->{password} || ''); |
| 38 | 38 | if ($uid && $sid) { |
| 39 | 39 | print $auth->cookie_header($sid) . "\n"; |
| 40 | 40 | print "Status: 302 Found\nLocation: /index.cgi\n\n"; exit; |
| 41 | 41 | } |
| 42 | 42 | $err = $sid; # the error message comes back in $sid slot on fail |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | 45 | my $brand_name = $cfg->settings('brand_name') || 'Meta-Admin'; |
| 46 | 46 | my $brand_tagline = $cfg->settings('brand_tagline') || 'One console. Every site.'; |
| 47 | 47 | my $assets_css = $cfg->settings('assets_css') || '/assets/css'; |
| 48 | 48 | |
| 49 | 49 | my $err_h = $err; $err_h =~ s/</</g; $err_h =~ s/>/>/g; |
| 50 | 50 | # 'maintenance_locked' = friendly translated to the user-facing copy |
| 51 | 51 | $err_h =~ s/^maintenance_locked$/Site is in maintenance mode. Only super-admins can sign in./; |
| 52 | 52 | my $err_html = length($err_h) ? qq~<div class="banner danger">$err_h</div>~ : ''; |
| 53 | 53 | |
| 54 | 54 | # Maintenance lockdown overlay (modal). Closeable with X / Esc; reappears |
| 55 | 55 | # on next page load if site is still locked. Admin sign-in path stays |
| 56 | 56 | # usable while the overlay is dismissed. |
| 57 | 57 | my $maint_locked = int($cfg->settings('maintenance_locked') || 0); |
| 58 | 58 | my $maint_html = ''; |
| 59 | 59 | if ($maint_locked || $form->{_preview_maintenance}) { |
| 60 | 60 | my $msg = $cfg->settings('maintenance_message') || '<p>Site is in maintenance mode.</p>'; |
| 61 | 61 | $maint_html = qq~<div id="maint-overlay" style="position:fixed;inset:0;background:rgba(0,0,0,0.88);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);z-index:9999;display:flex;align-items:center;justify-content:center;padding:24px"><div style="position:relative;background:#0f0f0f;border:1px solid rgba(217,119,6,0.6);border-radius:12px;max-width:680px;width:100%;padding:48px 40px;box-shadow:0 30px 90px rgba(0,0,0,0.6),0 0 0 1px rgba(217,119,6,0.15)"><button type="button" aria-label="Close" onclick="document.getElementById('maint-overlay').style.display='none'" style="position:absolute;top:14px;right:14px;width:36px;height:36px;background:transparent;border:1px solid rgba(255,255,255,0.12);color:#aaa;font-size:22px;line-height:1;border-radius:8px;cursor:pointer">×</button>$msg</div><script>document.addEventListener('keydown',function(e){if(e.key==='Escape'){var o=document.getElementById('maint-overlay');if(o)o.style.display='none';}});</script></div>~; |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | 64 | print "Content-Type: text/html; charset=utf-8\nCache-Control: no-store\n\n"; |
| 65 | 65 | print <<"HTML"; |
| 66 | 66 | <!DOCTYPE html> |
| 67 | 67 | <html lang="en"> |
| 68 | 68 | <head> |
| 69 | 69 | <meta charset="utf-8"> |
| 70 | 70 | <meta name="viewport" content="width=device-width, initial-scale=1"> |
| 71 | 71 | <title>Sign in · $brand_name</title> |
| 72 | 72 | <link rel="stylesheet" href="$assets_css/meta.css?v=2"> |
| 73 | 73 | </head> |
| 74 | 74 | <body style="display:block"> |
| 75 | 75 | <div style="min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px;position:relative;z-index:1"> |
| 76 | 76 | <div style="width:100%;max-width:420px"> |
| 77 | 77 | <div style="text-align:center;margin-bottom:28px"> |
| 78 | 78 | <div class="brand-mark" style="margin:0 auto 14px;width:48px;height:48px;border-radius:12px;font-size:20px">M</div> |
| 79 | 79 | <div class="brand-name" style="font-size:22px">$brand_name</div> |
| 80 | 80 | <div class="brand-tag" style="margin-top:4px">$brand_tagline</div> |
| 81 | 81 | </div> |
| 82 | 82 | $maint_html |
| 83 | 83 | $err_html |
| 84 | 84 | <div class="module glow-magenta"> |
| 85 | 85 | <div class="module-head"><div class="left"><div class="module-title">Sign in</div></div></div> |
| 86 | 86 | <div class="module-body"> |
| 87 | 87 | <form method="POST" action="/login.cgi"> |
| 88 | 88 | <input type="hidden" name="op" value="signin"> |
| 89 | 89 | <label class="lbl"><span class="t">Email</span> |
| 90 | 90 | <input type="email" name="email" autocomplete="email" required></label> |
| 91 | 91 | <label class="lbl"><span class="t">Password</span> |
| 92 | 92 | <input type="password" name="password" autocomplete="current-password" required></label> |
| 93 | 93 | <button type="submit" class="btn btn-primary" style="width:100%;justify-content:center">Sign in</button> |
| 94 | 94 | </form> |
| 95 | 95 | </div> |
| 96 | 96 | </div> |
| 97 | 97 | </div> |
| 98 | 98 | </div> |
| 99 | 99 | </body> |
| 100 | 100 | </html> |
| 101 | 101 | HTML |