Skip to content

Commit

Permalink
Refactor the routes
Browse files Browse the repository at this point in the history
  • Loading branch information
Dlurak committed Mar 28, 2024
1 parent 897f80e commit 882dc4a
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 124 deletions.
129 changes: 5 additions & 124 deletions src/routes/auth/index.ts
Original file line number Diff line number Diff line change
@@ -1,126 +1,7 @@
import e from "@edgedb";
import { Elysia, t } from "elysia";
import { HttpStatusCode } from "elysia-http-status-code";
import { client } from "index";
import { passowrdAuthSecret } from "schemas/auth";
import { createToken } from "utils/auth/jwt";
import { isUsernameTaken } from "utils/db/users";
import { randomNumber } from "utils/random";
import { wait } from "utils/time";
import { Elysia } from "elysia";
import { refreshTokenRouter } from "./refreshToken";
import { registerRouter } from "./register";

export const router = new Elysia({ prefix: "/auth" })
.group("/register", (app) =>
app.use(HttpStatusCode()).post(
"/password",
async ({ body, set, httpStatus }) => {
if (await isUsernameTaken(body.username)) {
set.status = httpStatus.HTTP_400_BAD_REQUEST;
return {
status: "error",
error: "Username already taken",
};
}

const creationQuery = e.insert(e.User, {
username: body.username,
displayname: body.displayname,
authmethod: e.Authmethod.Password,
authsecret: { password: await Bun.password.hash(body.password) },
});

return creationQuery
.run(client)
.then((data) => ({
status: "success",
message: "User created successfully",
data: {
id: data.id,
usernmae: body.username,
},
}))
.catch((e) => {
console.error(e);
set.status = httpStatus.HTTP_500_INTERNAL_SERVER_ERROR;
return {
status: "error",
error: "An error occurred while creating the user",
};
});
},
{
body: t.Object({
username: t.String({
minLength: 1,
}),
displayname: t.String({
minLength: 1,
}),
password: t.RegExp(
/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$ %^&*-]).{8,}$/,
),
}),
},
),
)
.group("/refresh-token", (app) =>
app.use(HttpStatusCode()).post(
"/password",
async ({ body, set, httpStatus }) => {
const notMatchingReturn = {
status: "error",
error: "Username or password is incorrect",
};

const user = await e
.select(e.User, (u) => ({
authsecret: true,
filter: e.op(u.username, "=", body.username),
}))
.run(client);

if (user.length === 0) {
// to prevent timing attacks, we wait a random amount of time
await wait(randomNumber(90, 130));
set.status = httpStatus.HTTP_401_UNAUTHORIZED;
return notMatchingReturn;
}

const expectedPwdHash = passowrdAuthSecret.safeParse(
user[0].authsecret,
);
if (!expectedPwdHash.success) {
set.status = httpStatus.HTTP_500_INTERNAL_SERVER_ERROR;
return {
status: "error",
error: "An error occurred while verifying the user",
};
}

const isPasswordCorrect = await Bun.password.verify(
body.password,
expectedPwdHash.data.password,
);
if (!isPasswordCorrect) {
set.status = httpStatus.HTTP_401_UNAUTHORIZED;
return notMatchingReturn;
}

const { token, expiresIn } = createToken({
username: body.username,
type: "refresh",
});

return {
status: "success",
message: "Token generated successfully",
data: { token, expiresIn },
};
},
{
body: t.Object({
username: t.String({ minLength: 1 }),
password: t.String({ minLength: 1 }),
}),
},
),
);
.use(registerRouter)
.use(refreshTokenRouter);
69 changes: 69 additions & 0 deletions src/routes/auth/refreshToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import e from "@edgedb";
import { Elysia, t } from "elysia";
import { HttpStatusCode } from "elysia-http-status-code";
import { client } from "index";
import { passowrdAuthSecret } from "schemas/auth";
import { createToken } from "utils/auth/jwt";
import { randomNumber } from "utils/random";
import { wait } from "utils/time";

export const refreshTokenRouter = new Elysia({ prefix: "/refresh-token" })
.use(HttpStatusCode())
.post(
"/password",
async ({ body, set, httpStatus }) => {
const notMatchingReturn = {
status: "error",
error: "Username or password is incorrect",
};

const user = await e
.select(e.User, (u) => ({
authsecret: true,
filter: e.op(u.username, "=", body.username),
}))
.run(client);

if (user.length === 0) {
// to prevent timing attacks, we wait a random amount of time
await wait(randomNumber(90, 130));
set.status = httpStatus.HTTP_401_UNAUTHORIZED;
return notMatchingReturn;
}

const expectedPwdHash = passowrdAuthSecret.safeParse(user[0].authsecret);
if (!expectedPwdHash.success) {
set.status = httpStatus.HTTP_500_INTERNAL_SERVER_ERROR;
return {
status: "error",
error: "An error occurred while verifying the user",
};
}

const isPasswordCorrect = await Bun.password.verify(
body.password,
expectedPwdHash.data.password,
);
if (!isPasswordCorrect) {
set.status = httpStatus.HTTP_401_UNAUTHORIZED;
return notMatchingReturn;
}

const { token, expiresIn } = createToken({
username: body.username,
type: "refresh",
});

return {
status: "success",
message: "Token generated successfully",
data: { token, expiresIn },
};
},
{
body: t.Object({
username: t.String({ minLength: 1 }),
password: t.String({ minLength: 1 }),
}),
},
);
59 changes: 59 additions & 0 deletions src/routes/auth/register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import e from "@edgedb";
import { Elysia, t } from "elysia";
import { HttpStatusCode } from "elysia-http-status-code";
import { client } from "index";
import { isUsernameTaken } from "utils/db/users";

export const registerRouter = new Elysia({ prefix: "/register" })
.use(HttpStatusCode())
.post(
"/password",
async ({ body, set, httpStatus }) => {
if (await isUsernameTaken(body.username)) {
set.status = httpStatus.HTTP_400_BAD_REQUEST;
return {
status: "error",
error: "Username already taken",
};
}

const creationQuery = e.insert(e.User, {
username: body.username,
displayname: body.displayname,
authmethod: e.Authmethod.Password,
authsecret: { password: await Bun.password.hash(body.password) },
});

return creationQuery
.run(client)
.then((data) => ({
status: "success",
message: "User created successfully",
data: {
id: data.id,
usernmae: body.username,
},
}))
.catch((e) => {
console.error(e);
set.status = httpStatus.HTTP_500_INTERNAL_SERVER_ERROR;
return {
status: "error",
error: "An error occurred while creating the user",
};
});
},
{
body: t.Object({
username: t.String({
minLength: 1,
}),
displayname: t.String({
minLength: 1,
}),
password: t.RegExp(
/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$ %^&*-]).{8,}$/,
),
}),
},
);

0 comments on commit 882dc4a

Please sign in to comment.