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.
 
 
 
 
 
 

104 lines
2.5 KiB

import { Entity, PrimaryGeneratedColumn, Column, BaseEntity, OneToMany, OneToOne, JoinColumn, CreateDateColumn, MoreThanOrEqual } from "typeorm";
import bcrypt from "bcrypt";
import { MovieTicket } from "./MovieTicket";
import { MovieQuota } from "./MovieQuota";
import { DiscordAccount } from "./DiscordAccount";
@Entity()
export class User extends BaseEntity
{
@PrimaryGeneratedColumn()
id!: number;
@Column()
isAdmin!: boolean;
@Column({ length: 50 })
name!: string;
@Column({ length: 255 })
email!: string;
@Column({ type: "char", length: 60 })
password!: string;
@CreateDateColumn()
createdAt!: Date;
@OneToOne(() => MovieQuota, { nullable: true })
@JoinColumn()
quota!: MovieQuota | null;
@OneToMany(() => User, user => user.movieTickets)
movieTickets!: MovieTicket[];
@OneToMany(() => DiscordAccount, account => account.user)
discordAccounts!: DiscordAccount[];
/**
* Authenticate a user and return an auth token upon success
*/
public static async authenticate(email: string, password: string) {
let user = <User>await User.findOne({ email });
if (user === undefined || !(await bcrypt.compare(password, user.password))) {
return null;
}
return user;
}
/**
* Create a new user
*/
public static async createUser(name: string, email: string, password: string, quota: number|null = 5) {
let user = new User();
user.isAdmin = false;
user.name = name;
user.email = email;
user.password = await bcrypt.hash(password, 8);
// Create a quota if necessary
if (quota !== null) {
user.quota = new MovieQuota;
user.quota.moviesPerWeek = quota;
await user.quota.save();
}
return await user.save();
}
/**
* Determine the user's available quota
*/
public async availableQuota() {
let quota = await this.fetchQuota();
if (quota === null) {
return null;
}
let oneWeekAgo = new Date(Date.now() - 1000*60*60*24*7);
let numTicketsThisWeek = await MovieTicket.count({
user: this,
createdAt: MoreThanOrEqual(oneWeekAgo),
isCanceled: false
});
return quota.moviesPerWeek - numTicketsThisWeek;
}
/**
* Get the user's quota, fetching it if undefined
*/
public async fetchQuota() {
if (this.quota !== undefined) {
return this.quota;
}
let user = <User>await User.findOne(this.id, { relations: ["quota"] });
return user.quota;
}
/**
* Fetch active movie tickets for this user
*/
public async activeMovieTickets() {
return await MovieTicket.find({
where: { user: this, isCanceled: false, isFulfilled: false },
relations: ["info"]
});
}
}