80 lines
2.1 KiB
TypeScript
80 lines
2.1 KiB
TypeScript
|
import { createHmac, randomBytes } from '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>
|
||
|
};
|