Diff -- /var/www/vhosts/3dshawn.com/repricer.3dshawn.com/account_close.cgi

O Operator
Diff

/var/www/vhosts/3dshawn.com/repricer.3dshawn.com/account_close.cgi

added on local at 2026-07-01 21:46:50

Added
+102
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to 81c41a042f87
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# RePricer -- account self-close (30-day grace).
4#
5# GET /account_close.cgi confirmation page
6# POST act=request stamp users.account_deletion_requested_at
7# POST act=cancel clear it (within grace window)
8#
9# Actual purge happens in _subscription_worker.pl when
10# account_deletion_requested_at <= NOW() - INTERVAL 30 DAY.
11#======================================================================
12use strict;
13use warnings;
14use lib '/var/www/vhosts/3dshawn.com/repricer.3dshawn.com';
15use CGI;
16use MODS::DBConnect;
17use MODS::Login;
18use MODS::RePricer::Config;
19use MODS::RePricer::Wrapper;
20
21$|=1;
22my $q = CGI->new;
23my $form = $q->Vars;
24my $auth = MODS::Login->new;
25my $wrap = MODS::RePricer::Wrapper->new;
26my $db = MODS::DBConnect->new;
27my $cfg = MODS::RePricer::Config->new;
28my $DB = $cfg->settings('database_name');
29
30my $userinfo = $auth->login_verify();
31unless ($userinfo) { print "Status: 302 Found\nLocation: /login.cgi\n\n"; exit; }
32my $uid = $userinfo->{user_id}; $uid =~ s/[^0-9]//g;
33
34sub _h { my $s = shift // ''; $s =~ s/&/&amp;/g; $s =~ s/</&lt;/g; $s =~ s/>/&gt;/g; $s =~ s/"/&quot;/g; $s }
35
36my $dbh = $db->db_connect();
37my $flash = '';
38if (($ENV{REQUEST_METHOD} || '') eq 'POST') {
39 my $act = $form->{act} || '';
40 if ($act eq 'request') {
41 $db->db_readwrite($dbh, qq~
42 UPDATE `${DB}`.users SET account_deletion_requested_at=NOW() WHERE id='$uid'
43 ~, $ENV{SCRIPT_NAME}, __LINE__);
44 $flash = 'requested';
45 } elsif ($act eq 'cancel') {
46 $db->db_readwrite($dbh, qq~
47 UPDATE `${DB}`.users SET account_deletion_requested_at=NULL WHERE id='$uid'
48 ~, $ENV{SCRIPT_NAME}, __LINE__);
49 $flash = 'cancelled';
50 }
51}
52
53my $u = $db->db_readwrite($dbh, qq~
54 SELECT account_deletion_requested_at,
55 TIMESTAMPDIFF(DAY, account_deletion_requested_at, NOW()) AS days_since
56 FROM `${DB}`.users WHERE id='$uid'
57~, $ENV{SCRIPT_NAME}, __LINE__);
58$db->db_disconnect($dbh);
59
60my $requested = $u->{account_deletion_requested_at} // '';
61my $days_left = $u->{days_since} ? (30 - $u->{days_since}) : 30;
62$days_left = 0 if $days_left < 0;
63
64my $body = '<div style="max-width:680px;margin:0 auto;padding:24px 28px;line-height:1.7;color:#e6ecf6">';
65$body .= '<h1 style="font-size:26px;color:#fff;margin:0 0 6px">Close my account</h1>';
66
67if ($flash eq 'requested') {
68 $body .= '<div style="background:#fbbf2422;border-left:3px solid #fbbf24;color:#fbbf24;padding:12px 16px;border-radius:8px;margin:14px 0">Deletion requested. You have 30 days to change your mind by clicking "Cancel deletion" below.</div>';
69} elsif ($flash eq 'cancelled') {
70 $body .= '<div style="background:#10b98122;border-left:3px solid #10b981;color:#10b981;padding:12px 16px;border-radius:8px;margin:14px 0">Deletion request cancelled. Your account is active.</div>';
71}
72
73if ($requested) {
74 $body .= '<section style="background:#0b1226;border:1px solid #fbbf24;border-radius:12px;padding:18px 22px;margin:14px 0">';
75 $body .= ' <div style="color:#fbbf24;font-size:16px;font-weight:600;margin-bottom:8px">Account deletion is scheduled</div>';
76 $body .= " <div style=\"color:#7e92b6\">Requested at " . _h($requested) . ". <b style=\"color:#fff\">$days_left days remaining</b> before the purge runs. Repricing is paused for this account until you cancel or the purge completes.</div>";
77 $body .= ' <form method="POST" style="margin-top:14px">';
78 $body .= ' <input type="hidden" name="act" value="cancel">';
79 $body .= ' <button type="submit" style="background:#064e3b;color:#a7f3d0;border:0;padding:10px 20px;border-radius:8px;font-weight:600;cursor:pointer">Cancel deletion &mdash; keep my account</button>';
80 $body .= ' </form>';
81 $body .= '</section>';
82} else {
83 $body .= '<p style="color:#7e92b6">Closing your account is a 2-step process so accidents are reversible:</p>';
84 $body .= '<ol style="color:#e6ecf6;padding-left:22px">';
85 $body .= ' <li>You request deletion below. We immediately pause all repricing on your account.</li>';
86 $body .= ' <li>30 days later, a worker permanently purges your row + tokens + products + price history. Until then, you can cancel from this same page.</li>';
87 $body .= '</ol>';
88 $body .= '<p style="color:#7e92b6">Stripe invoice records are retained for 7 years for tax / legal compliance, separate from your account row. Per <a href="/privacy.cgi" style="color:#14b8a6">privacy policy</a>.</p>';
89 $body .= '<p style="color:#7e92b6">If you have an active paid subscription, <a href="/billing.cgi" style="color:#14b8a6">cancel it first</a> &mdash; otherwise you&apos;ll keep getting charged through your current cycle.</p>';
90 $body .= '<form method="POST" style="margin-top:18px" onsubmit="return confirm(\'Request deletion? Your data is reversibly hidden for 30 days, then permanently purged.\')">';
91 $body .= ' <input type="hidden" name="act" value="request">';
92 $body .= ' <button type="submit" style="background:#ef4444;color:#fff;border:0;padding:10px 20px;border-radius:8px;font-weight:600;cursor:pointer">Request account deletion</button>';
93 $body .= ' &nbsp; <a href="/profile.cgi" style="color:#7e92b6;font-size:13px;text-decoration:none">Cancel &mdash; back to profile</a>';
94 $body .= '</form>';
95}
96
97$body .= '<div style="margin-top:18px;color:#7e92b6;font-size:12px"><a href="/account_export.cgi" style="color:#14b8a6">Download your data first</a> (recommended).</div>';
98$body .= '</div>';
99
100print "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";
101$wrap->render({ userinfo => $userinfo, title => 'Close my account', body => $body });
102exit;