diff --git a/src/v2/lib/managers/auth/user-session-manager.ts b/src/v2/lib/managers/auth/user-session-manager.ts index 528c8095..f010cb0f 100644 --- a/src/v2/lib/managers/auth/user-session-manager.ts +++ b/src/v2/lib/managers/auth/user-session-manager.ts @@ -67,4 +67,16 @@ export class AuthSessionManager { return true } + + public async invalidateSessionById(id: string) { + const { user } = await this.validateAndGetSession() + + if (!user) { + return null + } + + await this.lucia.invalidateSession(id) + + return true + } } diff --git a/src/v2/routes/asset/delete-asset.ts b/src/v2/routes/asset/delete-asset.ts index 4e8ab2bf..caaef55d 100644 --- a/src/v2/routes/asset/delete-asset.ts +++ b/src/v2/routes/asset/delete-asset.ts @@ -12,7 +12,7 @@ const deleteAssetByIdSchema = z.object({ name: "id", in: "path", description: "The ID of the asset to delete.", - example: "1", + example: "asset_id", required: true, }, }), diff --git a/src/v2/routes/asset/like-asset.ts b/src/v2/routes/asset/like-asset.ts index a298c29a..95269f26 100644 --- a/src/v2/routes/asset/like-asset.ts +++ b/src/v2/routes/asset/like-asset.ts @@ -11,7 +11,7 @@ const likeAssetByIdSchema = z.object({ id: z.string().openapi({ param: { description: "The id of the asset to like.", - example: "1", + example: "asset_id", in: "path", name: "id", required: true, diff --git a/src/v2/routes/asset/modify-asset.ts b/src/v2/routes/asset/modify-asset.ts index 50ce6e47..e3f8bc87 100644 --- a/src/v2/routes/asset/modify-asset.ts +++ b/src/v2/routes/asset/modify-asset.ts @@ -12,7 +12,7 @@ const modifyAssetPathSchema = z.object({ id: z.string().openapi({ param: { description: "The id of the asset to modify.", - example: "1", + example: "asset_id", in: "path", required: true, }, diff --git a/src/v2/routes/asset/unlike-asset.ts b/src/v2/routes/asset/unlike-asset.ts index 60396235..c19e570d 100644 --- a/src/v2/routes/asset/unlike-asset.ts +++ b/src/v2/routes/asset/unlike-asset.ts @@ -11,7 +11,7 @@ const unlikeAssetByIdSchema = z.object({ id: z.string().openapi({ param: { description: "The id of the asset to unlike.", - example: "1", + example: "asset_id", in: "path", name: "id", required: true, diff --git a/src/v2/routes/asset/upload-asset.ts b/src/v2/routes/asset/upload-asset.ts index c9f901d6..81f3f61b 100644 --- a/src/v2/routes/asset/upload-asset.ts +++ b/src/v2/routes/asset/upload-asset.ts @@ -50,7 +50,8 @@ const uploadAssetSchema = z.object({ .min(1) .max(1) .openapi({ - description: "If the asset contains suggestive content 0 or 1.", + description: + "If the asset contains suggestive content. 1 = Yes, 0 = No.", example: "1", }) .transform((value) => parseInt(value)) diff --git a/src/v2/routes/auth/handler.ts b/src/v2/routes/auth/handler.ts index 56d1776c..9ceebeef 100644 --- a/src/v2/routes/auth/handler.ts +++ b/src/v2/routes/auth/handler.ts @@ -4,6 +4,7 @@ import { UserLoginRoute } from "./account-login" import { UserAllCurrentSessionsRoute } from "./get-all-sessions" import { LogoutCurrentSessionRoute } from "./logout-current-session" import { ValidateSessionRoute } from "./validate-current-session" +import { InvalidateSessionRoute } from "./invalidate-session" const handler = new OpenAPIHono<{ Bindings: Bindings; Variables: Variables }>() @@ -11,6 +12,7 @@ UserCreateAccountRoute(handler) UserLoginRoute(handler) ValidateSessionRoute(handler) +InvalidateSessionRoute(handler) UserAllCurrentSessionsRoute(handler) LogoutCurrentSessionRoute(handler) diff --git a/src/v2/routes/auth/invalidate-session.ts b/src/v2/routes/auth/invalidate-session.ts index e69de29b..6163188e 100644 --- a/src/v2/routes/auth/invalidate-session.ts +++ b/src/v2/routes/auth/invalidate-session.ts @@ -0,0 +1,94 @@ +import { AppHandler } from "../handler" +import { AuthSessionManager } from "@/v2/lib/managers/auth/user-session-manager" +// import { deleteCookie } from "hono/cookie" +import { createRoute } from "@hono/zod-openapi" +import { GenericResponses } from "@/v2/lib/response-schemas" +import { z } from "@hono/zod-openapi" + +const invalidateSessionSchema = z.object({ + id: z.string().openapi({ + param: { + description: "The id of the session to invalidate.", + example: "session_id", + in: "path", + name: "id", + required: true, + }, + }), +}) + +const invalidateSessionResponseSchema = z.object({ + success: z.literal(true), +}) + +const invalidateSessionRoute = createRoute({ + path: "/invalidate/{id}", + method: "get", + description: "Invalidate a session by its ID.", + tags: ["Auth"], + request: { + params: invalidateSessionSchema, + }, + responses: { + 200: { + description: "Logout successful.", + content: { + "application/json": { + schema: invalidateSessionResponseSchema, + }, + }, + }, + ...GenericResponses, + }, +}) + +export const InvalidateSessionRoute = (handler: AppHandler) => { + handler.openapi(invalidateSessionRoute, async (ctx) => { + const sessionId = ctx.req.valid("param").id + + const authSessionManager = new AuthSessionManager(ctx) + + const { user, session } = await authSessionManager.validateSession() + + if (!user) { + return ctx.json( + { + success: false, + message: "Unauthorized", + }, + 401 + ) + } + + if (sessionId == session.id) { + return ctx.json( + { + success: false, + message: "Cannot invalidate the current session.", + }, + 400 + ) + } + + const sessions = await authSessionManager.getAllSessions() + + if (!sessions.find((s) => s.id === sessionId)) { + return ctx.json( + { + success: false, + message: "Session not found.", + }, + 400 + ) + } + + await authSessionManager.invalidateSessionById(sessionId) + + return ctx.json( + { + success: true, + }, + 200 + ) + }) +} diff --git a/src/v2/routes/requests/delete-request.ts b/src/v2/routes/requests/delete-request.ts index 16ef9a48..fc9df68a 100644 --- a/src/v2/routes/requests/delete-request.ts +++ b/src/v2/routes/requests/delete-request.ts @@ -13,7 +13,7 @@ export const deleteRequestByIdSchema = z.object({ name: "id", in: "path", description: "The ID of the request to delete. Supporter required.", - example: "1", + example: "request_id", required: true, }, }), diff --git a/src/v2/routes/requests/remove-request-upvote.ts b/src/v2/routes/requests/remove-request-upvote.ts index 85fd7208..afe244c7 100644 --- a/src/v2/routes/requests/remove-request-upvote.ts +++ b/src/v2/routes/requests/remove-request-upvote.ts @@ -13,7 +13,7 @@ export const removeRequestUpvoteByIdSchema = z.object({ name: "id", in: "path", description: "The ID of the request to remove the upvote for.", - example: "1", + example: "request_id", required: true, }, }), diff --git a/src/v2/routes/requests/upvote-request.ts b/src/v2/routes/requests/upvote-request.ts index 66fcbcfb..ea23d7b1 100644 --- a/src/v2/routes/requests/upvote-request.ts +++ b/src/v2/routes/requests/upvote-request.ts @@ -13,7 +13,7 @@ export const upvoteRequestByIdSchema = z.object({ name: "id", in: "path", description: "The ID of the request to upvote.", - example: "1", + example: "request_id", required: true, }, }), diff --git a/src/v2/routes/requests/view-request.ts b/src/v2/routes/requests/view-request.ts index 3744ad6c..c0d860e5 100644 --- a/src/v2/routes/requests/view-request.ts +++ b/src/v2/routes/requests/view-request.ts @@ -13,7 +13,7 @@ export const viewRequestByIdSchema = z.object({ name: "id", in: "path", description: "The ID of the request to view.", - example: "1", + example: "request_id", required: true, }, }),