From de3cc0fd1161fac1685dbb69875b62610b128d3c Mon Sep 17 00:00:00 2001 From: zkldi <20380519+zkldi@users.noreply.github.com> Date: Wed, 12 Oct 2022 21:01:11 +0100 Subject: [PATCH] feat: revert integration endpoint --- .../dashboard/users/UserIntegrationsPage.tsx | 31 +++++++++++++++--- docs/docs/api/routes/user-integrations.md | 26 +++++++++++++++ .../integrations/kai/_kaiType/router.ts | 32 ++++++++++++++++++- server/src/utils/queries/auth.ts | 7 ++++ 4 files changed, 91 insertions(+), 5 deletions(-) diff --git a/client/src/app/pages/dashboard/users/UserIntegrationsPage.tsx b/client/src/app/pages/dashboard/users/UserIntegrationsPage.tsx index dae7f9f2c..5b88edd95 100644 --- a/client/src/app/pages/dashboard/users/UserIntegrationsPage.tsx +++ b/client/src/app/pages/dashboard/users/UserIntegrationsPage.tsx @@ -703,7 +703,32 @@ function KAIIntegrationStatus({ : `You are not authenticated with ${kaiType.toUpperCase()}`} {data.authStatus ? ( -

There's no configuration to do here. You're all good!

+ <> + + + The below button will revoke your authentication with{" "} + {kaiType.toUpperCase()}. +
+ You only need to do this if you've revoked it on {kaiType.toLowerCase()}! + ) : (

You should authenticate yourself by going to{" "} @@ -720,9 +745,7 @@ function APIKeysPage({ reqUser }: { reqUser: PublicUserDocument }) { const [apiKeys, setApiKeys] = useState([]); const [showModal, setShowModal] = useState(false); - const { data, error } = useApiQuery( - `/users/${reqUser.id}/api-tokens` - ); + const { data, error } = useApiQuery(`/users/${reqUser.id}/api-tokens`); useEffect(() => { if (data) { diff --git a/docs/docs/api/routes/user-integrations.md b/docs/docs/api/routes/user-integrations.md index 9c46ca301..168b91389 100644 --- a/docs/docs/api/routes/user-integrations.md +++ b/docs/docs/api/routes/user-integrations.md @@ -42,6 +42,32 @@ GET /api/v1/users/1/integrations/kai/flo ***** +## Revoke this user's authentication with this kaiType + +`DELETE /api/v1/users/:userID/integrations/kai/:kaiType` + + +**Kamaitachi Only** + +!!! note + A KaiType is either "flo", "min", or "eag". Since these three services + share backends, they all use the same authentication mechanisms, and share + endpoints like this. + +### Permissions + +- Self-key: This request must be made using Cookie authentication, which means it cannot be used with API keys. + +### Parameters + +None. + +### Response + +Empty Object. + +***** + ## Update a user's access_token and refresh_token from an intermediate code. `POST /api/v1/users/:userID/integrations/kai/:kaiType/oauth2callback` diff --git a/server/src/server/router/api/v1/users/_userID/integrations/kai/_kaiType/router.ts b/server/src/server/router/api/v1/users/_userID/integrations/kai/_kaiType/router.ts index 56b33ad4b..0477be033 100644 --- a/server/src/server/router/api/v1/users/_userID/integrations/kai/_kaiType/router.ts +++ b/server/src/server/router/api/v1/users/_userID/integrations/kai/_kaiType/router.ts @@ -12,7 +12,7 @@ import prValidate from "server/middleware/prudence-validate"; import { RequireKamaitachi } from "server/middleware/type-require"; import fetch from "utils/fetch"; import { NotNullish } from "utils/misc"; -import { GetKaiAuth } from "utils/queries/auth"; +import { GetKaiAuth, RevokeKaiAuth } from "utils/queries/auth"; import { GetTachiData } from "utils/req-tachi-data"; import { FormatUserDoc } from "utils/user"; import { URL } from "url"; @@ -46,6 +46,36 @@ router.get("/", async (req, res) => { }); }); +/** + * Revoke your authentication for this kaiType. + * @note - Express's types infer arg0 of "/" to mean no params, for some reason. + * the generic overrides this behaviour. + * + * @name DELETE /api/v1/users/:userID/integrations/kai/:kaiType + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +router.delete("/", async (req, res) => { + const user = GetTachiData(req, "requestedUser"); + const kaiType = NotNullish(req.params.kaiType).toUpperCase() as "EAG" | "FLO" | "MIN"; + + const authDoc = await GetKaiAuth(user.id, kaiType); + + if (!authDoc) { + return res.status(409).json({ + success: false, + description: `You are not authorised with this service.`, + }); + } + + await RevokeKaiAuth(user.id, kaiType); + + return res.status(200).json({ + success: true, + description: `Revoked authentication for ${kaiType}.`, + body: {}, + }); +}); + const KAI_OAUTH2_RETURN_SCHEMA = { access_token: "string", refresh_token: "string", diff --git a/server/src/utils/queries/auth.ts b/server/src/utils/queries/auth.ts index 07ca5ddbb..50003d1e1 100644 --- a/server/src/utils/queries/auth.ts +++ b/server/src/utils/queries/auth.ts @@ -10,6 +10,13 @@ export function GetKaiAuth(userID: integer, service: "EAG" | "FLO" | "MIN") { }); } +export function RevokeKaiAuth(userID: integer, service: "EAG" | "FLO" | "MIN") { + return db["kai-auth-tokens"].remove({ + userID, + service, + }); +} + export async function GetKaiAuthGuaranteed( userID: integer, service: "EAG" | "FLO" | "MIN",