Skip to content

Commit

Permalink
feat: add backdoor endpoint for test code
Browse files Browse the repository at this point in the history
  • Loading branch information
solufa committed Jun 19, 2024
1 parent 48050ca commit 2fe57b0
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 53 deletions.
48 changes: 48 additions & 0 deletions server/api/backdoor/controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { UserEntity } from 'api/@types/user';
import { userMethod } from 'domain/user/model/userMethod';
import { userCommand } from 'domain/user/repository/userCommand';
import { genCredentials } from 'domain/user/service/genCredentials';
import { genTokens } from 'domain/user/service/genTokens';
import { userPoolQuery } from 'domain/userPool/repository/userPoolQuery';
import { DEFAULT_USER_POOL_CLIENT_ID, DEFAULT_USER_POOL_ID } from 'service/envValues';
import { prismaClient } from 'service/prismaClient';
import { genJwks } from 'service/privateKey';
import { defineController } from './$relay';

// サインアップフローを省略してテストを書くためのエンドポイント
// 200行まではcontrollerにべた書きで良い
export default defineController(() => ({
post: async ({ body }) => {
const { salt, verifier } = genCredentials({
poolId: DEFAULT_USER_POOL_ID,
username: body.username,
password: body.password,
});
const user: UserEntity = {
...userMethod.createUser({
name: body.username,
email: body.email,
salt,
verifier,
userPoolId: DEFAULT_USER_POOL_ID,
}),
verified: true,
};

await userCommand.save(prismaClient, user);

const pool = await userPoolQuery.findById(prismaClient, DEFAULT_USER_POOL_ID);
const jwks = await genJwks(pool.privateKey);
const tokens = genTokens({
privateKey: pool.privateKey,
userPoolClientId: DEFAULT_USER_POOL_CLIENT_ID,
jwks,
user,
});

return {
status: 200,
body: { ...tokens, ExpiresIn: 3600, RefreshToken: user.refreshToken, TokenType: 'Bearer' },
};
},
}));
13 changes: 13 additions & 0 deletions server/api/backdoor/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { RespondToAuthChallengeTarget } from 'api/@types/auth';
import type { DefineMethods } from 'aspida';

export type Methods = DefineMethods<{
post: {
reqBody: {
username: string;
email: string;
password: string;
};
resBody: RespondToAuthChallengeTarget['resBody']['AuthenticationResult'];
};
}>;
12 changes: 12 additions & 0 deletions server/api/private/backdoor/controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { prismaClient } from 'service/prismaClient';
import { defineController } from './$relay';

// サインアップフローを省略してテストを書くためのエンドポイント
// 200行まではcontrollerにべた書きで良い
export default defineController(() => ({
delete: async ({ user }) => {
await prismaClient.user.delete({ where: { id: user.id } });

return { status: 204 };
},
}));
5 changes: 5 additions & 0 deletions server/api/private/backdoor/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { DefineMethods } from 'aspida';

export type Methods = DefineMethods<{
delete: { status: 204 };
}>;
57 changes: 7 additions & 50 deletions server/tests/api/apiClient.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
import aspida from '@aspida/axios';
import api from 'api/$api';
import type { UserEntity } from 'api/@types/user';
import axios from 'axios';
import { genConfirmationCode } from 'domain/user/service/genConfirmationCode';
import { genVerifier } from 'domain/user/service/genCredentials';
import { genTokens } from 'domain/user/service/genTokens';
import { brandedId } from 'service/brandedId';
import { COOKIE_NAME } from 'service/constants';
import { DEFAULT_USER_POOL_CLIENT_ID, DEFAULT_USER_POOL_ID, PORT } from 'service/envValues';
import { prismaClient } from 'service/prismaClient';
import { genJwks } from 'service/privateKey';
import { PORT } from 'service/envValues';
import { ulid } from 'ulid';

const baseURL = `http://127.0.0.1:${PORT}`;
Expand All @@ -19,52 +12,16 @@ export const noCookieClient = api(
);

export const createUserClient = async (): Promise<typeof noCookieClient> => {
const salt = 'test-client-salt';
const verifier = genVerifier({
poolId: DEFAULT_USER_POOL_ID,
username: 'test-client',
password: 'test-client-password',
salt,
});
const user: UserEntity = {
id: brandedId.user.entity.parse(ulid()),
email: `${ulid()}@example.com`,
name: 'test-client',
verified: true,
confirmationCode: genConfirmationCode(),
salt,
verifier,
refreshToken: ulid(),
userPoolId: DEFAULT_USER_POOL_ID,
createdTime: Date.now(),
};
await prismaClient.user.create({
data: {
id: user.id,
email: user.email,
name: user.name,
verified: true,
confirmationCode: genConfirmationCode(),
salt: user.salt,
verifier: user.verifier,
refreshToken: user.refreshToken,
userPoolId: DEFAULT_USER_POOL_ID,
createdAt: new Date(user.createdTime),
const tokens = await noCookieClient.backdoor.$post({
body: {
username: 'test-client',
email: `${ulid()}@example.com`,
password: 'test-client-password',
},
});
const pool = await prismaClient.userPool.findUniqueOrThrow({
where: { id: DEFAULT_USER_POOL_ID },
});
const jwks = await genJwks(pool.privateKey);
const { IdToken } = genTokens({
privateKey: pool.privateKey,
userPoolClientId: DEFAULT_USER_POOL_CLIENT_ID,
jwks,
user,
});
const agent = axios.create({
baseURL,
headers: { cookie: `${COOKIE_NAME}=${IdToken}`, 'Content-Type': 'text/plain' },
headers: { cookie: `${COOKIE_NAME}=${tokens.IdToken}`, 'Content-Type': 'text/plain' },
});

agent.interceptors.response.use(undefined, (err) =>
Expand Down
2 changes: 2 additions & 0 deletions server/tests/api/private.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ test(GET(noCookieClient.private), async () => {
expect(res).toEqual('');

await expect(noCookieClient.private.get()).rejects.toHaveProperty('response.status', 401);
await userClient.private.backdoor.$delete();
});

test(GET(noCookieClient.private.me), async () => {
const userClient = await createUserClient();
const res = await userClient.private.me.get();

expect(res.status).toBe(200);
await userClient.private.backdoor.$delete();
});
8 changes: 5 additions & 3 deletions server/tests/api/signIn.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { N, g } from 'domain/user/service/srp/constants';
import { fromBuffer, toBuffer } from 'domain/user/service/srp/util';
import { DEFAULT_USER_POOL_CLIENT_ID } from 'service/envValues';
import { expect, test } from 'vitest';
import { createUserClient } from './apiClient';
import { createUserClient, noCookieClient } from './apiClient';

test('signIn', async () => {
const noCookieClient = await createUserClient();
const userClient = await createUserClient();
const a = crypto.randomBytes(32);
const A = toBuffer(g.modPow(fromBuffer(a), N));
const res1 = await noCookieClient.$post({
Expand All @@ -26,7 +26,7 @@ test('signIn', async () => {
secretBlock,
username: 'test-client',
password: 'test-client-password',
salt: 'test-client-salt',
salt: res1.ChallengeParameters.SALT,
timestamp: 'Thu Jan 01 00:00:00 UTC 1970',
A: A.toString('hex'),
a: fromBuffer(a),
Expand Down Expand Up @@ -73,4 +73,6 @@ test('signIn', async () => {
});

expect(res3.status).toBe(200);

await userClient.private.backdoor.$delete();
});

0 comments on commit 2fe57b0

Please sign in to comment.