diff --git a/api.yml b/api.yml index 9a34fb5..62ce87f 100644 --- a/api.yml +++ b/api.yml @@ -3316,6 +3316,67 @@ paths: $ref: "#/components/schemas/ApiResponseError" example: { "ok": false, "status": 2, "error": "Failed to decode password with base64." } + /token/manage: + delete: + operationId: deleteTokenById + summary: Delete a token by token id + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + required: [id] + properties: + id: + type: integer + format: int64 + description: Token id + default: '' + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/ApiResponseTrue" + "400": + description: Bad Request + content: + application/json: + schema: + $ref: "#/components/schemas/ApiResponseError" + example: { "ok": false, "status": 2, "error": "token id not specified." } + "401": + description: Authorization information is missing or invalid + content: + application/json: + schema: + $ref: "#/components/schemas/ApiResponseError" + example: { "ok": false, "status": 401, "error": "Unauthorized" } + "403": + description: Permission denied + content: + application/json: + schema: + $ref: "#/components/schemas/ApiResponseError" + examples: + admin: + description: Requires administrator privileges. + value: { "ok": false, "status": 403, "error": "Permission denied." } + root: + description: Requires root user. + value: { "ok": false, "status": 3, "error": "Only root user can delete admin user's token." } + "404": + description: Not found + content: + application/json: + schema: + $ref: "#/components/schemas/ApiResponseError" + examples: + user: + value: { "ok": false, "status": 404, "error": "User not found." } + token: + value: { "ok": false, "status": 404, "error": "Token not found." } /user: delete: operationId: deleteUser diff --git a/db.ts b/db.ts index 51b98d3..73997e1 100644 --- a/db.ts +++ b/db.ts @@ -1401,6 +1401,15 @@ export class EhDb { ); return s.length ? s[0] : undefined; } + get_token_by_id(id: number | bigint) { + const s = this.convert_token( + this.db.queryEntries( + "SELECT * FROM token WHERE id = ?;", + [id], + ), + ); + return s.length ? s[0] : undefined; + } get_user(id: number | bigint) { const s = this.convert_user( this.db.queryEntries( diff --git a/fresh.gen.ts b/fresh.gen.ts index 5d62e44..0ce30fd 100644 --- a/fresh.gen.ts +++ b/fresh.gen.ts @@ -33,6 +33,7 @@ import * as $api_task_export_zip_cfg from "./routes/api/task/export_zip_cfg.ts"; import * as $api_task_import_cfg from "./routes/api/task/import_cfg.ts"; import * as $api_thumbnail_id_ from "./routes/api/thumbnail/[id].ts"; import * as $api_token from "./routes/api/token.ts"; +import * as $api_token_manage from "./routes/api/token/manage.ts"; import * as $api_user from "./routes/api/user.ts"; import * as $api_user_change_name from "./routes/api/user/change_name.ts"; import * as $api_user_change_password from "./routes/api/user/change_password.ts"; @@ -82,6 +83,7 @@ const manifest = { "./routes/api/task/import_cfg.ts": $api_task_import_cfg, "./routes/api/thumbnail/[id].ts": $api_thumbnail_id_, "./routes/api/token.ts": $api_token, + "./routes/api/token/manage.ts": $api_token_manage, "./routes/api/user.ts": $api_user, "./routes/api/user/change_name.ts": $api_user_change_name, "./routes/api/user/change_password.ts": $api_user_change_password, diff --git a/routes/api/token/manage.ts b/routes/api/token/manage.ts new file mode 100644 index 0000000..01eea6f --- /dev/null +++ b/routes/api/token/manage.ts @@ -0,0 +1,42 @@ +import { Handlers } from "$fresh/server.ts"; +import { User } from "../../../db.ts"; +import { get_task_manager } from "../../../server.ts"; +import { parse_big_int } from "../../../server/parse_form.ts"; +import { return_data, return_error } from "../../../server/utils.ts"; + +export const handler: Handlers = { + async DELETE(req, ctx) { + const user = ctx.state.user; + let data: FormData | null = null; + try { + data = await req.formData(); + } catch (_) { + return return_error(1, "Invalid parameters."); + } + const id = await parse_big_int(data.get("id"), null); + if (id === null) { + return return_error(2, "token id not specified."); + } + const m = get_task_manager(); + const token = m.db.get_token_by_id(id); + if (!token) { + return return_error(404, "Token not found."); + } + if (user) { + if (!user.is_admin && user.id != token.uid) { + return return_error(403, "Permission denied."); + } + if (user.is_admin && user.id != token.uid && user.id != 0) { + const u = m.db.get_user(token.uid); + if (!u) { + return return_error(404, "User not found."); + } + if (u.is_admin) { + return return_error(3, "Only root user can delete admin user's token.", 403); + } + } + } + m.db.delete_token(token.token); + return return_data(true); + }, +}