ionian/packages/server/src/model/user.ts
2024-03-29 00:19:36 +09:00

84 lines
2 KiB
TypeScript

import { createHmac, randomBytes } from "node:crypto";
function hashForPassword(salt: string, password: string) {
return createHmac("sha256", salt).update(password).digest("hex");
}
function createPasswordHashAndSalt(password: string): { salt: string; hash: string } {
const secret = randomBytes(32).toString("hex");
return {
salt: secret,
hash: hashForPassword(secret, password),
};
}
export class Password {
private _salt: string;
private _hash: string;
constructor(pw: string | { salt: string; hash: string }) {
const { salt, hash } = typeof pw === "string" ? createPasswordHashAndSalt(pw) : pw;
this._hash = hash;
this._salt = salt;
}
set_password(password: string) {
const { salt, hash } = createPasswordHashAndSalt(password);
this._hash = hash;
this._salt = salt;
}
check_password(password: string): boolean {
return this._hash === hashForPassword(this._salt, password);
}
get salt() {
return this._salt;
}
get hash() {
return this._hash;
}
}
export interface UserCreateInput {
username: string;
password: string;
}
export interface IUser {
readonly username: string;
readonly password: Password;
/**
* return user's permission list.
*/
get_permissions(): Promise<string[]>;
/**
* add permission
* @param name permission name to add
* @returns if `name` doesn't exist, return true
*/
add(name: string): Promise<boolean>;
/**
* remove permission
* @param name permission name to remove
* @returns if `name` exist, return true
*/
remove(name: string): Promise<boolean>;
/**
* reset password.
* @param password password to set
*/
reset_password(password: string): Promise<void>;
}
export interface UserAccessor {
/**
* create user
* @returns if user exist, return undefined
*/
createUser: (input: UserCreateInput) => Promise<IUser | undefined>;
/**
* find user
*/
findUser: (username: string) => Promise<IUser | undefined>;
/**
* remove user
* @returns if user exist, true
*/
delUser: (username: string) => Promise<boolean>;
}