Skip to content
This repository was archived by the owner on Jan 4, 2025. It is now read-only.

Commit f218be3

Browse files
authored
Merge pull request #98 from johnnygerard/ajv
feat: add JSON parsing and validation with ajv
2 parents e8b4e57 + 19a0321 commit f218be3

28 files changed

+307
-134
lines changed

client/e2e/log-in-user.function.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { expect, Page } from "@playwright/test";
22
import { CREATED } from "_server/constants/http-status-code";
3+
import { Credentials } from "_server/types/credentials";
34

45
/**
56
* Fill out and submit the login form while verifying the response status.
@@ -9,10 +10,7 @@ import { CREATED } from "_server/constants/http-status-code";
910
*/
1011
export const logInUser = async (
1112
page: Page,
12-
credentials: {
13-
username: string;
14-
password: string;
15-
},
13+
credentials: Credentials,
1614
expectedStatus = CREATED,
1715
): Promise<void> => {
1816
await page.goto("/sign-in");

client/e2e/register-user.function.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { faker } from "@faker-js/faker";
22
import { expect, Page } from "@playwright/test";
33
import { CREATED } from "_server/constants/http-status-code";
4+
import { Credentials } from "_server/types/credentials";
45

56
/**
67
* Fill out and submit the registration form while verifying the response status.
@@ -10,10 +11,7 @@ import { CREATED } from "_server/constants/http-status-code";
1011
*/
1112
export const registerUser = async (
1213
page: Page,
13-
credentials?: Partial<{
14-
username: string;
15-
password: string;
16-
}>,
14+
credentials?: Partial<Credentials>,
1715
expectedStatus = CREATED,
1816
): Promise<void> => {
1917
await page.goto("/register");

client/e2e/tests/session-revocation.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { expect, test } from "@playwright/test";
22
import { getFakeCredentials } from "_server/test-helpers/faker-extensions";
3+
import { Credentials } from "_server/types/credentials";
34
import { UserMessage } from "../../src/app/types/user-message.enum";
45
import { logInUser } from "../log-in-user.function";
56
import { registerUser } from "../register-user.function";
67

78
test.describe("Session revocation", () => {
8-
let credentials: { username: string; password: string };
9+
let credentials: Credentials;
910

1011
test.beforeEach(async ({ browser, page }) => {
1112
const context = await browser.newContext();

client/playwright.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import ms from "ms";
1111
* See https://playwright.dev/docs/test-configuration.
1212
*/
1313
export default defineConfig({
14-
timeout: ms("10 seconds"),
14+
timeout: ms("20 seconds"),
1515
globalTimeout: ms("5 minutes"),
1616
testDir: "./e2e",
1717
/* Run tests in files in parallel */

client/src/app/components/register-form/register-form.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ export class RegisterFormComponent {
136136
}
137137

138138
onSubmit(): void {
139-
if (!this.form.valid || this.isLoading()) return;
139+
if (this.form.invalid || this.isLoading()) return;
140140
if (this.#passwordStrength.isWorkerBusy()) {
141141
this.#shouldResubmit = true;
142142
return;

client/src/app/directives/username-validator.directive.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@ import {
55
ValidationErrors,
66
Validator,
77
} from "@angular/forms";
8-
import {
9-
usernameHasValidCharacters,
10-
usernameHasValidType,
11-
} from "_server/validation/username";
8+
import { hasValidUsernameCharacters } from "_server/validation/username";
129

1310
@Directive({
1411
selector: "[appUsernameValidator]",
@@ -25,8 +22,7 @@ export class UsernameValidatorDirective implements Validator {
2522
validate(control: AbstractControl): ValidationErrors | null {
2623
const username = control.value;
2724

28-
return usernameHasValidType(username) &&
29-
!usernameHasValidCharacters(username)
25+
return typeof username === "string" && !hasValidUsernameCharacters(username)
3026
? { pattern: "Invalid characters" }
3127
: null;
3228
}

server/package-lock.json

Lines changed: 44 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"dependencies": {
3+
"ajv": "^8.17.1",
34
"argon2": "^0.41.1",
45
"cookie-parser": "^1.4.7",
56
"cors": "^2.8.5",
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { faker } from "@faker-js/faker";
2+
import assert from "node:assert/strict";
3+
import { suite, test } from "node:test";
4+
import { getLeakedPassword } from "../test-helpers/leaked-passwords.js";
5+
import { isLeakedPassword } from "./is-leaked-password.js";
6+
7+
suite("The isLeakedPassword function", () => {
8+
test("returns true for a leaked password", async () => {
9+
const password = getLeakedPassword();
10+
const isLeaked = await isLeakedPassword(password);
11+
assert(isLeaked, `Password "${password}" is not leaked`);
12+
});
13+
14+
test("returns false for a non-leaked password", async () => {
15+
const password = faker.internet.password();
16+
const isLeaked = await isLeakedPassword(password);
17+
assert(!isLeaked, `Password "${password}" is leaked`);
18+
});
19+
});

server/src/auth/pwned-passwords-api.ts renamed to server/src/auth/is-leaked-password.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import { OK } from "../constants/http-status-code.js";
88
* This function queries the Pwned Passwords API using the k-Anonymity model
99
* (only a partial digest of the hashed password is sent).
1010
* @param password - Plaintext password
11-
* @returns `false` if the password is not exposed or the API server did not
12-
* reply in time with the 200 status code, `true` if the password is exposed.
11+
* @returns `false` if the password is not leaked or the API server did not
12+
* reply in time with the 200 status code, `true` if the password is leaked.
1313
* @see https://haveibeenpwned.com/API/v3#PwnedPasswords
1414
*/
15-
export const isPasswordExposed = async (password: string): Promise<boolean> => {
15+
export const isLeakedPassword = async (password: string): Promise<boolean> => {
1616
try {
1717
const digest = hash("sha1", password);
1818
const partialDigest = digest.slice(0, 5);

0 commit comments

Comments
 (0)