mirror of
https://github.com/lifegpc/eh-downloader.git
synced 2026-06-17 08:24:42 +08:00
Add new api to change name and password
This commit is contained in:
@@ -29,6 +29,8 @@ import * as $api_task_export_zip_cfg from "./routes/api/task/export_zip_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_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";
|
||||
import * as $api_user_list from "./routes/api/user/list.ts";
|
||||
import * as $file_id_ from "./routes/file/[id].ts";
|
||||
import * as $file_verify_id_ from "./routes/file/[verify]/[id].ts";
|
||||
@@ -70,6 +72,8 @@ const manifest = {
|
||||
"./routes/api/thumbnail/[id].ts": $api_thumbnail_id_,
|
||||
"./routes/api/token.ts": $api_token,
|
||||
"./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,
|
||||
"./routes/api/user/list.ts": $api_user_list,
|
||||
"./routes/file/[id].ts": $file_id_,
|
||||
"./routes/file/[verify]/[id].ts": $file_verify_id_,
|
||||
|
||||
@@ -35,8 +35,8 @@ class TimestampCache {
|
||||
}
|
||||
}
|
||||
|
||||
const timestamp_cache = new TimestampCache();
|
||||
const cache_mutex = new Mutex();
|
||||
export const timestamp_cache = new TimestampCache();
|
||||
export const cache_mutex = new Mutex();
|
||||
|
||||
export const handler: Handlers = {
|
||||
async DELETE(req, ctx) {
|
||||
|
||||
42
routes/api/user/change_name.ts
Normal file
42
routes/api/user/change_name.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Handlers } from "$fresh/server.ts";
|
||||
import { User } from "../../../db.ts";
|
||||
import { get_task_manager } from "../../../server.ts";
|
||||
import { get_string } from "../../../server/parse_form.ts";
|
||||
import { BUser } from "../../../server/user.ts";
|
||||
import { return_data, return_error } from "../../../server/utils.ts";
|
||||
|
||||
export const handler: Handlers = {
|
||||
async POST(req, ctx) {
|
||||
const user = <User | undefined> ctx.state.user;
|
||||
if (!user) {
|
||||
return return_error(403, "Permission denied.");
|
||||
}
|
||||
let d: FormData | null = null;
|
||||
try {
|
||||
d = await req.formData();
|
||||
} catch (_) {
|
||||
return return_error(1, "Invalid parameters.");
|
||||
}
|
||||
const username = await get_string(d.get("username"));
|
||||
if (!username) return return_error(2, "User name not specified.");
|
||||
if (user.username == username) {
|
||||
return return_error(3, "Name not changed.");
|
||||
}
|
||||
const m = get_task_manager();
|
||||
const u = m.db.get_user_by_name(username);
|
||||
if (u) {
|
||||
return return_error(
|
||||
4,
|
||||
"User name is already used by other user, please use another name.",
|
||||
);
|
||||
}
|
||||
user.username = username;
|
||||
m.db.update_user(user);
|
||||
return return_data<BUser>({
|
||||
id: user.id,
|
||||
is_admin: user.is_admin,
|
||||
permissions: user.permissions,
|
||||
username: user.username,
|
||||
});
|
||||
},
|
||||
};
|
||||
74
routes/api/user/change_password.ts
Normal file
74
routes/api/user/change_password.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { Handlers } from "$fresh/server.ts";
|
||||
import isEqual from "lodash/isEqual";
|
||||
import pbkdf2Hmac from "pbkdf2-hmac";
|
||||
import { decodeBase64 } from "std/encoding/base64.ts";
|
||||
import { User } from "../../../db.ts";
|
||||
import { get_task_manager } from "../../../server.ts";
|
||||
import { get_string, parse_int } from "../../../server/parse_form.ts";
|
||||
import { return_data, return_error } from "../../../server/utils.ts";
|
||||
import { cache_mutex, timestamp_cache } from "../token.ts";
|
||||
|
||||
export const handler: Handlers = {
|
||||
async POST(req, ctx) {
|
||||
const user = <User | undefined> ctx.state.user;
|
||||
if (!user) {
|
||||
return return_error(403, "Permission denied.");
|
||||
}
|
||||
let d: FormData | null = null;
|
||||
try {
|
||||
d = await req.formData();
|
||||
} catch (_) {
|
||||
return return_error(1, "Invalid parameters.");
|
||||
}
|
||||
const oldp = await get_string(d.get("old"));
|
||||
if (!oldp) return return_error(2, "Old password is needed.");
|
||||
let old: Uint8Array | null = null;
|
||||
try {
|
||||
old = decodeBase64(oldp);
|
||||
} catch (_) {
|
||||
return return_error(
|
||||
3,
|
||||
"Failed to decode old password with base64.",
|
||||
);
|
||||
}
|
||||
if (old.length !== 64) {
|
||||
return return_error(3, "Old password need 64 bytes.");
|
||||
}
|
||||
const t = await parse_int(d.get("t"), null);
|
||||
if (t === null) return return_error(2, "t not specified.");
|
||||
const now = Date.now();
|
||||
if (t > now + 60000 || t < now - 60000) {
|
||||
return return_error(4, "Time is not corrected.");
|
||||
}
|
||||
const newp = await get_string(d.get("new"));
|
||||
if (!newp) return return_error(2, "New password not specified.");
|
||||
const pa = new Uint8Array(
|
||||
await pbkdf2Hmac(user.password, t.toString(), 1000, 64, "SHA-512"),
|
||||
);
|
||||
if (!isEqual(pa, old)) {
|
||||
return return_error(5, "Incorrect password");
|
||||
}
|
||||
await cache_mutex.acquire();
|
||||
try {
|
||||
timestamp_cache.clear_expired(user.username, now);
|
||||
if (timestamp_cache.is_in_cache(user.username, t)) {
|
||||
return return_error(6, "This request has been used.");
|
||||
}
|
||||
timestamp_cache.add(user.username, t);
|
||||
} finally {
|
||||
cache_mutex.release();
|
||||
}
|
||||
user.password = new Uint8Array(
|
||||
await pbkdf2Hmac(
|
||||
newp,
|
||||
"eh-downloader-salt",
|
||||
210000,
|
||||
64,
|
||||
"SHA-512",
|
||||
),
|
||||
);
|
||||
const m = get_task_manager();
|
||||
m.db.update_user(user);
|
||||
return return_data(true);
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user