Skip to content

Commit be5b8b8

Browse files
author
teycir
committed
feat(ui): add comprehensive input validations for seal creation
Implements robust input validation checks at the beginning of the handleCreateSeal function. This includes: - Ensuring Turnstile token is present. - Validating message content (not empty, max length 1MB). - Validating file size (max 25MB). - Comprehensive checks for 'timed' seals: unlock date existence, valid format, not in the past or now, at least 1 minute in the future, and not more than 20 years in the future. - Validating 'deadman's switch' pulse interval (between 1 and 90 days). These changes enhance user experience by providing immediate feedback on invalid inputs and improve the robustness of the sealing process.
1 parent f13e7b8 commit be5b8b8

1 file changed

Lines changed: 62 additions & 22 deletions

File tree

app/page.tsx

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,71 @@ export default function HomePage() {
158158
};
159159

160160
const handleCreateSeal = async () => {
161-
if ((!message.trim() && !file) || !turnstileToken) {
162-
toast.error('Please complete the security check and valid input');
161+
// Validate Turnstile
162+
if (!turnstileToken) {
163+
toast.error('Please complete the security check');
163164
return;
164165
}
165166

167+
// Validate content
168+
if (!message.trim() && !file) {
169+
toast.error('Please enter a message or upload a file');
170+
return;
171+
}
172+
173+
// Validate message length
174+
if (message.trim() && message.length > 1000000) {
175+
toast.error('Message too large (max 1MB)');
176+
return;
177+
}
178+
179+
// Validate file size
180+
if (file && file.size > 25 * 1024 * 1024) {
181+
toast.error('File too large (max 25MB)');
182+
return;
183+
}
184+
185+
// Validate date for timed release
186+
if (sealType === 'timed') {
187+
if (!unlockDate) {
188+
toast.error('Please select an unlock date and time');
189+
return;
190+
}
191+
192+
const selectedTime = new Date(unlockDate).getTime();
193+
const now = Date.now();
194+
const minTime = now + 60000;
195+
const maxTime = now + (20 * 365 * 24 * 60 * 60 * 1000);
196+
197+
if (Number.isNaN(selectedTime)) {
198+
toast.error('Invalid date format');
199+
return;
200+
}
201+
202+
if (selectedTime <= now) {
203+
toast.error('Unlock time cannot be in the past or now');
204+
return;
205+
}
206+
207+
if (selectedTime < minTime) {
208+
toast.error('Unlock time must be at least 1 minute in the future');
209+
return;
210+
}
211+
212+
if (selectedTime > maxTime) {
213+
toast.error('Unlock time cannot be more than 20 years in the future');
214+
return;
215+
}
216+
}
217+
218+
// Validate pulse interval for dead man's switch
219+
if (sealType === 'deadman') {
220+
if (pulseDays < 1 || pulseDays > 90) {
221+
toast.error('Pulse interval must be between 1 and 90 days');
222+
return;
223+
}
224+
}
225+
166226
setIsCreating(true);
167227
const loadingToast = toast.loading('Encrypting and sealing data...');
168228

@@ -176,30 +236,10 @@ export default function HomePage() {
176236
let pulseDuration: number | undefined;
177237

178238
if (sealType === 'timed') {
179-
if (!unlockDate) {
180-
toast.dismiss(loadingToast);
181-
toast.error('Please select a valid future date');
182-
return;
183-
}
184239
unlockTime = new Date(unlockDate).getTime();
185-
186-
const minTime = Date.now() + 60000; // 1 minute from now
187-
if (Number.isNaN(unlockTime) || unlockTime <= minTime) {
188-
toast.dismiss(loadingToast);
189-
toast.error('Unlock time must be at least 1 minute in the future');
190-
return;
191-
}
192240
} else {
193241
// Dead man's switch
194242
pulseDuration = pulseDays * 24 * 60 * 60 * 1000;
195-
196-
// Validate pulse interval
197-
if (pulseDays < 1 || pulseDays > 90) {
198-
toast.dismiss(loadingToast);
199-
toast.error('Pulse interval must be between 1 and 90 days');
200-
return;
201-
}
202-
203243
unlockTime = Date.now() + pulseDuration;
204244
pulseToken = crypto.randomUUID();
205245
}

0 commit comments

Comments
 (0)