Mirror of https://github.com/roostorg/coop
github.com/roostorg/coop
1import sequelize, {
2 type CreationOptional,
3 type HasManyGetAssociationsMixin,
4 type InferAttributes,
5 type InferCreationAttributes,
6 type Sequelize,
7} from 'sequelize';
8
9import { validateUrl } from '../utils/url.js';
10import { type LocationBank } from './banks/LocationBankModel.js';
11import { type DataTypes } from './index.js';
12import { type Policy } from './PolicyModel.js';
13import { type SequelizeAction } from './rules/ActionModel.js';
14import { type Rule } from './rules/RuleModel.js';
15import { type User } from './UserModel.js';
16
17const { Model } = sequelize;
18
19export type Org = InstanceType<ReturnType<typeof makeOrgModel>>;
20
21/**
22 * Data Model for Organizations
23 */
24export default function makeOrgModel(
25 sequelize: Sequelize,
26 DataTypes: DataTypes,
27) {
28 class Org extends Model<
29 InferAttributes<Org, { omit: 'createdAt' | 'updatedAt' }>,
30 InferCreationAttributes<Org, { omit: 'createdAt' | 'updatedAt' }>
31 > {
32 public declare id: string;
33 public declare email: string;
34 public declare name: string;
35 public declare websiteUrl: string;
36 public declare apiKeyId?: CreationOptional<string>;
37 public declare onCallAlertEmail?: CreationOptional<string>;
38
39 public declare getRules: HasManyGetAssociationsMixin<Rule>;
40 public declare getActions: HasManyGetAssociationsMixin<SequelizeAction>;
41 // Has to use any below to avoid circular type errors.
42 // eslint-disable-next-line @typescript-eslint/no-explicit-any
43 public declare getContentTypes: HasManyGetAssociationsMixin<any>;
44 public declare getLocationBanks: HasManyGetAssociationsMixin<LocationBank>;
45 public declare getUsers: HasManyGetAssociationsMixin<User>;
46 public declare getPolicies: HasManyGetAssociationsMixin<Policy>;
47 public declare createdAt: Date;
48 public declare updatedAt: Date;
49
50 // eslint-disable-next-line @typescript-eslint/no-explicit-any
51 static associate(models: { [key: string]: any }) {
52 Org.hasMany(models.User, { as: 'Users' });
53 Org.hasMany(models.Rule, { as: 'Rules' });
54 Org.hasMany(models.Action, { as: 'Actions', foreignKey: 'orgId' });
55 Org.hasMany(models.ItemType, { as: 'ContentTypes' });
56 Org.hasMany(models.LocationBank, { as: 'LocationBanks' });
57 Org.hasMany(models.Policy, { as: 'policies' });
58 }
59 }
60
61 /* Fields */
62 Org.init(
63 {
64 id: {
65 type: DataTypes.STRING,
66 primaryKey: true,
67 },
68 email: {
69 type: DataTypes.STRING,
70 unique: true,
71 allowNull: false,
72 validate: {
73 isEmail: true,
74 notEmpty: true,
75 },
76 },
77 name: {
78 type: DataTypes.STRING,
79 unique: true,
80 allowNull: false,
81 validate: {
82 notEmpty: true,
83 },
84 },
85 websiteUrl: {
86 type: DataTypes.STRING,
87 unique: true,
88 allowNull: false,
89 validate: {
90 isValidUrl: validateUrl,
91 },
92 },
93 // ID of the AWS API Key resource that stores the API key. Not actually
94 // used for anything at the moment (instead, the API key is looked up in
95 // but potentially useful.
96 apiKeyId: {
97 type: DataTypes.STRING,
98 },
99 onCallAlertEmail: {
100 type: DataTypes.STRING,
101 validate: {
102 isEmail: true,
103 },
104 },
105 },
106 {
107 sequelize,
108 modelName: 'org',
109 underscored: true,
110 },
111 );
112
113 return Org;
114}