Diff -- /var/www/vhosts/3dshawn.com/affiliate.3dshawn.com/profile.cgi
Diff

/var/www/vhosts/3dshawn.com/affiliate.3dshawn.com/profile.cgi

added on local at 2026-07-01 13:47:39

Added
+185
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to e2c308f07d2a
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
1#!/usr/bin/perl
2#======================================================================
3# AffSoft -- Profile (account identity)
4#
5# Replaces the "Account" + "Security" portions of the old settings.cgi.
6# Notification toggles + Available Features tab moved to preferences.cgi.
7#
8# Handles:
9# save_account -- display_name / email / currency / timezone
10# resend_verification -- re-mint + send email-verification token
11#
12# Read-only renders email-verified state, 2FA state, active-session count,
13# and password-change link (the real password change still POSTs to
14# /password_change.cgi). The template (affsoft_profile.html) is the
15# split-out account / security half of webstls_settings.html.
16#======================================================================
17use strict;
18use warnings;
19
20use lib '/var/www/vhosts/3dshawn.com/affiliate.3dshawn.com';
21use CGI;
22use MODS::Template;
23use MODS::DBConnect;
24use MODS::Login;
25use MODS::AffSoft::Config;
26use MODS::AffSoft::Wrapper;
27
28my $q = CGI->new;
29my $form = $q->Vars;
30my $auth = MODS::Login->new;
31my $wrap = MODS::AffSoft::Wrapper->new;
32my $tfile = MODS::Template->new;
33my $db = MODS::DBConnect->new;
34my $cfg = MODS::AffSoft::Config->new;
35my $DB = $cfg->settings('database_name');
36
37$|=1;
38my $userinfo = $auth->login_verify();
39if (!$userinfo) {
40 print "Status: 302 Found\nLocation: /login.cgi\n\n";
41 exit;
42}
43my $uid = $userinfo->{user_id};
44$uid =~ s/[^0-9]//g;
45
46my $dbh = $db->db_connect();
47
48sub _esc {
49 my $s = shift;
50 $s //= '';
51 $s =~ s/\\/\\\\/g;
52 $s =~ s/'/''/g;
53 return $s;
54}
55
56# ---- POST handlers -------------------------------------------------
57my $saved_msg = '';
58
59if (($form->{action} || '') eq 'save_account') {
60 my $name = $form->{display_name} // '';
61 my $email = $form->{email} // '';
62 my $cur = uc($form->{default_currency} // 'USD');
63 my $tz = $form->{timezone} // 'UTC';
64
65 $name =~ s/^\s+|\s+$//g;
66 $email =~ s/^\s+|\s+$//g;
67 $cur = substr($cur, 0, 3);
68 $tz = substr($tz, 0, 64);
69
70 if ($name eq '' || $email !~ /\@/) {
71 $saved_msg = 'Please provide a display name and a valid email address.';
72 } else {
73 $db->db_readwrite($dbh, qq~
74 UPDATE `${DB}`.users
75 SET display_name='~ . _esc($name) . qq~',
76 email='~ . _esc($email) . qq~',
77 default_currency='~ . _esc($cur) . qq~',
78 timezone='~ . _esc($tz) . qq~'
79 WHERE id='$uid'
80 ~, $ENV{SCRIPT_NAME}, __LINE__);
81 $saved_msg = 'Profile saved.';
82 }
83}
84elsif (($form->{action} || '') eq 'resend_verification') {
85 require MODS::AffSoft::EmailVerify;
86 my $u_check = $db->db_readwrite($dbh, qq~
87 SELECT id, email, display_name, email_verified_at
88 FROM `${DB}`.users WHERE id='$uid' LIMIT 1
89 ~, $ENV{SCRIPT_NAME}, __LINE__);
90 if ($u_check && $u_check->{id} && !$u_check->{email_verified_at}) {
91 my $r = MODS::AffSoft::EmailVerify->send_for_user(
92 $db, $dbh, $DB,
93 { id => $u_check->{id}, email => $u_check->{email}, display_name => $u_check->{display_name} },
94 );
95 $saved_msg = ($r && $r->{ok})
96 ? 'Verification email sent. Check your inbox (and spam folder).'
97 : 'Could not send verification email: ' . ($r->{error} || 'unknown error');
98 } else {
99 $saved_msg = 'Your email is already verified.';
100 }
101}
102
103# ---- Load current state --------------------------------------------
104my $u = $db->db_readwrite($dbh, qq~
105 SELECT display_name, email, default_currency, timezone,
106 two_factor_enabled,
107 email_verified_at,
108 DATE_FORMAT(email_verified_at, '%b %e, %Y') AS verified_on
109 FROM `${DB}`.users
110 WHERE id='$uid'
111~, $ENV{SCRIPT_NAME}, __LINE__) || {};
112
113# Build the dropdown lists with `selected` flags so the template can
114# render plain HTML without any client-side guessing.
115my @CURRENCIES = qw(USD EUR GBP CAD AUD JPY);
116my @TIMEZONES = (
117 'UTC',
118 'America/Los_Angeles',
119 'America/Denver',
120 'America/Chicago',
121 'America/New_York',
122 'Europe/London',
123 'Europe/Berlin',
124 'Europe/Paris',
125 'Asia/Tokyo',
126 'Australia/Sydney',
127);
128my (@cur_opts, @tz_opts);
129my $cur_now = $u->{default_currency} || 'USD';
130my $tz_now = $u->{timezone} || 'UTC';
131foreach my $c (@CURRENCIES) {
132 push @cur_opts, { value => $c, selected_attr => ($c eq $cur_now ? ' selected' : '') };
133}
134foreach my $t (@TIMEZONES) {
135 push @tz_opts, { value => $t, selected_attr => ($t eq $tz_now ? ' selected' : '') };
136}
137
138# Active sessions
139my $active_sessions = 0;
140my $r_sess = $db->db_readwrite($dbh, qq~
141 SELECT COUNT(*) AS n FROM `${DB}`.user_sessions
142 WHERE user_id='$uid'
143 AND revoked_at IS NULL
144 AND expires_at > NOW()
145~, $ENV{SCRIPT_NAME}, __LINE__);
146$active_sessions = $r_sess->{n} if $r_sess && defined $r_sess->{n};
147
148$db->db_disconnect($dbh);
149
150sub _h_attr {
151 my $s = shift;
152 $s //= '';
153 $s =~ s/&/&/g;
154 $s =~ s/</&lt;/g;
155 $s =~ s/>/&gt;/g;
156 $s =~ s/"/&quot;/g;
157 return $s;
158}
159
160my $tvars = {
161 user_id => $uid,
162 saved_msg => $saved_msg,
163 has_saved_msg => $saved_msg ? 1 : 0,
164
165 display_name => _h_attr($u->{display_name}),
166 email => _h_attr($u->{email}),
167 currency_options => \@cur_opts,
168 timezone_options => \@tz_opts,
169
170 email_verified => $u->{email_verified_at} ? 1 : 0,
171 email_verified_label => $u->{email_verified_at} ? ('Verified ' . ($u->{verified_on} || '')) : 'Not verified yet',
172 two_factor_enabled => $u->{two_factor_enabled} ? 1 : 0,
173 active_session_count => $active_sessions,
174};
175
176print "Content-Type: text/html; charset=utf-8\nCache-Control: no-store, no-cache, must-revalidate, max-age=0\nPragma: no-cache\nExpires: 0\n\n";
177
178my $body = join('', $tfile->template('affsoft_profile.html', $tvars, $userinfo));
179
180$wrap->render({
181 userinfo => $userinfo,
182 page_key => 'my_profile',
183 title => 'My Profile',
184 body => $body,
185});
Keyboard: j next diff k previous diff g top G bottom r restore c compile-check ? help