refactor(api): ♻️ Throw ApiError instead of returning error JSON

This commit is contained in:
Jesse Wierzbinski 2024-12-30 18:00:23 +01:00
parent c14621ee06
commit fbfd237f27
No known key found for this signature in database
88 changed files with 458 additions and 483 deletions

View file

@ -102,7 +102,7 @@ describe("/oauth/authorize", () => {
const params = new URLSearchParams(location.search);
expect(params.get("error")).toBe("invalid_request");
expect(params.get("error_description")).toBe(
"Invalid JWT, could not verify",
"Invalid JWT: could not verify",
);
});
@ -141,7 +141,7 @@ describe("/oauth/authorize", () => {
const params = new URLSearchParams(location.search);
expect(params.get("error")).toBe("invalid_request");
expect(params.get("error_description")).toBe(
"Invalid JWT, missing required fields (aud, sub, exp)",
"Invalid JWT: missing required fields (aud, sub, exp, iss)",
);
});
@ -183,7 +183,7 @@ describe("/oauth/authorize", () => {
const params = new URLSearchParams(location.search);
expect(params.get("error")).toBe("invalid_request");
expect(params.get("error_description")).toBe(
"Invalid JWT, sub is not a valid user ID",
"Invalid JWT: sub is not a valid user ID",
);
const jwt2 = await new SignJWT({
@ -266,9 +266,9 @@ describe("/oauth/authorize", () => {
config.http.base_url,
);
const params = new URLSearchParams(location.search);
expect(params.get("error")).toBe("invalid_request");
expect(params.get("error")).toBe("unauthorized");
expect(params.get("error_description")).toBe(
`User is missing the required permission ${RolePermissions.OAuth}`,
`User missing required '${RolePermissions.OAuth}' permission`,
);
config.permissions.default = oldPermissions;
@ -312,7 +312,7 @@ describe("/oauth/authorize", () => {
const params = new URLSearchParams(location.search);
expect(params.get("error")).toBe("invalid_request");
expect(params.get("error_description")).toBe(
"Invalid client_id: no associated application found",
"Invalid client_id: no associated API application found",
);
});
@ -354,7 +354,7 @@ describe("/oauth/authorize", () => {
const params = new URLSearchParams(location.search);
expect(params.get("error")).toBe("invalid_request");
expect(params.get("error_description")).toBe(
"Invalid redirect_uri: does not match application's redirect_uri",
"Invalid redirect_uri: does not match API application's redirect_uri",
);
});
@ -394,7 +394,7 @@ describe("/oauth/authorize", () => {
config.http.base_url,
);
const params = new URLSearchParams(location.search);
expect(params.get("error")).toBe("invalid_scope");
expect(params.get("error")).toBe("invalid_request");
expect(params.get("error_description")).toBe(
"Invalid scope: not a subset of the application's scopes",
);

View file

@ -6,6 +6,7 @@ import { type SQL, and, eq, isNull } from "@versia/kit/drizzle";
import { OpenIdAccounts, RolePermissions, Users } from "@versia/kit/tables";
import { setCookie } from "hono/cookie";
import { SignJWT } from "jose";
import { ApiError } from "~/classes/errors/api-error.ts";
import type { PluginType } from "../../index.ts";
import { automaticOidcFlow } from "../../utils.ts";
@ -78,7 +79,7 @@ export default (plugin: PluginType): void => {
.providers.find((provider) => provider.id === issuerParam);
if (!issuer) {
return context.json({ error: "Issuer not found" }, 404);
throw new ApiError(404, "Issuer not found");
}
const userInfo = await automaticOidcFlow(
@ -303,10 +304,7 @@ export default (plugin: PluginType): void => {
}
if (!flow.application) {
return context.json(
{ error: "Application not found" },
500,
);
throw new ApiError(500, "Application not found");
}
const code = randomString(32, "hex");

View file

@ -4,6 +4,7 @@ import { createRoute, z } from "@hono/zod-openapi";
import { db } from "@versia/kit/db";
import { type SQL, eq } from "@versia/kit/drizzle";
import { OpenIdAccounts, RolePermissions } from "@versia/kit/tables";
import { ApiError } from "~/classes/errors/api-error";
import type { PluginType } from "~/plugins/openid";
import { ErrorSchema } from "~/types/api";
@ -66,12 +67,7 @@ export default (plugin: PluginType): void => {
const { user } = context.get("auth");
if (!user) {
return context.json(
{
error: "Unauthorized",
},
401,
);
throw new ApiError(401, "Unauthorized");
}
const issuer = context
@ -96,11 +92,9 @@ export default (plugin: PluginType): void => {
});
if (!account) {
return context.json(
{
error: "Account not found or is not linked to this issuer",
},
throw new ApiError(
404,
"Account not found or is not linked to this issuer",
);
}
@ -163,7 +157,7 @@ export default (plugin: PluginType): void => {
const { user } = context.get("auth");
if (!user) {
return context.json({ error: "Unauthorized" }, 401);
throw new ApiError(401, "Unauthorized");
}
// Check if issuer exists
@ -189,11 +183,9 @@ export default (plugin: PluginType): void => {
});
if (!account) {
return context.json(
{
error: "Account not found or is not linked to this issuer",
},
throw new ApiError(
404,
"Account not found or is not linked to this issuer",
);
}

View file

@ -6,6 +6,7 @@ import {
generateRandomCodeVerifier,
} from "oauth4webapi";
import { z } from "zod";
import { ApiError } from "~/classes/errors/api-error.ts";
import { ErrorSchema } from "~/types/api";
import type { PluginType } from "../../index.ts";
import { oauthDiscoveryRequest, oauthRedirectUri } from "../../utils.ts";
@ -57,12 +58,7 @@ export default (plugin: PluginType): void => {
const { user } = context.get("auth");
if (!user) {
return context.json(
{
error: "Unauthorized",
},
401,
);
throw new ApiError(401, "Unauthorized");
}
const linkedAccounts = await user.getLinkedOidcAccounts(
@ -133,12 +129,7 @@ export default (plugin: PluginType): void => {
const { user } = context.get("auth");
if (!user) {
return context.json(
{
error: "Unauthorized",
},
401,
);
throw new ApiError(401, "Unauthorized");
}
const { issuer: issuerId } = context.req.valid("json");