Diff -- /var/www/vhosts/webstls.com/httpdocs/buyer_login.cgi
Diff

/var/www/vhosts/webstls.com/httpdocs/buyer_login.cgi

added on WebSTLs (webstls.com) at 2026-07-01 22:26:29

Added
+217
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to 75212bf6ee27
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# WebSTLs -- buyer auth (login / signup / logout).
4#
5# Consolidates the former /buyer_signup.cgi and /buyer_logout.cgi via
6# SCRIPT_NAME dispatch. The signup + logout .cgi files are wrappers
7# that `do` this file.
8#
9# GET /buyer_login.cgi?id=<storefront_id> -> render login form
10# POST /buyer_login.cgi -> authenticate + set cookie
11# GET /buyer_signup.cgi?id=<storefront_id> -> render signup form
12# POST /buyer_signup.cgi -> create account + login
13# ANY /buyer_logout.cgi?id=<storefront_id> -> revoke session + redirect
14#======================================================================
15use strict;
16use warnings;
17
18use lib '/var/www/vhosts/webstls.com/httpdocs';
19use CGI;
20use MODS::Template;
21use MODS::DBConnect;
22use MODS::WebSTLs::Config;
23use MODS::WebSTLs::BuyerAuth;
24use MODS::WebSTLs::Themes;
25
26my $q = CGI->new;
27my $form = $q->Vars;
28my $db = MODS::DBConnect->new;
29my $cfg = MODS::WebSTLs::Config->new;
30my $auth = MODS::WebSTLs::BuyerAuth->new;
31my $DB = $cfg->settings('database_name');
32
33$| = 1;
34
35my $entry = ($ENV{SCRIPT_NAME} || '') =~ m{/([^/]+)\.cgi$} ? $1 : 'buyer_login';
36
37my $sid = $form->{id} || $form->{storefront_id} || 0;
38$sid =~ s/[^0-9]//g;
39
40#----------------------------------------------------------------------
41# buyer_logout entry: revoke session + 302 back to storefront.
42#----------------------------------------------------------------------
43if ($entry eq 'buyer_logout') {
44 my $dbh = $db->db_connect();
45 my $buyer = $auth->verify($q, $db, $dbh, $DB);
46 my $cookie = $auth->logout($db, $dbh, $DB, $buyer ? $buyer->{session_id} : '');
47 $db->db_disconnect($dbh);
48
49 my $back = $sid ? "/store.cgi?id=$sid" : '/';
50 print "Status: 302 Found\n";
51 print "Set-Cookie: $cookie\n";
52 print "Location: $back\n\n";
53 exit;
54}
55
56#----------------------------------------------------------------------
57# login + signup share the storefront lookup + theme + chrome render.
58#----------------------------------------------------------------------
59my $tfile = MODS::Template->new;
60my $themes = MODS::WebSTLs::Themes->new;
61
62my $dbh = $db->db_connect();
63my $store;
64if ($sid) {
65 $store = $db->db_readwrite($dbh,
66 qq~SELECT id, name, subdomain, theme_id FROM `${DB}`.storefronts WHERE id='$sid' LIMIT 1~,
67 $ENV{SCRIPT_NAME}, __LINE__);
68}
69unless ($store && $store->{id}) {
70 $db->db_disconnect($dbh);
71 print "Status: 302 Found\nLocation: /\n\n";
72 exit;
73}
74
75my $err = '';
76my $email_in = '';
77my $name_in = '';
78
79if ($entry eq 'buyer_signup') {
80 #------------------------------------------------------------------
81 # buyer_signup: POST creates account, auto-logs-in, links tracking
82 # + backfills historic buyer credits.
83 #------------------------------------------------------------------
84 if (($ENV{REQUEST_METHOD} || '') eq 'POST') {
85 $email_in = $form->{email} || '';
86 $name_in = $form->{display_name} || '';
87 my $pw = $form->{password} || '';
88
89 my $result = $auth->signup($db, $dbh, $DB, $store->{id}, $email_in, $pw, $name_in);
90 if (ref($result) eq 'HASH' && $result->{error}) {
91 $err = $result->{error};
92 } else {
93 # Auto-login the new account.
94 my ($buyer, $cookie) = $auth->login($db, $dbh, $DB, $store->{id}, $email_in, $pw);
95
96 # Link the visitor's existing tracking session to the new
97 # buyer_account so admin sees them flip from Guest -> Lead.
98 if ($buyer && $buyer->{id}) {
99 _ba_link_tracking($buyer->{id});
100
101 # Backfill any historic buyer_credit_ledger rows that were
102 # issued to this email while it was unregistered, so the new
103 # account inherits the credit balance instantly. Self-guards
104 # against the table being absent.
105 eval {
106 require MODS::WebSTLs::BuyerCredits;
107 my $bc = MODS::WebSTLs::BuyerCredits->new;
108 $bc->link_email_to_account($db, $dbh, $DB,
109 $store->{id}, $buyer->{id}, $email_in);
110 };
111 }
112
113 $db->db_disconnect($dbh);
114 print "Status: 302 Found\n";
115 print "Set-Cookie: $cookie\n" if $cookie;
116 print "Location: /my_orders.cgi?id=$store->{id}\n\n";
117 exit;
118 }
119 }
120}
121else {
122 #------------------------------------------------------------------
123 # buyer_login (default): POST authenticates + links tracking session.
124 #------------------------------------------------------------------
125 if (($ENV{REQUEST_METHOD} || '') eq 'POST') {
126 $email_in = $form->{email} || '';
127 my $pw = $form->{password} || '';
128
129 my ($buyer, $cookie) = $auth->login($db, $dbh, $DB, $store->{id}, $email_in, $pw);
130 if (ref($buyer) eq 'HASH' && $buyer->{error}) {
131 $err = $buyer->{error};
132 } elsif ($buyer && $buyer->{id}) {
133 # Link this visitor's tracking session to the buyer account so
134 # the admin visitor list + chat can flag them as a Customer /
135 # Lead and show their order count + LTV.
136 _ba_link_tracking($buyer->{id});
137
138 $db->db_disconnect($dbh);
139 print "Status: 302 Found\n";
140 print "Set-Cookie: $cookie\n" if $cookie;
141 print "Location: /my_orders.cgi?id=$store->{id}\n\n";
142 exit;
143 } else {
144 $err = 'login failed';
145 }
146 }
147}
148
149my $theme = $themes->by_id($store->{theme_id});
150my $css_vars = $themes->css_vars($theme);
151
152$db->db_disconnect($dbh);
153
154require MODS::WebSTLs::StoreChrome;
155my $chrome_dbh = $db->db_connect();
156my $chrome_html = MODS::WebSTLs::StoreChrome->header_html({
157 store_id => $store->{id},
158 store_name => $store->{name} || $store->{subdomain},
159 is_buyer_in => 0,
160 cart_count => 0,
161 db => $db,
162 dbh => $chrome_dbh,
163 DB => $DB,
164});
165$db->db_disconnect($chrome_dbh);
166
167my $tvars = {
168 theme_css_vars => $css_vars,
169 store_id => $store->{id},
170 store_name => _ba_esc($store->{name} || $store->{subdomain}),
171 store_chrome_html => $chrome_html,
172 email_value => _ba_esc($email_in),
173 has_error => $err ? 1 : 0,
174 error_message => _ba_esc($err),
175 back_href => "/store.cgi?id=$store->{id}",
176};
177
178my $tpl;
179if ($entry eq 'buyer_signup') {
180 $tvars->{name_value} = _ba_esc($name_in);
181 $tvars->{login_href} = "/buyer_login.cgi?id=$store->{id}";
182 $tpl = 'webstls_buyer_signup.html';
183}
184else {
185 $tvars->{signup_href} = "/buyer_signup.cgi?id=$store->{id}";
186 $tpl = 'webstls_buyer_login.html';
187}
188
189print "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";
190print join('', $tfile->template($tpl, $tvars, undef));
191
192#======================================================================
193# Helpers (prefixed _ba_ = buyer auth, avoids collision when do'd from
194# wrappers alongside other helpers).
195#======================================================================
196sub _ba_esc {
197 my $s = shift;
198 $s //= '';
199 $s =~ s/&/&amp;/g;
200 $s =~ s/</&lt;/g;
201 $s =~ s/>/&gt;/g;
202 $s =~ s/"/&quot;/g;
203 return $s;
204}
205
206sub _ba_link_tracking {
207 my $buyer_id = shift;
208 my $track_token = '';
209 my $raw_cookie = $ENV{HTTP_COOKIE} || '';
210 if ($raw_cookie =~ /(?:^|;\s*)webstls_track=([a-f0-9-]{36})/) {
211 $track_token = $1;
212 }
213 return unless $track_token;
214 require MODS::WebSTLs::Tracking;
215 my $tr = MODS::WebSTLs::Tracking->new;
216 $tr->link_session_to_buyer($db, $dbh, $DB, $track_token, $buyer_id);
217}
Keyboard: j next diff k previous diff g top G bottom r restore c compile-check ? help