-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathverify.html
More file actions
215 lines (188 loc) · 9.61 KB
/
verify.html
File metadata and controls
215 lines (188 loc) · 9.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>4SP - VERIFY</title>
<meta name="description" content="Processing your authentication request...">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
<script src="https://cdn.tailwindcss.com"></script>
<script src="../navigation-mini.js"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
'custom-darkest-gray': '#040404',
'custom-dark-gray': '#111111',
'custom-medium-gray': '#252525',
'custom-light-gray': '#505050',
'custom-lighter-gray': '#808080',
'custom-white-gray': '#c0c0c0',
}
}
}
}
</script>
<style>
:root {
--geist-foreground: 192, 192, 192;
--geist-background: 7, 7, 7;
}
body {
font-family: 'Geist', sans-serif;
background-color: rgb(var(--geist-background));
color: rgb(var(--geist-foreground));
transition: all 0.3s ease;
font-weight: 300;
}
h1, h2, h3, .font-bold, .font-semibold, strong, .tracking-tighter {
font-weight: 400 !important;
}
.message-area { min-height: 20px; }
.error-message { color: #f87171; font-weight: 400; }
.success-message { color: #4ade80; font-weight: 400; }
.warning-message { color: #fbbf24; font-weight: 400; }
</style>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-1D4F692C1Q"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-1D4F692C1Q');
</script>
</head>
<body class="bg-custom-darkest-gray text-custom-white-gray min-h-screen flex flex-col items-center justify-center p-4">
<div class="w-full max-w-md p-8 bg-custom-dark-gray border border-custom-medium-gray rounded-xl shadow-2xl text-center">
<i id="actionIcon" class="fas fa-circle-notch fa-spin text-5xl text-blue-500 mb-6"></i>
<h1 id="actionTitle" class="text-3xl font-normal tracking-tighter mb-4">Processing...</h1>
<p id="actionMessage" class="text-custom-light-gray text-lg font-light mb-6">
Please wait while we process your request.
</p>
<!-- Hidden form for password reset -->
<div id="passwordResetForm" class="hidden text-left">
<div class="mb-5">
<label for="newPassword" class="block mb-2 text-custom-light-gray text-sm font-light">New Password</label>
<input type="password" id="newPassword" placeholder="Enter new password" class="w-full p-3 border border-custom-medium-gray bg-custom-darkest-gray rounded-xl text-custom-white-gray transition focus:border-custom-light-gray focus:ring focus:ring-custom-light-gray/50 focus:outline-none">
</div>
<button id="savePasswordBtn" class="w-full p-3 text-lg rounded-xl font-normal ring-1 ring-white/20 text-white bg-white/5 hover:bg-white/10 transition">
SAVE PASSWORD
</button>
</div>
<div id="actionButtons" class="hidden space-y-3">
<a href="authentication.html" class="block w-full p-3 text-lg rounded-xl font-normal ring-1 ring-white/20 text-white bg-white/5 hover:bg-white/10 transition">
Back to Login
</a>
</div>
</div>
<footer class="border-t border-gray-900 py-6">
<div class="mx-auto max-w-7xl px-4 text-center text-gray-500 text-sm">
© 2025 4simpleproblems (4SP). Built for students.
<span class="mx-2">|</span>
<a href="legal.html#terms-of-service" class="hover:underline">Terms of Service</a>
<span class="mx-2">|</span>
<a href="legal.html#privacy-policy" class="hover:underline">Privacy Policy</a>
</div>
</footer>
<script type="module">
import { initializeApp } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-app.js";
import {
getAuth,
applyActionCode,
verifyPasswordResetCode,
confirmPasswordReset
} from "https://www.gstatic.com/firebasejs/10.12.2/firebase-auth.js";
import { firebaseConfig } from "./firebase-config.js";
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const actionIcon = document.getElementById('actionIcon');
const actionTitle = document.getElementById('actionTitle');
const actionMessage = document.getElementById('actionMessage');
const actionButtons = document.getElementById('actionButtons');
const passwordResetForm = document.getElementById('passwordResetForm');
const savePasswordBtn = document.getElementById('savePasswordBtn');
const newPasswordInput = document.getElementById('newPassword');
function showStatus(title, message, iconClass = 'fas fa-info-circle', isError = false) {
actionTitle.textContent = title;
actionMessage.innerHTML = message;
actionIcon.className = `${iconClass} text-5xl mb-6 ${isError ? 'text-red-500' : 'text-green-500'}`;
if (isError) {
actionButtons.classList.remove('hidden');
}
}
document.addEventListener('DOMContentLoaded', async () => {
const params = new URLSearchParams(window.location.search);
const mode = params.get('mode');
const actionCode = params.get('oobCode');
if (!mode || !actionCode) {
showStatus('Invalid Link', 'This link is invalid or has expired.', 'fas fa-times-circle', true);
return;
}
switch (mode) {
case 'verifyEmail':
handleVerifyEmail(auth, actionCode);
break;
case 'resetPassword':
handleResetPassword(auth, actionCode);
break;
case 'recoverEmail':
// Handle email recovery if needed, or show generic message
showStatus('Email Recovery', 'Please contact support to recover your email.', 'fas fa-envelope', true);
break;
default:
showStatus('Unknown Action', 'The request mode is unknown.', 'fas fa-question-circle', true);
}
});
async function handleVerifyEmail(auth, actionCode) {
try {
await applyActionCode(auth, actionCode);
showStatus('Email Verified!', 'Your email has been successfully verified. You can now access your account.', 'fas fa-check-circle');
actionButtons.classList.remove('hidden');
// Auto redirect
setTimeout(() => {
window.location.href = 'logged-in/dashboard.html';
}, 3000);
} catch (error) {
console.error('Verify Email Error:', error);
showStatus('Verification Failed', 'The verification link is invalid or has expired. Please request a new one.', 'fas fa-times-circle', true);
}
}
async function handleResetPassword(auth, actionCode) {
try {
const email = await verifyPasswordResetCode(auth, actionCode);
// Show form
actionIcon.className = 'fas fa-key text-5xl text-blue-500 mb-6';
actionTitle.textContent = 'Reset Password';
actionMessage.textContent = `Enter a new password for ${email}.`;
passwordResetForm.classList.remove('hidden');
savePasswordBtn.addEventListener('click', async () => {
const newPassword = newPasswordInput.value;
if (newPassword.length < 6) {
alert('Password must be at least 6 characters.');
return;
}
try {
savePasswordBtn.disabled = true;
savePasswordBtn.textContent = 'Saving...';
await confirmPasswordReset(auth, actionCode, newPassword);
passwordResetForm.classList.add('hidden');
showStatus('Password Reset!', 'Your password has been updated. You can now log in.', 'fas fa-check-circle');
actionButtons.classList.remove('hidden');
} catch (error) {
console.error('Confirm Reset Error:', error);
alert('Failed to reset password: ' + error.message);
savePasswordBtn.disabled = false;
savePasswordBtn.textContent = 'SAVE PASSWORD';
}
});
} catch (error) {
console.error('Verify Code Error:', error);
showStatus('Invalid Link', 'This password reset link is invalid or has expired.', 'fas fa-times-circle', true);
}
}
</script>
</body>
</html>