refactor user/checkName to return the status

This commit is contained in:
Christian Fehmer 2025-09-11 01:22:02 +02:00
parent 5314e3f572
commit addfcd3658
No known key found for this signature in database
GPG key ID: FE53784A69964062
7 changed files with 44 additions and 32 deletions

View file

@ -238,8 +238,8 @@ describe("user controller test", () => {
//THEN
expect(body).toEqual({
message: "Username available",
data: null,
message: "Check username",
data: { availability: "available" },
});
expect(userIsNameAvailableMock).toHaveBeenCalledWith("bob", "");
});
@ -252,10 +252,13 @@ describe("user controller test", () => {
const { body } = await mockApp
.get("/users/checkName/bob")
//no authentication required
.expect(409);
.expect(200);
//THEN
expect(body.message).toEqual("Username unavailable");
expect(body).toEqual({
message: "Check username",
data: { availability: "taken" },
});
expect(userIsNameAvailableMock).toHaveBeenCalledWith("bob", "");
});
@ -271,8 +274,8 @@ describe("user controller test", () => {
//THEN
expect(body).toEqual({
message: "Username available",
data: null,
message: "Check username",
data: { availability: "available" },
});
expect(userIsNameAvailableMock).toHaveBeenCalledWith("bob", uid);
});

View file

@ -51,6 +51,7 @@ import {
AddTagRequest,
AddTagResponse,
CheckNamePathParameters,
CheckNameResponse,
CreateUserRequest,
DeleteCustomThemeRequest,
EditCustomThemeRequst,
@ -430,16 +431,15 @@ export async function optOutOfLeaderboards(
export async function checkName(
req: MonkeyRequest<undefined, undefined, CheckNamePathParameters>
): Promise<MonkeyResponse> {
): Promise<CheckNameResponse> {
const { name } = req.params;
const { uid } = req.ctx.decodedToken;
const available = await UserDAL.isNameAvailable(name, uid);
if (!available) {
throw new MonkeyError(409, "Username unavailable");
}
return new MonkeyResponse("Username available", null);
return new MonkeyResponse("Check username", {
availability: available ? "available" : "taken",
});
}
export async function updateEmail(

View file

@ -155,13 +155,14 @@ function disableInput(): void {
validateWithIndicator(nameInputEl, {
schema: UserNameSchema,
isValid: async (name: string) => {
const checkNameResponse = (
await Ape.users.getNameAvailability({
params: { name: name },
})
).status;
const checkNameResponse = await Ape.users.getNameAvailability({
params: { name: name },
});
return checkNameResponse === 200 ? true : "Name not available";
return checkNameResponse.status === 200 &&
checkNameResponse.body.data.availability === "available"
? true
: "Name not available";
},
debounceDelay: 1000,
callback: (result) => {

View file

@ -476,13 +476,14 @@ list.updateName = new SimpleModal({
validation: {
schema: UserNameSchema,
isValid: async (newName: string) => {
const checkNameResponse = (
await Ape.users.getNameAvailability({
params: { name: newName },
})
).status;
const checkNameResponse = await Ape.users.getNameAvailability({
params: { name: newName },
});
return checkNameResponse === 200 ? true : "Name not available";
return checkNameResponse.status === 200 &&
checkNameResponse.body.data.availability === "available"
? true
: "Name not available";
},
debounceDelay: 1000,
},

View file

@ -64,13 +64,14 @@ const nameInputEl = document.querySelector(
validateWithIndicator(nameInputEl, {
schema: UserNameSchema,
isValid: async (name: string) => {
const checkNameResponse = (
await Ape.users.getNameAvailability({
params: { name: name },
})
).status;
const checkNameResponse = await Ape.users.getNameAvailability({
params: { name: name },
});
return checkNameResponse === 200 ? true : "Name not available";
return checkNameResponse.status === 200 &&
checkNameResponse.body.data.availability === "available"
? true
: "Name not available";
},
debounceDelay: 1000,
callback: (result) => {

View file

@ -37,5 +37,5 @@ export const contract = c.router({
* Whenever there is a breaking change with old frontend clients increase this number.
* This will inform the frontend to refresh.
*/
export const COMPATIBILITY_CHECK = 3;
export const COMPATIBILITY_CHECK = 4;
export const COMPATIBILITY_CHECK_HEADER = "X-Compatibility-Check";

View file

@ -59,6 +59,13 @@ export type CheckNamePathParameters = z.infer<
typeof CheckNamePathParametersSchema
>;
export const CheckNameResponseSchema = responseWithData(
z.object({
availability: z.enum(["available", "taken"]),
})
);
export type CheckNameResponse = z.infer<typeof CheckNameResponseSchema>;
export const UpdateUserNameRequestSchema = z.object({
name: UserNameSchema,
});
@ -364,8 +371,7 @@ export const usersContract = c.router(
path: "/checkName/:name",
pathParams: CheckNamePathParametersSchema.strict(),
responses: {
200: MonkeyResponseSchema.describe("Name is available"),
409: MonkeyResponseSchema.describe("Name is not available"),
200: CheckNameResponseSchema,
},
metadata: meta({
authenticationOptions: { isPublic: true },