User.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. import {
  2. DataTypes,
  3. Model,
  4. InferAttributes,
  5. InferCreationAttributes,
  6. CreationOptional,
  7. HasManyAddAssociationMixin,
  8. HasManyCountAssociationsMixin,
  9. HasManyCreateAssociationMixin,
  10. HasManyGetAssociationsMixin,
  11. HasManyHasAssociationMixin,
  12. HasManySetAssociationsMixin,
  13. HasManyAddAssociationsMixin,
  14. HasManyHasAssociationsMixin,
  15. HasManyRemoveAssociationMixin,
  16. HasManyRemoveAssociationsMixin,
  17. NonAttribute,
  18. Association
  19. } from "sequelize";
  20. import { UserRole } from "./User/UserRole";
  21. import { UserAvatarColor } from "./User/UserAvatarColor";
  22. import { UserAvatarType } from "./User/UserAvatarType";
  23. import News from "./News";
  24. import Session from "./Session";
  25. import { ObjectIdType } from "@/modules/DataModule";
  26. export class User extends Model<
  27. // eslint-disable-next-line no-use-before-define
  28. InferAttributes<User>,
  29. // eslint-disable-next-line no-use-before-define
  30. InferCreationAttributes<User>
  31. > {
  32. declare _id: CreationOptional<ObjectIdType>;
  33. declare username: string;
  34. declare role: UserRole;
  35. declare emailVerified: CreationOptional<boolean>;
  36. declare emailVerificationToken: CreationOptional<string | null>;
  37. declare emailAddress: string;
  38. declare avatarType: UserAvatarType;
  39. declare avatarUrl: CreationOptional<string | null>;
  40. declare avatarColor: CreationOptional<UserAvatarColor | null>;
  41. // Services
  42. declare password: string;
  43. declare passwordResetCode: CreationOptional<string | null>;
  44. declare passwordResetExpiresAt: CreationOptional<Date | null>;
  45. declare passwordSetCode: CreationOptional<string | null>;
  46. declare passwordSetExpiresAt: CreationOptional<Date | null>;
  47. declare githubId: CreationOptional<number | null>;
  48. declare githubAccessToken: CreationOptional<string | null>;
  49. // End services
  50. // Statistics
  51. declare songsRequested: CreationOptional<number>;
  52. // End statistics
  53. // declare likedSongsPlaylist: Types.ObjectId;
  54. // declare dislikedSongsPlaylist: Types.ObjectId;
  55. // declare favoriteStations: Types.ObjectId[];
  56. declare name: string;
  57. declare location: CreationOptional<string | null>;
  58. declare bio: CreationOptional<string | null>;
  59. // Preferences
  60. // declare orderOfPlaylists: Types.ObjectId[];
  61. declare nightmode: CreationOptional<boolean>;
  62. declare autoSkipDisliked: CreationOptional<boolean>;
  63. declare activityLogPublic: CreationOptional<boolean>;
  64. declare anonymousSongRequests: CreationOptional<boolean>;
  65. declare activityWatch: CreationOptional<boolean>;
  66. // End preferences
  67. declare createdAt: CreationOptional<Date>;
  68. declare updatedAt: CreationOptional<Date>;
  69. declare getSessionModels: HasManyGetAssociationsMixin<Session>;
  70. declare addSessionModel: HasManyAddAssociationMixin<Session, number>;
  71. declare addSessionModels: HasManyAddAssociationsMixin<Session, number>;
  72. declare setSessionModels: HasManySetAssociationsMixin<Session, number>;
  73. declare removeSessionModel: HasManyRemoveAssociationMixin<Session, number>;
  74. declare removeSessionModels: HasManyRemoveAssociationsMixin<
  75. Session,
  76. number
  77. >;
  78. declare hasSessionModel: HasManyHasAssociationMixin<Session, number>;
  79. declare hasSessionModels: HasManyHasAssociationsMixin<Session, number>;
  80. declare countSessionModels: HasManyCountAssociationsMixin;
  81. declare createSessionModel: HasManyCreateAssociationMixin<
  82. Session,
  83. "userId"
  84. >;
  85. declare sessionModels?: NonAttribute<Session[]>;
  86. declare getCreatedNewsModels: HasManyGetAssociationsMixin<News>;
  87. declare addCreatedNewsModel: HasManyAddAssociationMixin<News, number>;
  88. declare addCreatedNewsModels: HasManyAddAssociationsMixin<News, number>;
  89. declare setCreatedNewsModels: HasManySetAssociationsMixin<News, number>;
  90. declare removeCreatedNewsModel: HasManyRemoveAssociationMixin<News, number>;
  91. declare removeCreatedNewsModels: HasManyRemoveAssociationsMixin<
  92. News,
  93. number
  94. >;
  95. declare hasCreatedNewsModel: HasManyHasAssociationMixin<News, number>;
  96. declare hasCreatedNewsModels: HasManyHasAssociationsMixin<News, number>;
  97. declare countCreatedNewsModels: HasManyCountAssociationsMixin;
  98. declare createCreatedNewsModel: HasManyCreateAssociationMixin<
  99. News,
  100. "createdBy"
  101. >;
  102. declare createdNewsModels?: NonAttribute<News[]>;
  103. declare static associations: {
  104. // eslint-disable-next-line no-use-before-define
  105. sessionModels: Association<User, Session>;
  106. // eslint-disable-next-line no-use-before-define
  107. createdNewsModels: Association<User, News>;
  108. };
  109. }
  110. // TODO add validation
  111. export const schema = {
  112. _id: {
  113. type: DataTypes.OBJECTID,
  114. autoNull: false,
  115. primaryKey: true
  116. },
  117. username: {
  118. type: DataTypes.STRING,
  119. allowNull: false
  120. },
  121. role: {
  122. type: DataTypes.ENUM(...Object.values(UserRole)),
  123. allowNull: false
  124. },
  125. emailVerified: {
  126. type: DataTypes.BOOLEAN,
  127. allowNull: true,
  128. defaultValue: false
  129. },
  130. emailVerificationToken: {
  131. type: DataTypes.STRING,
  132. allowNull: true
  133. },
  134. emailAddress: {
  135. type: DataTypes.STRING,
  136. allowNull: false
  137. },
  138. avatarType: {
  139. type: DataTypes.ENUM(...Object.values(UserAvatarType)),
  140. allowNull: false
  141. },
  142. avatarUrl: {
  143. type: DataTypes.STRING,
  144. allowNull: true
  145. },
  146. avatarColor: {
  147. type: DataTypes.ENUM(...Object.values(UserAvatarColor)),
  148. allowNull: true
  149. },
  150. password: {
  151. type: DataTypes.STRING,
  152. allowNull: false
  153. },
  154. passwordResetCode: {
  155. type: DataTypes.STRING,
  156. allowNull: true
  157. },
  158. passwordResetExpiresAt: {
  159. type: DataTypes.DATE,
  160. allowNull: true
  161. },
  162. passwordSetCode: {
  163. type: DataTypes.STRING,
  164. allowNull: true
  165. },
  166. passwordSetExpiresAt: {
  167. type: DataTypes.DATE,
  168. allowNull: true
  169. },
  170. githubId: {
  171. type: DataTypes.BIGINT,
  172. allowNull: true
  173. },
  174. githubAccessToken: {
  175. type: DataTypes.STRING,
  176. allowNull: true
  177. },
  178. songsRequested: {
  179. type: DataTypes.BIGINT,
  180. allowNull: false,
  181. defaultValue: 0
  182. },
  183. name: {
  184. type: DataTypes.STRING,
  185. allowNull: false
  186. },
  187. location: {
  188. type: DataTypes.STRING,
  189. allowNull: true
  190. },
  191. bio: {
  192. type: DataTypes.STRING,
  193. allowNull: true
  194. },
  195. nightmode: {
  196. type: DataTypes.BOOLEAN,
  197. allowNull: false,
  198. defaultValue: false
  199. },
  200. autoSkipDisliked: {
  201. type: DataTypes.BOOLEAN,
  202. allowNull: false,
  203. defaultValue: true
  204. },
  205. activityLogPublic: {
  206. type: DataTypes.BOOLEAN,
  207. allowNull: false,
  208. defaultValue: false
  209. },
  210. anonymousSongRequests: {
  211. type: DataTypes.BOOLEAN,
  212. allowNull: false,
  213. defaultValue: false
  214. },
  215. activityWatch: {
  216. type: DataTypes.BOOLEAN,
  217. allowNull: false,
  218. defaultValue: false
  219. },
  220. createdAt: DataTypes.DATE,
  221. updatedAt: DataTypes.DATE,
  222. hasPassword: {
  223. type: DataTypes.BOOLEAN,
  224. readonly: true
  225. },
  226. _name: {
  227. type: DataTypes.VIRTUAL,
  228. get() {
  229. return `users`;
  230. }
  231. },
  232. // Temporary
  233. favoriteStations: {
  234. type: DataTypes.VIRTUAL,
  235. get() {
  236. return [];
  237. }
  238. }
  239. };
  240. export const options = {
  241. defaultScope: {
  242. attributes: {
  243. exclude: [
  244. "emailVerificationToken",
  245. "password",
  246. "passwordResetCode",
  247. "passwordSetCode",
  248. "githubAccessToken"
  249. ]
  250. }
  251. }
  252. };
  253. export const setup = async () => {
  254. User.hasMany(Session, {
  255. as: "sessionModels",
  256. foreignKey: {
  257. name: "userId",
  258. type: DataTypes.OBJECTID,
  259. allowNull: false
  260. },
  261. onDelete: "RESTRICT",
  262. onUpdate: "RESTRICT"
  263. });
  264. User.hasMany(News, {
  265. as: "createdNewsModels",
  266. foreignKey: {
  267. name: "createdBy",
  268. type: DataTypes.OBJECTID,
  269. allowNull: false
  270. },
  271. onDelete: "RESTRICT",
  272. onUpdate: "RESTRICT"
  273. });
  274. // User.afterSave(async record => {});
  275. // User.afterDestroy(async record => {});
  276. };
  277. export default User;