diff --git a/util/package.json b/util/package.json
index 35d2fbbe..587e8a14 100644
--- a/util/package.json
+++ b/util/package.json
@@ -6,7 +6,7 @@
"types": "src/index.ts",
"scripts": {
"start": "npm run build && node dist/",
- "test": "npm run build && jest",
+ "test": "npm run build && npx jest",
"postinstall": "npm run build",
"build": "npx tsc -p .",
"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js"
diff --git a/util/src/entities/BackupCodes.ts b/util/src/entities/BackupCodes.ts
new file mode 100644
index 00000000..d532a39a
--- /dev/null
+++ b/util/src/entities/BackupCodes.ts
@@ -0,0 +1,35 @@
+import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
+import { BaseClass } from "./BaseClass";
+import { User } from "./User";
+import crypto from "crypto";
+
+@Entity("backup_codes")
+export class BackupCode extends BaseClass {
+ @JoinColumn({ name: "user_id" })
+ @ManyToOne(() => User, { onDelete: "CASCADE" })
+ user: User;
+
+ @Column()
+ code: string;
+
+ @Column()
+ consumed: boolean;
+
+ @Column()
+ expired: boolean;
+}
+
+export function generateMfaBackupCodes(user_id: string) {
+ let backup_codes: BackupCode[] = [];
+ for (let i = 0; i < 10; i++) {
+ const code = BackupCode.create({
+ user: { id: user_id },
+ code: crypto.randomBytes(4).toString("hex"), // 8 characters
+ consumed: false,
+ expired: false,
+ });
+ backup_codes.push(code);
+ }
+
+ return backup_codes;
+}
\ No newline at end of file
diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts
index 9b1c494e..79d415ca 100644
--- a/util/src/entities/User.ts
+++ b/util/src/entities/User.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, FindOneOptions, JoinColumn, ManyToMany, OneToMany, RelationId } from "typeorm";
+import { Column, Entity, FindOneOptions, JoinColumn, OneToMany } from "typeorm";
import { BaseClass } from "./BaseClass";
import { BitField } from "../util/BitField";
import { Relationship } from "./Relationship";
@@ -108,6 +108,12 @@ export class User extends BaseClass {
@Column({ select: false })
mfa_enabled: boolean; // if multi factor authentication is enabled
+ @Column({ select: false, nullable: true })
+ totp_secret?: string;
+
+ @Column({ nullable: true, select: false })
+ totp_last_ticket?: string;
+
@Column()
created_at: Date; // registration date
diff --git a/util/src/entities/index.ts b/util/src/entities/index.ts
index f023d5a6..1b6259ae 100644
--- a/util/src/entities/index.ts
+++ b/util/src/entities/index.ts
@@ -27,4 +27,5 @@ export * from "./Template";
export * from "./User";
export * from "./VoiceState";
export * from "./Webhook";
-export * from "./ClientRelease";
\ No newline at end of file
+export * from "./ClientRelease";
+export * from "./BackupCodes";
\ No newline at end of file
|