Skip to content

Commit

Permalink
Add an endpoint to get a list of requests or the own request
Browse files Browse the repository at this point in the history
  • Loading branch information
Dlurak committed Mar 30, 2024
1 parent b049142 commit 1cc4224
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 9 deletions.
9 changes: 6 additions & 3 deletions src/routes/moderation/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import Elysia from "elysia";
import { createJoinRequest } from "./create";
import { listJoinRequests } from "./list";
import { ownJoinRequest } from "./own";

export const moderationRouter = new Elysia({ prefix: "/mod" }).use(
createJoinRequest,
);
export const moderationRouter = new Elysia({ prefix: "/mod" })
.use(ownJoinRequest("/own"))
.use(createJoinRequest)
.use(listJoinRequests);
67 changes: 67 additions & 0 deletions src/routes/moderation/list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import e from "@edgedb";
import { DATABASE_READ_FAILED, UNAUTHORIZED } from "constants/responses";
import Elysia, { t } from "elysia";
import { HttpStatusCode } from "elysia-http-status-code";
import { client } from "index";
import { auth } from "plugins/auth";
import { promiseResult } from "utils/errors";
import { replaceDateWithTimestamp } from "utils/objects/transform";
import { responseBuilder } from "utils/response";

export const listJoinRequests = new Elysia()
.use(HttpStatusCode())
.use(auth)
.get("/", async ({ set, auth, httpStatus }) => {
if (!auth.isAuthorized) {
set.status = httpStatus.HTTP_401_UNAUTHORIZED;
return UNAUTHORIZED;
}

const joinRequestsQuery = e.select(e.JoinRequest, (jr) => {
const classMatches = e.op(
jr.wantsToJoin.students.username,
"=",
auth.username,
);

return {
filter: classMatches,

user: () => ({
username: true,
displayname: true,
created: true,
classes: () => ({
name: true,
school: () => ({ name: true }),
}),
}),
wantsToJoin: () => ({
name: true,
school: () => ({ name: true }),
}),
status: true,
created: true,
reviewedAt: true,
reviewedBy: () => ({
username: true,
displayname: true,
}),
id: true,
};
});
const joinRequests = await promiseResult(() =>
joinRequestsQuery.run(client),
);

if (joinRequests.isError) {
set.status = httpStatus.HTTP_500_INTERNAL_SERVER_ERROR;
return DATABASE_READ_FAILED;
}

const responseData = joinRequests.data.map(replaceDateWithTimestamp);
return responseBuilder("success", {
message: `Successfully retrieved join requests ${auth.username} can review`,
data: responseData,
});
});
57 changes: 57 additions & 0 deletions src/routes/moderation/own.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import e from "@edgedb";
import { DATABASE_READ_FAILED, UNAUTHORIZED } from "constants/responses";
import Elysia from "elysia";
import { HttpStatusCode } from "elysia-http-status-code";
import { client } from "index";
import { auth } from "plugins/auth";
import { promiseResult } from "utils/errors";
import { replaceDateWithTimestamp } from "utils/objects/transform";
import { responseBuilder } from "utils/response";

export const ownJoinRequest = (path: string) =>
new Elysia()
.use(auth)
.use(HttpStatusCode())
.get(path, async ({ auth, httpStatus, set }) => {
if (!auth.isAuthorized) {
set.status = httpStatus.HTTP_401_UNAUTHORIZED;
return UNAUTHORIZED;
}

const joinRequestQuery = e.select(e.JoinRequest, (jr) => ({
filter: e.op(jr.user.username, "=", auth.username),

status: true,
created: true,
reviewedAt: true,
reviewedBy: () => ({
username: true,
displayname: true,
}),
wantsToJoin: () => ({
name: true,
school: () => ({ name: true }),
}),
}));

const joinRequest = await promiseResult(() =>
joinRequestQuery.run(client),
);

if (joinRequest.isError) {
set.status = httpStatus.HTTP_500_INTERNAL_SERVER_ERROR;
return DATABASE_READ_FAILED;
}
if (!joinRequest.data) {
set.status = httpStatus.HTTP_404_NOT_FOUND;
return responseBuilder("error", {
error: `No join request found for user ${auth.username}`,
});
}

const responseData = joinRequest.data.map(replaceDateWithTimestamp);
return responseBuilder("success", {
message: `Successfully retrieved join request for ${auth.username}`,
data: responseData,
});
});
18 changes: 12 additions & 6 deletions src/utils/objects/transform.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
type Object = Record<string | number | symbol, unknown>;

type ConvertDatesOther<T extends Object, R> = {
[K in keyof T]: T[K] extends Date ? R : T[K];
type ConverDatesDeep<T extends Object, R> = {
[K in keyof T]: T[K] extends Date
? R
: T[K] extends Object
? ConverDatesDeep<T[K], R>
: T[K];
};

type DateCallback<T> = (val: Date) => T;

export const replaceDate = <T extends Object, R>(
export const replaceDateDeep = <T extends Object, R>(
obj: T,
callback: DateCallback<R>,
): ConvertDatesOther<T, R> => {
): ConverDatesDeep<T, R> => {
const pairs = Object.entries(obj);
const newPairs: [string, unknown][] = [];
for (const [key, val] of pairs) {
if (val instanceof Date) newPairs.push([key, callback(val)]);
else if (typeof val === "object" && val)
newPairs.push([key, replaceDateDeep(val as Object, callback)]);
else newPairs.push([key, val]);
}

return Object.fromEntries(newPairs) as ConvertDatesOther<T, R>;
return Object.fromEntries(newPairs) as ConverDatesDeep<T, R>;
};

/**
* Replaces all Date objects in an object with their timestamp
*/
export const replaceDateWithTimestamp = <T extends Object>(obj: T) =>
replaceDate(obj, (val) => val.getTime());
replaceDateDeep(obj, (val) => val.getTime());
20 changes: 20 additions & 0 deletions tests/objects/transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,24 @@ describe("transform", () => {
string: "hello",
});
});

it("works recursively", () => {
const obj = {
date: new Date("2021-01-01"),
inner: {
date: new Date("2021-01-01"),
number: 1,
string: "hello",
},
};

expect(replaceDateWithTimestamp(obj)).toEqual({
date: 1609459200000,
inner: {
date: 1609459200000,
number: 1,
string: "hello",
},
});
});
});

0 comments on commit 1cc4224

Please sign in to comment.