summary refs log tree commit diff
path: root/util/src/models
diff options
context:
space:
mode:
authorFlam3rboy <34555296+Flam3rboy@users.noreply.github.com>2021-08-22 12:41:21 +0200
committerFlam3rboy <34555296+Flam3rboy@users.noreply.github.com>2021-08-22 12:41:21 +0200
commitae2896fa6148cc1366573166368e157d6fa50b82 (patch)
treeb4fbe795d2ee0b4c3b0e21de525195a553fe48ee /util/src/models
parent:construction: typeorm (diff)
downloadserver-ae2896fa6148cc1366573166368e157d6fa50b82.tar.xz
:construction: typeorm
Diffstat (limited to 'util/src/models')
-rw-r--r--util/src/models/BaseClass.ts24
-rw-r--r--util/src/models/User.ts171
2 files changed, 103 insertions, 92 deletions
diff --git a/util/src/models/BaseClass.ts b/util/src/models/BaseClass.ts
index 78cd329c..d4f635f6 100644
--- a/util/src/models/BaseClass.ts
+++ b/util/src/models/BaseClass.ts
@@ -1,22 +1,24 @@
 import "reflect-metadata";
-import { BaseEntity, Column } from "typeorm";
+import { BaseEntity, BeforeInsert, BeforeUpdate, Column, PrimaryGeneratedColumn } from "typeorm";
+import { Snowflake } from "../util/Snowflake";
+import { IsString, validateOrReject } from "class-validator";
 
 export class BaseClass extends BaseEntity {
+	@PrimaryGeneratedColumn()
 	@Column()
-	id?: string;
+	@IsString()
+	id: string;
 
-	constructor(props?: any) {
+	constructor(props?: any, opts: { id?: string } = {}) {
 		super();
-		BaseClass.assign(props, this, "body.");
+		this.id = opts.id || Snowflake.generate();
+		Object.defineProperties(this, props);
 	}
 
-	private static assign(props: any, object: any, path?: string): any {
-		const expectedType = Reflect.getMetadata("design:type", object, props);
-		console.log(expectedType, object, props, path, typeof object);
-
-		if (typeof object !== typeof props) throw new Error(`Property at ${path} must be`);
-		if (typeof object === "object")
-			return Object.keys(object).map((key) => BaseClass.assign(props[key], object[key], `${path}.${key}`));
+	@BeforeUpdate()
+	@BeforeInsert()
+	async validate() {
+		await validateOrReject(this, {});
 	}
 }
 
diff --git a/util/src/models/User.ts b/util/src/models/User.ts
index 38045738..27aa63d1 100644
--- a/util/src/models/User.ts
+++ b/util/src/models/User.ts
@@ -2,6 +2,7 @@ import { Column, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm";
 import { Activity } from "./Activity";
 import { BaseClass } from "./BaseClass";
 import { ClientStatus, Status } from "./Status";
+import { validateOrReject, IsInt, IsEmail, IsPhoneNumber, IsBoolean, IsString, ValidateNested } from "class-validator";
 
 export const PublicUserProjection = {
 	username: true,
@@ -16,67 +17,80 @@ export const PublicUserProjection = {
 };
 
 export class User extends BaseClass {
-	@PrimaryGeneratedColumn()
-	id: string;
-
 	@Column()
+	@IsString()
 	username: string; // username max length 32, min 2 (should be configurable)
 
 	@Column()
+	@IsInt()
 	discriminator: string; // #0001 4 digit long string from #0001 - #9999
 
 	@Column()
+	@IsString()
 	avatar: string | null; // hash of the user avatar
 
 	@Column()
+	@IsInt()
 	accent_color: number | null; // banner color of user
 
 	@Column()
 	banner: string | null; // hash of the user banner
 
 	@Column()
+	@IsPhoneNumber()
 	phone: string | null; // phone number of the user
 
 	@Column()
+	@IsBoolean()
 	desktop: boolean; // if the user has desktop app installed
 
 	@Column()
+	@IsBoolean()
 	mobile: boolean; // if the user has mobile app installed
 
 	@Column()
+	@IsBoolean()
 	premium: boolean; // if user bought nitro
 
 	@Column()
 	premium_type: number; // nitro level
 
 	@Column()
+	@IsBoolean()
 	bot: boolean; // if user is bot
 
 	@Column()
 	bio: string; // short description of the user (max 190 chars -> should be configurable)
 
 	@Column()
+	@IsBoolean()
 	system: boolean; // shouldn't be used, the api sents this field type true, if the generated message comes from a system generated author
 
 	@Column()
+	@IsBoolean()
 	nsfw_allowed: boolean; // if the user is older than 18 (resp. Config)
 
 	@Column()
+	@IsBoolean()
 	mfa_enabled: boolean; // if multi factor authentication is enabled
 
 	@Column()
 	created_at: Date; // registration date
 
 	@Column()
+	@IsBoolean()
 	verified: boolean; // if the user is offically verified
 
 	@Column()
+	@IsBoolean()
 	disabled: boolean; // if the account is disabled
 
 	@Column()
+	@IsBoolean()
 	deleted: boolean; // if the user was deleted
 
 	@Column()
+	@IsEmail()
 	email: string | null; // email of the user
 
 	@Column()
@@ -86,15 +100,19 @@ export class User extends BaseClass {
 	public_flags: bigint;
 
 	@Column("simple-array") // string in simple-array must not contain commas
+	@IsString({ each: true })
 	guilds: string[]; // array of guild ids the user is part of
 
 	@Column("simple-json")
-	user_settings: UserSettings;
-
-	@Column("simple-json")
-	user_data: UserData;
+	@ValidateNested() // TODO: https://github.com/typestack/class-validator#validating-nested-objects
+	user_data: {
+		valid_tokens_since: Date; // all tokens with a previous issue date are invalid
+		hash: string; // hash of the password, salt is saved in password (bcrypt)
+		fingerprints: string[]; // array of fingerprints -> used to prevent multiple accounts
+	};
 
 	@Column("simple-json")
+	@ValidateNested() // TODO: https://github.com/typestack/class-validator#validating-nested-objects
 	presence: {
 		status: Status;
 		activities: Activity[];
@@ -102,22 +120,76 @@ export class User extends BaseClass {
 	};
 
 	@Column("simple-json")
-	relationships: Relationship[];
+	@ValidateNested() // TODO: https://github.com/typestack/class-validator#validating-nested-objects
+	relationships: {
+		id: string;
+		nickname?: string;
+		type: RelationshipType;
+	}[];
 
 	@Column("simple-json")
-	connected_accounts: ConnectedAccount[];
-}
-
-// @ts-ignore
-global.User = User;
+	@ValidateNested() // TODO: https://github.com/typestack/class-validator#validating-nested-objects
+	connected_accounts: {
+		access_token: string;
+		friend_sync: boolean;
+		id: string;
+		name: string;
+		revoked: boolean;
+		show_activity: boolean;
+		type: string;
+		verifie: boolean;
+		visibility: number;
+	}[];
 
-// Private user data that should never get sent to the client
-export interface UserData {
-	valid_tokens_since: Date; // all tokens with a previous issue date are invalid
-	hash: string; // hash of the password, salt is saved in password (bcrypt)
-	fingerprints: string[]; // array of fingerprints -> used to prevent multiple accounts
+	@Column("simple-json")
+	@ValidateNested() // TODO: https://github.com/typestack/class-validator#validating-nested-objects
+	user_settings: {
+		afk_timeout: number;
+		allow_accessibility_detection: boolean;
+		animate_emoji: boolean;
+		animate_stickers: number;
+		contact_sync_enabled: boolean;
+		convert_emoticons: boolean;
+		custom_status: {
+			emoji_id: string | null;
+			emoji_name: string | null;
+			expires_at: number | null;
+			text: string | null;
+		};
+		default_guilds_restricted: boolean;
+		detect_platform_accounts: boolean;
+		developer_mode: boolean;
+		disable_games_tab: boolean;
+		enable_tts_command: boolean;
+		explicit_content_filter: number;
+		friend_source_flags: { all: boolean };
+		gateway_connected: boolean;
+		gif_auto_play: boolean;
+		guild_folders: // every top guild is displayed as a "folder"
+		{
+			color: number;
+			guild_ids: string[];
+			id: number;
+			name: string;
+		}[];
+		guild_positions: string[]; // guild ids ordered by position
+		inline_attachment_media: boolean;
+		inline_embed_media: boolean;
+		locale: string; // en_US
+		message_display_compact: boolean;
+		native_phone_integration_enabled: boolean;
+		render_embeds: boolean;
+		render_reactions: boolean;
+		restricted_guilds: string[];
+		show_current_game: boolean;
+		status: "online" | "offline" | "dnd" | "idle";
+		stream_notifications_enabled: boolean;
+		theme: "dark" | "white"; // dark
+		timezone_offset: number; // e.g -60
+	};
 }
 
+// Private user data that should never get sent to the client
 export interface PublicUser {
 	id: string;
 	discriminator: string;
@@ -129,72 +201,9 @@ export interface PublicUser {
 	bot: boolean;
 }
 
-export interface ConnectedAccount {
-	access_token: string;
-	friend_sync: boolean;
-	id: string;
-	name: string;
-	revoked: boolean;
-	show_activity: boolean;
-	type: string;
-	verifie: boolean;
-	visibility: number;
-}
-
-export interface Relationship {
-	id: string;
-	nickname?: string;
-	type: RelationshipType;
-}
-
 export enum RelationshipType {
 	outgoing = 4,
 	incoming = 3,
 	blocked = 2,
 	friends = 1,
 }
-
-export interface UserSettings {
-	afk_timeout: number;
-	allow_accessibility_detection: boolean;
-	animate_emoji: boolean;
-	animate_stickers: number;
-	contact_sync_enabled: boolean;
-	convert_emoticons: boolean;
-	custom_status: {
-		emoji_id: string | null;
-		emoji_name: string | null;
-		expires_at: number | null;
-		text: string | null;
-	};
-	default_guilds_restricted: boolean;
-	detect_platform_accounts: boolean;
-	developer_mode: boolean;
-	disable_games_tab: boolean;
-	enable_tts_command: boolean;
-	explicit_content_filter: number;
-	friend_source_flags: { all: boolean };
-	gateway_connected: boolean;
-	gif_auto_play: boolean;
-	guild_folders: // every top guild is displayed as a "folder"
-	{
-		color: number;
-		guild_ids: string[];
-		id: number;
-		name: string;
-	}[];
-	guild_positions: string[]; // guild ids ordered by position
-	inline_attachment_media: boolean;
-	inline_embed_media: boolean;
-	locale: string; // en_US
-	message_display_compact: boolean;
-	native_phone_integration_enabled: boolean;
-	render_embeds: boolean;
-	render_reactions: boolean;
-	restricted_guilds: string[];
-	show_current_game: boolean;
-	status: "online" | "offline" | "dnd" | "idle";
-	stream_notifications_enabled: boolean;
-	theme: "dark" | "white"; // dark
-	timezone_offset: number; // e.g -60
-}