Refactor /me routes

This commit is contained in:
Dominic Ferrando
2026-09-26 16:07:21 -04:00
parent d2c31ba9fa
commit 0d9b8fb4fa
2 changed files with 87 additions and 94 deletions
+83 -90
View File
@@ -458,6 +458,7 @@ export const app = new Elysia()
// ACCOUNTS // ACCOUNTS
.group("/accounts", (app) => app .group("/accounts", (app) => app
// TODO: for added security, could enforce bot or admin only access
.get("/:id/stats", async ({ params: { id } }) => { .get("/:id/stats", async ({ params: { id } }) => {
const stats = await s.Accounts.stats(id); const stats = await s.Accounts.stats(id);
if (!stats) throw new NotFoundError("Account stats not found"); if (!stats) throw new NotFoundError("Account stats not found");
@@ -465,13 +466,6 @@ export const app = new Elysia()
}, { }, {
params: t.Object({ id: t.String() }) params: t.Object({ id: t.String() })
}) })
.guard({ auth: true }, (app) => app
.get("/me/stats", async ({ accountId }) => {
const stats = await s.Accounts.stats(accountId);
if (!stats) throw new NotFoundError("Account stats not found");
return stats;
})
)
.guard({ authAdmin: true }, (app) => app .guard({ authAdmin: true }, (app) => app
.get("/:id", async ({ params: { id } }) => { .get("/:id", async ({ params: { id } }) => {
const account = await s.Accounts.get(id); const account = await s.Accounts.get(id);
@@ -481,12 +475,13 @@ export const app = new Elysia()
params: t.Object({ id: t.String() }) params: t.Object({ id: t.String() })
}) })
) )
) .group("/me", { auth: true }, (app) => app
.get("/stats", async ({ accountId }) => {
// ASSESSMENTS const stats = await s.Accounts.stats(accountId);
.group("/assessments", (app) => app if (!stats) throw new NotFoundError("Account stats not found");
.guard({ auth: true }, (app) => app return stats;
.post("/me", async ({ body: { player, activityPerformances }, accountId }) => { })
.post("/assessments", async ({ body: { player, activityPerformances }, accountId }) => {
return await s.Assessments.create(player, activityPerformances, accountId); return await s.Assessments.create(player, activityPerformances, accountId);
}, { }, {
body: t.Object({ body: t.Object({
@@ -494,43 +489,16 @@ export const app = new Elysia()
activityPerformances: t.Array(ActivityPerformanceSchema) activityPerformances: t.Array(ActivityPerformanceSchema)
}) })
}) })
.get("/me", async ({ accountId }) => { .get("/assessments", async ({ accountId }) => {
return await s.Assessments.list({ filter: { accountId } }); return await s.Assessments.list({ filter: { accountId } });
}) })
.delete("/me/:id", async ({ params: { id }, accountId }) => { .delete("/assessments/:id", async ({ params: { id }, accountId }) => {
const deleted = await s.Assessments.delete(id, accountId); const deleted = await s.Assessments.delete(id, accountId);
if (!deleted) throw new NotFoundError("Assessment not found"); if (!deleted) throw new NotFoundError("Assessment not found");
}, { }, {
params: t.Object({ id: t.String() }) params: t.Object({ id: t.String() })
}) })
) .post("/verifications", async ({ body: { assessmentId, activityVideoUrls }, accountId }) => {
.guard({ authAdmin: true }, (app) => app
.post("/", async ({ body: { player, activityPerformances, id } }) => {
await s.Assessments.create(player, activityPerformances, id);
}, {
body: t.Object({
player: PlayerSchema,
activityPerformances: t.Array(ActivityPerformanceSchema),
id: t.Optional(t.String()),
})
})
.put("/:id", async ({ body: { player, activityPerformances }, params: { id } }) => {
const updated = await s.Assessments.update(id, player, activityPerformances);
if (!updated) throw new NotFoundError("Assessment not found");
}, {
params: t.Object({ id: t.String() }),
body: t.Object({
player: PlayerSchema,
activityPerformances: t.Array(ActivityPerformanceSchema),
})
})
)
)
// VERIFICATIONS
.group("/verifications", (app) => app
.guard({ auth: true }, (app) => app
.post("/me", async ({ body: { assessmentId, activityVideoUrls }, accountId }) => {
const requested = await s.Verifications.request(assessmentId, accountId, activityVideoUrls); const requested = await s.Verifications.request(assessmentId, accountId, activityVideoUrls);
if (!requested) throw new NotFoundError("Assessment not found"); if (!requested) throw new NotFoundError("Assessment not found");
return requested; return requested;
@@ -541,57 +509,82 @@ export const app = new Elysia()
}) })
}) })
) )
.guard({ authAdmin: true }, (app) => app )
.get("/", async ({ query }) => {
return await s.Verifications.list({
filter: { status: query.status },
limit: query.limit,
offset: query.offset,
});
}, {
query: t.Object({
status: t.Optional(VerificationStatusSchema),
limit: t.Optional(t.Numeric()),
offset: t.Optional(t.Numeric()),
})
})
.get("/:id", async ({ params: { id } }) => {
const verification = await s.Verifications.get(id);
if (!verification) throw new NotFoundError("Verification not found");
return verification;
}, {
params: t.Object({ id: t.String() })
})
.post("/:id/request-action", async ({ params: { id }, body: { reviewerNotes, activityVerifications } }) => {
const verification = await s.Verifications.get(id);
if (!verification) throw new NotFoundError("Verification not found");
if (verification.status === "completed" || verification.status === "action_requested")
throw status(409, { error: "Cannot modify a completed or action-requested verification" });
const updated = await s.Verifications.requestAction(id, reviewerNotes ?? null, activityVerifications); // ASSESSMENTS
if (!updated) throw new NotFoundError("Verification not found"); .group("/assessments", { authAdmin: true }, (app) => app
}, { .post("/", async ({ body: { player, activityPerformances, id } }) => {
params: t.Object({ id: t.String() }), await s.Assessments.create(player, activityPerformances, id);
body: t.Object({ }, {
reviewerNotes: t.Optional(t.String()), body: t.Object({
activityVerifications: ActivityVerificationsSchema, player: PlayerSchema,
}) activityPerformances: t.Array(ActivityPerformanceSchema),
id: t.Optional(t.String()),
}) })
.post("/:id/complete", async ({ params: { id }, body: { activityVerifications }, accountId }) => { })
const verification = await s.Verifications.get(id); .put("/:id", async ({ body: { player, activityPerformances }, params: { id } }) => {
if (!verification) throw new NotFoundError("Verification not found"); const updated = await s.Assessments.update(id, player, activityPerformances);
if (verification.status === "completed" || verification.status === "action_requested") if (!updated) throw new NotFoundError("Assessment not found");
throw status(409, { error: "Cannot modify a completed or action-requested verification" }); }, {
params: t.Object({ id: t.String() }),
body: t.Object({
player: PlayerSchema,
activityPerformances: t.Array(ActivityPerformanceSchema),
})
})
)
const updated = await s.Verifications.complete(id, accountId, activityVerifications); // VERIFICATIONS
if (!updated) throw new NotFoundError("Verification not found"); .group("/verifications", { authAdmin: true }, (app) => app
}, { .get("/", async ({ query }) => {
params: t.Object({ id: t.String() }), return await s.Verifications.list({
body: t.Object({ filter: { status: query.status },
activityVerifications: ActivityVerificationsSchema, limit: query.limit,
}) offset: query.offset,
});
}, {
query: t.Object({
status: t.Optional(VerificationStatusSchema),
limit: t.Optional(t.Numeric()),
offset: t.Optional(t.Numeric()),
}) })
) })
.get("/:id", async ({ params: { id } }) => {
const verification = await s.Verifications.get(id);
if (!verification) throw new NotFoundError("Verification not found");
return verification;
}, {
params: t.Object({ id: t.String() })
})
.post("/:id/request-action", async ({ params: { id }, body: { reviewerNotes, activityVerifications } }) => {
const verification = await s.Verifications.get(id);
if (!verification) throw new NotFoundError("Verification not found");
if (verification.status === "completed" || verification.status === "action_requested")
throw status(409, { error: "Cannot modify a completed or action-requested verification" });
const updated = await s.Verifications.requestAction(id, reviewerNotes ?? null, activityVerifications);
if (!updated) throw new NotFoundError("Verification not found");
}, {
params: t.Object({ id: t.String() }),
body: t.Object({
reviewerNotes: t.Optional(t.String()),
activityVerifications: ActivityVerificationsSchema,
})
})
.post("/:id/complete", async ({ params: { id }, body: { activityVerifications }, accountId }) => {
const verification = await s.Verifications.get(id);
if (!verification) throw new NotFoundError("Verification not found");
if (verification.status === "completed" || verification.status === "action_requested")
throw status(409, { error: "Cannot modify a completed or action-requested verification" });
const updated = await s.Verifications.complete(id, accountId, activityVerifications);
if (!updated) throw new NotFoundError("Verification not found");
}, {
params: t.Object({ id: t.String() }),
body: t.Object({
activityVerifications: ActivityVerificationsSchema,
})
})
) )
// WEBHOOKS // WEBHOOKS
@@ -18,7 +18,7 @@
import { api } from "$lib/api"; import { api } from "$lib/api";
type AssessmentRow = NonNullable< type AssessmentRow = NonNullable<
Awaited<ReturnType<typeof api.assessments.me.get>>["data"] Awaited<ReturnType<typeof api.accounts.me.assessments.get>>["data"]
>[number]; >[number];
interface CalcData { interface CalcData {
@@ -112,7 +112,7 @@
loading = true; loading = true;
loadError = null; loadError = null;
try { try {
const res = await api.assessments.me.get(); const res = await api.accounts.me.assessments.get();
if (res.error) throw res.error; if (res.error) throw res.error;
calculations = (res.data ?? []).map(assessmentToCalc); calculations = (res.data ?? []).map(assessmentToCalc);
} catch (err) { } catch (err) {
@@ -135,7 +135,7 @@
}); });
if (res.error) throw res.error; if (res.error) throw res.error;
} else { } else {
const res = await api.assessments.me.post({ const res = await api.accounts.me.assessments.post({
player: calculation.player, player: calculation.player,
activityPerformances: calculation.activityPerformances, activityPerformances: calculation.activityPerformances,
}); });
@@ -162,7 +162,7 @@
calculation.deleting = true; calculation.deleting = true;
calculation.deleteError = undefined; calculation.deleteError = undefined;
try { try {
const res = await api.assessments.me({ id: calculation.id }).delete(); const res = await api.accounts.me.assessments({ id: calculation.id }).delete();
if (res.error) throw res.error; if (res.error) throw res.error;
calculations.splice(index, 1); calculations.splice(index, 1);
} catch (err) { } catch (err) {