mirror of
https://github.com/lifegpc/eh-downloader.git
synced 2026-06-06 05:38:44 +08:00
Add api to list tokens
This commit is contained in:
105
api.yml
105
api.yml
@@ -1028,9 +1028,28 @@ components:
|
||||
const: 1
|
||||
description: ffmpeg BINARY
|
||||
Token:
|
||||
description: Token information
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/TokenWithoutToken"
|
||||
- type: object
|
||||
required: [token]
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
description: Token
|
||||
TokenApiResult:
|
||||
description: Api response for createToken
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/ApiResponse"
|
||||
- type: object
|
||||
required: [data]
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/Token'
|
||||
TokenWithoutToken:
|
||||
description: Token information
|
||||
type: object
|
||||
required: [id, uid, token, expired, http_only, secure, last_used]
|
||||
required: [id, uid, expired, http_only, secure, last_used]
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
@@ -1038,9 +1057,6 @@ components:
|
||||
uid:
|
||||
type: integer
|
||||
description: User id
|
||||
token:
|
||||
type: string
|
||||
description: Token
|
||||
expired:
|
||||
type: string
|
||||
format: date-time
|
||||
@@ -1067,15 +1083,20 @@ components:
|
||||
client_platform:
|
||||
type: string
|
||||
description: Client platform
|
||||
TokenApiResult:
|
||||
description: Api response for createToken
|
||||
TokenWithoutTokenList:
|
||||
description: A list of tokens
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/TokenWithoutToken"
|
||||
TokenWithoutTokenListApiResult:
|
||||
description: Api response for listTokens
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/ApiResponse"
|
||||
- type: object
|
||||
required: [data]
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/Token'
|
||||
$ref: '#/components/schemas/TokenWithoutTokenList'
|
||||
TokenWithUserInfo:
|
||||
description: Token information with user information
|
||||
type: object
|
||||
@@ -3377,6 +3398,76 @@ paths:
|
||||
value: { "ok": false, "status": 404, "error": "User not found." }
|
||||
token:
|
||||
value: { "ok": false, "status": 404, "error": "Token not found." }
|
||||
get:
|
||||
operationId: listTokens
|
||||
summary: List user's tokens
|
||||
parameters:
|
||||
- name: uid
|
||||
in: query
|
||||
description: User id
|
||||
schema:
|
||||
type: integer
|
||||
- name: offset
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
description: Page offset
|
||||
- name: limit
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
description: Page size
|
||||
- name: all_user
|
||||
in: query
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Return all users' tokens
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TokenWithoutTokenListApiResult"
|
||||
"400":
|
||||
description: Bad Request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ApiResponseError"
|
||||
example: { "ok": false, "status": 2, "error": "User 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." }
|
||||
all_user:
|
||||
description: Requires root user.
|
||||
value: { "ok": false, "status": 4, "error": "Only root user can get all user's tokens." }
|
||||
"404":
|
||||
description: Not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ApiResponseError"
|
||||
example: { "ok": false, "status": 404, "error": "User not found." }
|
||||
/user:
|
||||
delete:
|
||||
operationId: deleteUser
|
||||
|
||||
34
db.ts
34
db.ts
@@ -346,7 +346,6 @@ function escape_fields(fields: string, namespace: string) {
|
||||
export class EhDb {
|
||||
// @ts-ignore Ignore
|
||||
db: Db;
|
||||
#flock_enabled: boolean = eval('typeof Deno.flock !== "undefined"');
|
||||
#file: Deno.FsFile | undefined;
|
||||
#dblock: Deno.FsFile | undefined;
|
||||
#exist_table: Set<string> = new Set();
|
||||
@@ -372,7 +371,7 @@ export class EhDb {
|
||||
this.db = new DB(this.#db_path);
|
||||
}
|
||||
if (!this.#check_database()) this.#create_table();
|
||||
if (!this.#use_ffi && this.#flock_enabled) {
|
||||
if (!this.#use_ffi) {
|
||||
this.#lock_file = join(this.#base_path, "db.lock");
|
||||
this.#dblock_file = join(this.#base_path, "eh.locked");
|
||||
this.#file = Deno.openSync(this.#lock_file, {
|
||||
@@ -384,11 +383,6 @@ export class EhDb {
|
||||
write: true,
|
||||
});
|
||||
this.dblock();
|
||||
} else if (!this.#use_ffi) {
|
||||
console.log(
|
||||
"%cFile locking is disabled. Use --unstable to enable file locking.",
|
||||
"color: yellow;",
|
||||
);
|
||||
}
|
||||
this.remove_expired_token();
|
||||
}
|
||||
@@ -1410,6 +1404,32 @@ export class EhDb {
|
||||
);
|
||||
return s.length ? s[0] : undefined;
|
||||
}
|
||||
get_tokens(
|
||||
offset: number | bigint | null = 0,
|
||||
limit: number | bigint | null = 20,
|
||||
uid: number | bigint | null = null,
|
||||
) {
|
||||
let sql = "";
|
||||
const args = [];
|
||||
if (uid !== null) {
|
||||
sql = " WHERE uid = ?";
|
||||
args.push(uid);
|
||||
}
|
||||
if (limit !== null) {
|
||||
sql += " LIMIT ?";
|
||||
args.push(limit);
|
||||
}
|
||||
if (offset !== null) {
|
||||
sql += " OFFSET ?";
|
||||
args.push(offset);
|
||||
}
|
||||
return this.convert_token(
|
||||
this.db.queryEntries<TokenRaw>(
|
||||
`SELECT * FROM token${sql};`,
|
||||
args,
|
||||
),
|
||||
);
|
||||
}
|
||||
get_user(id: number | bigint) {
|
||||
const s = this.convert_user(
|
||||
this.db.queryEntries<UserRaw>(
|
||||
|
||||
@@ -21,7 +21,11 @@
|
||||
"static/sw.js",
|
||||
"static/sw.meta.json",
|
||||
"_fresh",
|
||||
"extensions/build"
|
||||
"extensions/build",
|
||||
"api.yml",
|
||||
"docker-compose.yml",
|
||||
".github/workflows/deno.yml",
|
||||
".github/workflows/docker.yaml"
|
||||
]
|
||||
},
|
||||
"compilerOptions": {
|
||||
|
||||
@@ -47,7 +47,7 @@ import * as $thumbnail_verify_id_ from "./routes/thumbnail/[verify]/[id].ts";
|
||||
import * as $thumbnail_middleware from "./routes/thumbnail/_middleware.ts";
|
||||
import * as $upload from "./routes/upload.tsx";
|
||||
import * as $Upload from "./islands/Upload.tsx";
|
||||
import { type Manifest } from "$fresh/server.ts";
|
||||
import type { Manifest } from "$fresh/server.ts";
|
||||
|
||||
const manifest = {
|
||||
routes: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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 { parse_big_int, parse_bool } from "../../../server/parse_form.ts";
|
||||
import { return_data, return_error } from "../../../server/utils.ts";
|
||||
|
||||
export const handler: Handlers = {
|
||||
@@ -32,11 +32,60 @@ export const handler: Handlers = {
|
||||
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);
|
||||
return return_error(
|
||||
3,
|
||||
"Only root user can delete admin user's token.",
|
||||
403,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
m.db.delete_token(token.token);
|
||||
return return_data(true);
|
||||
},
|
||||
}
|
||||
async GET(req, ctx) {
|
||||
const user = <User | undefined> ctx.state.user;
|
||||
const data = new URL(req.url).searchParams;
|
||||
let uid = await parse_big_int(data.get("uid"), null);
|
||||
const offset = await parse_big_int(data.get("offset"), null);
|
||||
const limit = await parse_big_int(data.get("limit"), null);
|
||||
const all_user = await parse_bool(data.get("all_user"), false);
|
||||
const m = get_task_manager();
|
||||
if (user) {
|
||||
if (!all_user && uid === null) uid = user.id;
|
||||
if (!user.is_admin && uid && user.id != uid) {
|
||||
return return_error(403, "Permission denied.");
|
||||
}
|
||||
if (user.is_admin && uid && user.id != uid && user.id != 0) {
|
||||
const u = m.db.get_user(uid);
|
||||
if (!u) {
|
||||
return return_error(404, "User not found.");
|
||||
}
|
||||
if (u.is_admin) {
|
||||
return return_error(
|
||||
3,
|
||||
"Only root user can get admin user's tokens.",
|
||||
403,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (user.id != 0 && uid === null) {
|
||||
return return_error(
|
||||
4,
|
||||
"Only root user can get all user's tokens.",
|
||||
403,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!all_user && uid === null) {
|
||||
return return_error(2, "User id not specified.");
|
||||
}
|
||||
return return_data(
|
||||
m.db.get_tokens(offset, limit, uid).map((e) => {
|
||||
// @ts-ignore Ignore
|
||||
delete e.token;
|
||||
return e;
|
||||
}),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user