Skip to content

Commit 33e3acc

Browse files
authored
refactor(login): use inputValidation on login page (@fehmer) (monkeytypegame#6866)
1 parent 119649b commit 33e3acc

File tree

8 files changed

+170
-384
lines changed

8 files changed

+170
-384
lines changed

frontend/src/ts/commandline/commandline.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,18 @@ import { areSortedArraysEqual, areUnsortedArraysEqual } from "../utils/arrays";
1515
import { parseIntOptional } from "../utils/numbers";
1616
import { debounce } from "throttle-debounce";
1717
import { intersect } from "@monkeytype/util/arrays";
18-
import { createInputEventHandler } from "../elements/input-validation";
18+
import {
19+
createInputEventHandler,
20+
ValidationResult,
21+
} from "../elements/input-validation";
1922

2023
type CommandlineMode = "search" | "input";
2124
type InputModeParams = {
2225
command: Command | null;
2326
placeholder: string | null;
2427
value: string | null;
2528
icon: string | null;
26-
validation?: {
27-
status: "checking" | "success" | "failed";
28-
errorMessage?: string;
29-
};
29+
validation?: ValidationResult;
3030
};
3131

3232
let activeIndex = 0;

frontend/src/ts/controllers/account-controller.ts

Lines changed: 4 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -404,66 +404,16 @@ async function signUp(): Promise<void> {
404404
LoginPage.disableInputs();
405405
LoginPage.disableSignUpButton();
406406
LoginPage.showPreloader();
407-
const nname = ($(".pageLogin .register input")[0] as HTMLInputElement).value;
408-
const email = ($(".pageLogin .register input")[1] as HTMLInputElement).value;
409-
const emailVerify = ($(".pageLogin .register input")[2] as HTMLInputElement)
410-
.value;
411-
const password = ($(".pageLogin .register input")[3] as HTMLInputElement)
412-
.value;
413-
const passwordVerify = (
414-
$(".pageLogin .register input")[4] as HTMLInputElement
415-
).value;
416-
417-
if (nname === "" || email === "" || emailVerify === "" || password === "") {
418-
LoginPage.hidePreloader();
419-
LoginPage.enableInputs();
420-
LoginPage.updateSignupButton();
421-
Notifications.add("Please fill in all fields", 0);
422-
return;
423-
}
424-
425-
if (
426-
!email.match(
427-
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
428-
)
429-
) {
430-
Notifications.add("Invalid email", 0);
431-
LoginPage.hidePreloader();
432-
LoginPage.enableInputs();
433-
LoginPage.updateSignupButton();
434-
return;
435-
}
436-
437-
if (email !== emailVerify) {
438-
Notifications.add("Emails do not match", 0);
439-
LoginPage.hidePreloader();
440-
LoginPage.enableInputs();
441-
LoginPage.updateSignupButton();
442-
return;
443-
}
444-
445-
if (password !== passwordVerify) {
446-
Notifications.add("Passwords do not match", 0);
447-
LoginPage.hidePreloader();
448-
LoginPage.enableInputs();
449-
LoginPage.updateSignupButton();
450-
return;
451-
}
452407

453-
// Force user to use a capital letter, number, special character and reasonable length when setting up an account and changing password
454-
if (!Misc.isDevEnvironment() && !Misc.isPasswordStrong(password)) {
455-
Notifications.add(
456-
"Password must contain at least one capital letter, number, a special character and must be between 8 and 64 characters long",
457-
0,
458-
{
459-
duration: 4,
460-
}
461-
);
408+
const signupData = LoginPage.getSignupData();
409+
if (signupData === false) {
462410
LoginPage.hidePreloader();
463411
LoginPage.enableInputs();
464412
LoginPage.updateSignupButton();
413+
Notifications.add("Please fill in all fields", 0);
465414
return;
466415
}
416+
const { name: nname, email, password } = signupData;
467417

468418
try {
469419
const createdAuthUser = await createUserWithEmailAndPassword(

frontend/src/ts/elements/input-validation.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Config, * as UpdateConfig from "../config";
1010
import * as Notifications from "../elements/notifications";
1111

1212
export type ValidationResult = {
13-
status: "checking" | "success" | "failed";
13+
status: "checking" | "success" | "failed" | "warning";
1414
errorMessage?: string;
1515
};
1616

@@ -28,7 +28,7 @@ export type Validation<T> = {
2828
* @param thisPopup the current modal
2929
* @returns true if the `value` is valid, an errorMessage as string if it is invalid.
3030
*/
31-
isValid?: (value: T) => Promise<true | string>;
31+
isValid?: (value: T) => Promise<true | string | { warning: string }>;
3232

3333
/** custom debounce delay for `isValid` call. defaults to 100 */
3434
debounceDelay?: number;
@@ -67,7 +67,17 @@ export function createInputEventHandler<T>(
6767
if (result === true) {
6868
callback({ status: "success" });
6969
} else {
70-
callback({ status: "failed", errorMessage: result });
70+
if (typeof result === "object" && "warning" in result) {
71+
callback({
72+
status: "warning",
73+
errorMessage: result.warning,
74+
});
75+
} else {
76+
callback({
77+
status: "failed",
78+
errorMessage: result,
79+
});
80+
}
7181
}
7282
}
7383
)
@@ -140,14 +150,18 @@ export function validateWithIndicator<T>(
140150
icon: "fa-times",
141151
level: -1,
142152
},
153+
warning: {
154+
icon: "fa-exclamation-triangle",
155+
level: 1,
156+
},
143157
checking: {
144158
icon: "fa-circle-notch",
145159
spinIcon: true,
146160
level: 0,
147161
},
148162
});
149163
const callback = (result: ValidationResult): void => {
150-
if (result.status === "failed") {
164+
if (result.status === "failed" || result.status === "warning") {
151165
indicator.show(result.status, result.errorMessage);
152166
} else {
153167
indicator.show(result.status);

frontend/src/ts/modals/forgot-password.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import AnimatedModal from "../utils/animated-modal";
33
import Ape from "../ape/index";
44
import * as Notifications from "../elements/notifications";
55
import * as Loader from "../elements/loader";
6-
import { z } from "zod";
6+
import { UserEmailSchema } from "@monkeytype/schemas/users";
77

88
export function show(): void {
99
if (!CaptchaController.isCaptchaAvailable()) {
@@ -47,9 +47,7 @@ async function submit(): Promise<void> {
4747
return;
4848
}
4949

50-
const emailSchema = z.string().email();
51-
52-
const validation = emailSchema.safeParse(email);
50+
const validation = UserEmailSchema.safeParse(email);
5351
if (!validation.success) {
5452
Notifications.add("Please enter a valid email address");
5553
CaptchaController.reset("forgotPasswordModal");

frontend/src/ts/modals/simple-modals.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import {
3939
} from "../utils/simple-modal";
4040
import { ShowOptions } from "../utils/animated-modal";
4141
import { GenerateDataRequest } from "@monkeytype/contracts/dev";
42-
import { UserEmailSchema, UserNameSchema } from "@monkeytype/contracts/users";
42+
import { UserEmailSchema, UserNameSchema } from "@monkeytype/schemas/users";
4343
import { goToPage } from "../pages/leaderboards";
4444
import FileStorage from "../utils/file-storage";
4545

0 commit comments

Comments
 (0)