mirror of
https://github.com/lifegpc/eh-downloader.git
synced 2026-06-06 05:38:44 +08:00
feat: Add log entry retrieval and deletion API endpoints
This commit is contained in:
93
api.yml
93
api.yml
@@ -808,6 +808,15 @@ components:
|
|||||||
stack:
|
stack:
|
||||||
type: string
|
type: string
|
||||||
description: Stack trace
|
description: Stack trace
|
||||||
|
LogEntryApiResult:
|
||||||
|
description: Api response for getLog
|
||||||
|
allOf:
|
||||||
|
- $ref: "#/components/schemas/ApiResponse"
|
||||||
|
- type: object
|
||||||
|
required: [data]
|
||||||
|
properties:
|
||||||
|
data:
|
||||||
|
$ref: "#/components/schemas/LogEntry"
|
||||||
LogEntries:
|
LogEntries:
|
||||||
description: Log entries
|
description: Log entries
|
||||||
type: object
|
type: object
|
||||||
@@ -2652,6 +2661,90 @@ paths:
|
|||||||
$ref: "#/components/schemas/ApiResponseError"
|
$ref: "#/components/schemas/ApiResponseError"
|
||||||
example:
|
example:
|
||||||
{ "ok": false, "status": 403, "error": "Permission denied." }
|
{ "ok": false, "status": 403, "error": "Permission denied." }
|
||||||
|
/log/{id}:
|
||||||
|
parameters:
|
||||||
|
- name: id
|
||||||
|
in: path
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
default: ''
|
||||||
|
required: true
|
||||||
|
description: Log entry ID
|
||||||
|
delete:
|
||||||
|
operationId: deleteLog
|
||||||
|
summary: Delete a log entry
|
||||||
|
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": 1, "error": "id is required." }
|
||||||
|
"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"
|
||||||
|
example:
|
||||||
|
{ "ok": false, "status": 403, "error": "Permission denied." }
|
||||||
|
get:
|
||||||
|
operationId: getLog
|
||||||
|
summary: Get a log entry
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/LogEntryApiResult"
|
||||||
|
"400":
|
||||||
|
description: Bad request
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/ApiResponseError"
|
||||||
|
example:
|
||||||
|
{ "ok": false, "status": 1, "error": "id is required." }
|
||||||
|
"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"
|
||||||
|
example:
|
||||||
|
{ "ok": false, "status": 403, "error": "Permission denied." }
|
||||||
|
"404":
|
||||||
|
description: Not found
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/ApiResponseError"
|
||||||
|
example:
|
||||||
|
{ "ok": false, "status": 404, "error": "log not found." }
|
||||||
/shared_token:
|
/shared_token:
|
||||||
delete:
|
delete:
|
||||||
operationId: deleteSharedToken
|
operationId: deleteSharedToken
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import * as $api_gallery_list from "./routes/api/gallery/list.ts";
|
|||||||
import * as $api_gallery_meta_gids_ from "./routes/api/gallery/meta/[gids].ts";
|
import * as $api_gallery_meta_gids_ from "./routes/api/gallery/meta/[gids].ts";
|
||||||
import * as $api_health_check from "./routes/api/health_check.ts";
|
import * as $api_health_check from "./routes/api/health_check.ts";
|
||||||
import * as $api_log from "./routes/api/log.ts";
|
import * as $api_log from "./routes/api/log.ts";
|
||||||
|
import * as $api_log_id_ from "./routes/api/log/[id].ts";
|
||||||
import * as $api_shared_token from "./routes/api/shared_token.ts";
|
import * as $api_shared_token from "./routes/api/shared_token.ts";
|
||||||
import * as $api_shared_token_list from "./routes/api/shared_token/list.ts";
|
import * as $api_shared_token_list from "./routes/api/shared_token/list.ts";
|
||||||
import * as $api_status from "./routes/api/status.ts";
|
import * as $api_status from "./routes/api/status.ts";
|
||||||
@@ -74,6 +75,7 @@ const manifest = {
|
|||||||
"./routes/api/gallery/meta/[gids].ts": $api_gallery_meta_gids_,
|
"./routes/api/gallery/meta/[gids].ts": $api_gallery_meta_gids_,
|
||||||
"./routes/api/health_check.ts": $api_health_check,
|
"./routes/api/health_check.ts": $api_health_check,
|
||||||
"./routes/api/log.ts": $api_log,
|
"./routes/api/log.ts": $api_log,
|
||||||
|
"./routes/api/log/[id].ts": $api_log_id_,
|
||||||
"./routes/api/shared_token.ts": $api_shared_token,
|
"./routes/api/shared_token.ts": $api_shared_token,
|
||||||
"./routes/api/shared_token/list.ts": $api_shared_token_list,
|
"./routes/api/shared_token/list.ts": $api_shared_token_list,
|
||||||
"./routes/api/status.ts": $api_status,
|
"./routes/api/status.ts": $api_status,
|
||||||
|
|||||||
41
routes/api/log/[id].ts
Normal file
41
routes/api/log/[id].ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { Handlers } from "$fresh/server.ts";
|
||||||
|
import { return_data, return_error } from "../../../server/utils.ts";
|
||||||
|
import { User, UserPermission } from "../../../db.ts";
|
||||||
|
import { parse_big_int } from "../../../server/parse_form.ts";
|
||||||
|
import { base_logger } from "../../../utils/logger.ts";
|
||||||
|
|
||||||
|
export const handler: Handlers = {
|
||||||
|
async GET(_req, ctx) {
|
||||||
|
const user = <User | undefined> ctx.state.user;
|
||||||
|
if (
|
||||||
|
user && !user.is_admin &&
|
||||||
|
!(Number(user.permissions) & UserPermission.QueryLog)
|
||||||
|
) {
|
||||||
|
return return_error(403, "Permission denied.");
|
||||||
|
}
|
||||||
|
const id = await parse_big_int(ctx.params["id"], null);
|
||||||
|
if (id === null) {
|
||||||
|
return return_error(1, "id is required.");
|
||||||
|
}
|
||||||
|
const log = base_logger.get_log(id);
|
||||||
|
if (!log) {
|
||||||
|
return return_error(404, "log not found.");
|
||||||
|
}
|
||||||
|
return return_data(log);
|
||||||
|
},
|
||||||
|
async DELETE(_req, ctx) {
|
||||||
|
const user = <User | undefined> ctx.state.user;
|
||||||
|
if (
|
||||||
|
user && !user.is_admin &&
|
||||||
|
!(Number(user.permissions) & UserPermission.QueryLog)
|
||||||
|
) {
|
||||||
|
return return_error(403, "Permission denied.");
|
||||||
|
}
|
||||||
|
const id = await parse_big_int(ctx.params["id"], null);
|
||||||
|
if (id === null) {
|
||||||
|
return return_error(1, "id is required.");
|
||||||
|
}
|
||||||
|
base_logger.delete_log(id);
|
||||||
|
return return_data(true);
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -150,6 +150,41 @@ class BaseLogger {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
clear(
|
||||||
|
type?: string | null,
|
||||||
|
min_level?: number | null,
|
||||||
|
max_level?: number | null,
|
||||||
|
deleted_level?: number[],
|
||||||
|
end_time?: Date | null,
|
||||||
|
) {
|
||||||
|
if (!this.db) return;
|
||||||
|
const where = [];
|
||||||
|
const args: QueryParameterSet = [];
|
||||||
|
if (type) {
|
||||||
|
where.push("type = ?");
|
||||||
|
args.push(type);
|
||||||
|
}
|
||||||
|
if (min_level) {
|
||||||
|
where.push("level >= ?");
|
||||||
|
args.push(min_level);
|
||||||
|
}
|
||||||
|
if (max_level) {
|
||||||
|
where.push("level <= ?");
|
||||||
|
args.push(max_level);
|
||||||
|
}
|
||||||
|
if (deleted_level) {
|
||||||
|
where.push(
|
||||||
|
"level IN (" + deleted_level.map(() => "?").join(",") + ")",
|
||||||
|
);
|
||||||
|
args.push(...deleted_level);
|
||||||
|
}
|
||||||
|
if (end_time) {
|
||||||
|
where.push("time <= ?");
|
||||||
|
args.push(end_time.getTime());
|
||||||
|
}
|
||||||
|
const where_str = where.length ? " WHERE " + where.join(" AND ") : "";
|
||||||
|
this.db.query(`DELETE FROM log${where_str};`, args);
|
||||||
|
}
|
||||||
close() {
|
close() {
|
||||||
this.db?.close();
|
this.db?.close();
|
||||||
this.db = undefined;
|
this.db = undefined;
|
||||||
@@ -201,6 +236,10 @@ class BaseLogger {
|
|||||||
debug(type: string, ...messages: unknown[]) {
|
debug(type: string, ...messages: unknown[]) {
|
||||||
this.add(type, LogLevel.Debug, ...messages);
|
this.add(type, LogLevel.Debug, ...messages);
|
||||||
}
|
}
|
||||||
|
delete_log(id: number | bigint) {
|
||||||
|
if (!this.db) return;
|
||||||
|
this.db.query("DELETE FROM log WHERE id = ?;", [id]);
|
||||||
|
}
|
||||||
error(type: string, ...messages: unknown[]) {
|
error(type: string, ...messages: unknown[]) {
|
||||||
this.add(type, LogLevel.Error, ...messages);
|
this.add(type, LogLevel.Error, ...messages);
|
||||||
}
|
}
|
||||||
@@ -240,6 +279,14 @@ class BaseLogger {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
get_log(id: number | bigint) {
|
||||||
|
if (!this.db) return null;
|
||||||
|
const cur = this.#convert(this.db.queryEntries<LogEntryRaw>(
|
||||||
|
"SELECT * FROM log WHERE id = ?;",
|
||||||
|
[id],
|
||||||
|
));
|
||||||
|
return cur.length ? cur[0] : null;
|
||||||
|
}
|
||||||
get_logger(type: string) {
|
get_logger(type: string) {
|
||||||
return new Logger(this, type);
|
return new Logger(this, type);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user