mirror of
https://github.com/lifegpc/eh-downloader.git
synced 2026-07-08 01:31:00 +08:00
Add user management API
This commit is contained in:
26
db.ts
26
db.ts
@@ -979,6 +979,20 @@ export class EhDb {
|
||||
delete_token(token: string) {
|
||||
this.db.query("DELETE FROM token WHERE token = ?;", [token]);
|
||||
}
|
||||
delete_user(id: number) {
|
||||
this.db.query("DELETE FROM user WHERE id = ?;", [id]);
|
||||
this.db.query("DELETE FROM token WHERE uid = ?;", [id]);
|
||||
this.db.query("DELETE FROM client_config WHERE uid = ?;", [id]);
|
||||
}
|
||||
delete_user_token(uid: number, excluded_token?: number) {
|
||||
let where = "";
|
||||
const args = [uid];
|
||||
if (excluded_token) {
|
||||
where = " AND id != ?";
|
||||
args.push(excluded_token);
|
||||
}
|
||||
this.db.query(`DELETE FROM token WHERE uid = ?${where};`, args);
|
||||
}
|
||||
async flock() {
|
||||
if (!this.#file) return;
|
||||
await eval(`Deno.flock(${this.#file.rid}, true);`);
|
||||
@@ -1438,4 +1452,16 @@ export class EhDb {
|
||||
[new Date(), token],
|
||||
);
|
||||
}
|
||||
update_user(user: User) {
|
||||
this.db.query(
|
||||
"INSERT OR REPLACE INTO user VALUES (?, ?, ?, ?, ?);",
|
||||
[
|
||||
user.id,
|
||||
user.username,
|
||||
user.password,
|
||||
user.is_admin,
|
||||
user.permissions,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Handlers } from "$fresh/server.ts";
|
||||
import { User, UserPermission } from "../../db.ts";
|
||||
import { Token, User, UserPermission } from "../../db.ts";
|
||||
import { get_task_manager } from "../../server.ts";
|
||||
import { get_string, parse_bool, parse_int } from "../../server/parse_form.ts";
|
||||
import type { BUser } from "../../server/user.ts";
|
||||
@@ -7,6 +7,40 @@ import { return_data, return_error } from "../../server/utils.ts";
|
||||
import pbkdf2Hmac from "pbkdf2-hmac";
|
||||
|
||||
export const handler: Handlers = {
|
||||
async DELETE(req, ctx) {
|
||||
const user = <User | undefined> ctx.state.user;
|
||||
if (user && !user.is_admin) {
|
||||
return return_error(403, "Permission denied.");
|
||||
}
|
||||
let data: FormData | null = null;
|
||||
try {
|
||||
data = await req.formData();
|
||||
} catch (_) {
|
||||
return return_error(3, "Invalid parameters.");
|
||||
}
|
||||
const id = await parse_int(data.get("id"), null);
|
||||
const username = await get_string(data.get("username"));
|
||||
if (id === null && !username && !user) {
|
||||
return return_error(1, "user not specified.");
|
||||
}
|
||||
const m = get_task_manager();
|
||||
const us = id !== null
|
||||
? m.db.get_user(id)
|
||||
: username
|
||||
? m.db.get_user_by_name(username)
|
||||
: user;
|
||||
if (!us) return return_error(404, "User not found.");
|
||||
if (us.id == 0) return return_error(6, "root user can not be deleted.");
|
||||
if (user && us.is_admin && user.id != 0) {
|
||||
return return_error(
|
||||
7,
|
||||
"Only root user can delete admin user.",
|
||||
403,
|
||||
);
|
||||
}
|
||||
m.db.delete_user(us.id);
|
||||
return return_data(true);
|
||||
},
|
||||
async GET(req, ctx) {
|
||||
const u = new URL(req.url);
|
||||
const id = await parse_int(u.searchParams.get("id"), null);
|
||||
@@ -32,6 +66,89 @@ export const handler: Handlers = {
|
||||
permissions: us.permissions,
|
||||
});
|
||||
},
|
||||
async PATCH(req, ctx) {
|
||||
const user = <User | undefined> ctx.state.user;
|
||||
if (user && !user.is_admin) {
|
||||
return return_error(403, "Permission denied.");
|
||||
}
|
||||
let data: FormData | null = null;
|
||||
try {
|
||||
data = await req.formData();
|
||||
} catch (_) {
|
||||
return return_error(3, "Invalid parameters.");
|
||||
}
|
||||
const id = await parse_int(data.get("id"), null);
|
||||
const username = await get_string(data.get("username"));
|
||||
if (id === null && !username && !user) {
|
||||
return return_error(1, "user not specified.");
|
||||
}
|
||||
const m = get_task_manager();
|
||||
const us = id !== null
|
||||
? m.db.get_user(id)
|
||||
: username
|
||||
? m.db.get_user_by_name(username)
|
||||
: user;
|
||||
if (!us) return return_error(404, "User not found.");
|
||||
if (user && us.is_admin && user.id != 0 && user.id != us.id) {
|
||||
return return_error(
|
||||
4,
|
||||
"Only root user can change other admin user's inforamtion.",
|
||||
403,
|
||||
);
|
||||
}
|
||||
const password = await get_string(data.get("password"));
|
||||
const is_admin = await parse_bool(data.get("is_admin"), null);
|
||||
const revoke_token = await parse_bool(data.get("revoke_token"), false);
|
||||
let permissions: UserPermission | null = await parse_int(
|
||||
data.get("permissions"),
|
||||
null,
|
||||
);
|
||||
if (is_admin && !us.is_admin && user && user.id != 0) {
|
||||
return return_error(
|
||||
5,
|
||||
"Only root user can prompt non-admin user to admin user.",
|
||||
403,
|
||||
);
|
||||
}
|
||||
if (is_admin) permissions = UserPermission.All;
|
||||
if (username) {
|
||||
if (us.username != username && m.db.get_user_by_name(username)) {
|
||||
return return_error(2, "Please change to another name.");
|
||||
}
|
||||
us.username = username;
|
||||
}
|
||||
if (password) {
|
||||
const hpassword = new Uint8Array(
|
||||
await pbkdf2Hmac(
|
||||
password,
|
||||
"eh-downloader-salt",
|
||||
210000,
|
||||
64,
|
||||
"SHA-512",
|
||||
),
|
||||
);
|
||||
us.password = hpassword;
|
||||
}
|
||||
if (us.id != 0 && is_admin !== null) {
|
||||
us.is_admin = is_admin;
|
||||
}
|
||||
if (us.id != 0 && permissions !== null) {
|
||||
us.permissions = permissions;
|
||||
}
|
||||
m.db.update_user(us);
|
||||
if (revoke_token) {
|
||||
const token = <Token | undefined> ctx.state.token;
|
||||
let tid: number | undefined = undefined;
|
||||
if (user && us.id == user.id && token) tid = token.id;
|
||||
m.db.delete_user_token(us.id, tid);
|
||||
}
|
||||
return return_data<BUser>({
|
||||
id: us.id,
|
||||
is_admin: us.is_admin,
|
||||
permissions: us.permissions,
|
||||
username: us.username,
|
||||
});
|
||||
},
|
||||
async PUT(req, ctx) {
|
||||
const data = await req.formData();
|
||||
const user = <User | undefined> ctx.state.user;
|
||||
@@ -45,6 +162,9 @@ export const handler: Handlers = {
|
||||
data.get("permissions"),
|
||||
UserPermission.None,
|
||||
);
|
||||
if (is_admin && user && user.id != 0) {
|
||||
return return_error(8, "Only root user can add admin user.", 403);
|
||||
}
|
||||
if (!name) return return_error(1, "name not specified.");
|
||||
if (!password) return return_error(1, "password not specified.");
|
||||
if (is_admin) permissions = UserPermission.All;
|
||||
|
||||
Reference in New Issue
Block a user