You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

116 lines
3.1 KiB

import * as bcrypt from "bcrypt";
import * as r from "rethinkdb";
import { createModelSchema, deserialize, primitive, serialize, update } from "serializr";
import { Database } from "./Database";
export interface IUser {
id: string | undefined;
username: string;
name: string;
passwordHash: string;
}
const HASH_ROUNDS = 10;
export class User implements IUser {
static readonly tableName = "users";
id: string | undefined;
username: string = "";
name: string = "";
passwordHash: string = "";
private db: Database;
private get _db() {
return this.db.db;
}
private get table() {
return this.db.db.table(User.tableName);
}
constructor(db: Database, data?: Partial<IUser>) {
this.db = db;
if (data) {
update(this, data);
}
}
static async createTable(db: Database) {
await db.db.tableCreate(User.tableName).run(db.conn);
await db.db.table(User.tableName).indexCreate("username").run(db.conn);
}
static async loadAll(db: Database): Promise<User[]> {
const cursor = await db.db.table(User.tableName)
.run(db.conn);
const users = await cursor.toArray();
return users.map((data) => {
return new User(db, data);
});
}
static async load(db: Database, id: string): Promise<User | null> {
const data = await db.db.table(User.tableName)
.get(id)
.run(db.conn);
if (data == null) {
return null;
}
return new User(db, data);
}
static async loadByUsername(db: Database, username: string): Promise<User | null> {
const seq = await db.db.table(User.tableName)
.filter(r.row("username").eq(username))
.run(db.conn);
const data = await seq.toArray();
if (data.length === 0) {
return null;
}
return new User(db, data[0]);
}
async create() {
const data = serialize(this);
delete data.id;
const a = this.table
.insert(data)
.run(this.db.conn);
}
async createOrUpdate() {
const data = serialize(this);
delete data.id;
const user = this.table.filter(r.row("username").eq(this.username));
const usernameDoesNotExist = user.isEmpty();
const a: r.WriteResult = await r.branch(usernameDoesNotExist,
this.table.insert(data) as r.Expression<any>,
user.nth(0).update(data) as r.Expression<any>)
.run(this.db.conn);
return a.inserted > 0;
}
async setPassword(newPassword: string): Promise<void> {
this.passwordHash = await bcrypt.hash(newPassword, HASH_ROUNDS);
}
async comparePassword(password: string): Promise<boolean> {
return bcrypt.compare(password, this.passwordHash);
}
toJSON(): any {
const data = serialize(this);
delete data.passwordHash;
return data;
}
}
createModelSchema(User, {
id: primitive(),
username: primitive(),
name: primitive(),
passwordHash: primitive(),
});