Skip to content

Commit cfe9094

Browse files
authored
Merge pull request #1940 from bluewave-labs/develop-saas
Develop saas -> Master saas
2 parents 4c92c62 + 00d3d63 commit cfe9094

File tree

1 file changed

+163
-0
lines changed

1 file changed

+163
-0
lines changed
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
'use strict';
2+
const { getTenantHash } = require("../../dist/tools/getTenantHash");
3+
4+
/** @type {import('sequelize-cli').Migration} */
5+
module.exports = {
6+
async up(queryInterface, Sequelize) {
7+
const transaction = await queryInterface.sequelize.transaction();
8+
try {
9+
const transaction = await queryInterface.sequelize.transaction();
10+
const organizations = await queryInterface.sequelize.query(`SELECT id FROM public.organizations;`, { transaction })
11+
for (let i = 1; i < organizations[0].length; i++) {
12+
const organization = organizations[0][i];
13+
const tenantHash = getTenantHash(organization.id);
14+
await queryInterface.sequelize.query(
15+
`CREATE TABLE "${tenantHash}".subclauses_iso__risks (
16+
subclause_id INTEGER NOT NULL,
17+
projects_risks_id INTEGER NOT NULL,
18+
PRIMARY KEY (subclause_id, projects_risks_id),
19+
FOREIGN KEY (subclause_id) REFERENCES "${tenantHash}".subclauses_iso(id) ON DELETE CASCADE ON UPDATE CASCADE,
20+
FOREIGN KEY (projects_risks_id) REFERENCES "${tenantHash}".projectrisks(id) ON DELETE CASCADE ON UPDATE CASCADE
21+
);`, { transaction }
22+
);
23+
24+
await Promise.all([
25+
`CREATE TABLE "${tenantHash}".controls_eu__risks (
26+
control_id INTEGER NOT NULL,
27+
projects_risks_id INTEGER NOT NULL,
28+
PRIMARY KEY (control_id, projects_risks_id),
29+
FOREIGN KEY (control_id) REFERENCES "${tenantHash}".controls_eu(id) ON DELETE CASCADE ON UPDATE CASCADE,
30+
FOREIGN KEY (projects_risks_id) REFERENCES "${tenantHash}".projectrisks(id) ON DELETE CASCADE ON UPDATE CASCADE
31+
);`,
32+
`CREATE TABLE "${tenantHash}".answers_eu__risks (
33+
answer_id INTEGER NOT NULL,
34+
projects_risks_id INTEGER NOT NULL,
35+
PRIMARY KEY (answer_id, projects_risks_id),
36+
FOREIGN KEY (answer_id) REFERENCES "${tenantHash}".answers_eu(id) ON DELETE CASCADE ON UPDATE CASCADE,
37+
FOREIGN KEY (projects_risks_id) REFERENCES "${tenantHash}".projectrisks(id) ON DELETE CASCADE ON UPDATE CASCADE
38+
);`
39+
].map(async (query) => {
40+
await queryInterface.sequelize.query(query, { transaction });
41+
}));
42+
43+
await queryInterface.sequelize.query(
44+
`CREATE OR REPLACE FUNCTION "${tenantHash}".check_only_one_organizational_project()
45+
RETURNS TRIGGER AS $$
46+
BEGIN
47+
-- If this row is being set to TRUE...
48+
IF NEW.is_organizational = TRUE THEN
49+
-- Count other rows (exclude the row we're updating/inserting)
50+
IF EXISTS (
51+
SELECT 1
52+
FROM "${tenantHash}".projects
53+
WHERE is_organizational = TRUE
54+
AND (TG_OP = 'INSERT' OR id <> NEW.id)
55+
) THEN
56+
RAISE EXCEPTION 'Only one project can have is_organizational = TRUE';
57+
END IF;
58+
END IF;
59+
RETURN NEW;
60+
END;
61+
$$ LANGUAGE plpgsql;`,
62+
{ transaction });
63+
const queries = [
64+
`ALTER TABLE "${tenantHash}".projects ALTER COLUMN ai_risk_classification DROP NOT NULL;`,
65+
`ALTER TABLE "${tenantHash}".projects ALTER COLUMN type_of_high_risk_role DROP NOT NULL;`,
66+
`ALTER TABLE "${tenantHash}".projects ALTER COLUMN goal DROP NOT NULL;`,
67+
`ALTER TABLE "${tenantHash}".projects ADD COLUMN is_organizational BOOLEAN DEFAULT FALSE;`,
68+
`CREATE TRIGGER "trg_${tenantHash}_ensure_one_organizational_project"
69+
BEFORE INSERT OR UPDATE ON "${tenantHash}".projects
70+
FOR EACH ROW
71+
EXECUTE FUNCTION "${tenantHash}".check_only_one_organizational_project();`,
72+
]
73+
await Promise.all(queries.map(query => queryInterface.sequelize.query(query, { transaction })));
74+
75+
for (let query of [
76+
`CREATE TABLE "${tenantHash}".subclauses_iso27001(
77+
id SERIAL PRIMARY KEY,
78+
implementation_description TEXT,
79+
evidence_links JSONB,
80+
status enum_subclauses_iso_status DEFAULT 'Not started',
81+
owner INT,
82+
reviewer INT,
83+
approver INT,
84+
due_date DATE,
85+
auditor_feedback TEXT,
86+
subclause_meta_id INT,
87+
projects_frameworks_id INT,
88+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
89+
is_demo BOOLEAN DEFAULT FALSE,
90+
FOREIGN KEY (subclause_meta_id) REFERENCES public.subclauses_struct_iso27001(id) ON DELETE CASCADE,
91+
FOREIGN KEY (projects_frameworks_id) REFERENCES "${tenantHash}".projects_frameworks(id) ON DELETE CASCADE,
92+
FOREIGN KEY (owner) REFERENCES public.users(id) ON DELETE SET NULL,
93+
FOREIGN KEY (reviewer) REFERENCES public.users(id) ON DELETE SET NULL,
94+
FOREIGN KEY (approver) REFERENCES public.users(id) ON DELETE SET NULL
95+
);`,
96+
`CREATE TABLE "${tenantHash}".subclauses_iso27001__risks(
97+
subclause_id INT,
98+
projects_risks_id INT PRIMARY KEY,
99+
FOREIGN KEY (subclause_id) REFERENCES "${tenantHash}".subclauses_iso27001(id) ON DELETE CASCADE,
100+
FOREIGN KEY (projects_risks_id) REFERENCES "${tenantHash}".projectrisks(id) ON DELETE CASCADE
101+
);`]) {
102+
await queryInterface.sequelize.query(query, { transaction });
103+
}
104+
105+
for (let query of [
106+
`CREATE TABLE "${tenantHash}".annexcontrols_iso27001(
107+
id SERIAL PRIMARY KEY,
108+
implementation_description TEXT,
109+
evidence_links JSONB,
110+
status enum_annexcategories_iso_status DEFAULT 'Not started',
111+
owner INT,
112+
reviewer INT,
113+
approver INT,
114+
due_date DATE,
115+
auditor_feedback TEXT,
116+
projects_frameworks_id INT,
117+
annexcontrol_meta_id INT,
118+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
119+
is_demo BOOLEAN DEFAULT FALSE,
120+
FOREIGN KEY (annexcontrol_meta_id) REFERENCES public.annexcontrols_struct_iso27001(id) ON DELETE CASCADE,
121+
FOREIGN KEY (projects_frameworks_id) REFERENCES "${tenantHash}".projects_frameworks(id) ON DELETE CASCADE,
122+
FOREIGN KEY (owner) REFERENCES public.users(id) ON DELETE SET NULL,
123+
FOREIGN KEY (reviewer) REFERENCES public.users(id) ON DELETE SET NULL,
124+
FOREIGN KEY (approver) REFERENCES public.users(id) ON DELETE SET NULL
125+
);`,
126+
`CREATE TABLE "${tenantHash}".annexcontrols_iso27001__risks(
127+
annexcontrol_id INT,
128+
projects_risks_id INT PRIMARY KEY,
129+
FOREIGN KEY (annexcontrol_id) REFERENCES "${tenantHash}".annexcontrols_iso27001(id) ON DELETE CASCADE,
130+
FOREIGN KEY (projects_risks_id) REFERENCES "${tenantHash}".projectrisks(id) ON DELETE CASCADE
131+
);`
132+
]) {
133+
await queryInterface.sequelize.query(query, { transaction });
134+
}
135+
136+
await queryInterface.sequelize.query(`
137+
CREATE TABLE IF NOT EXISTS "${tenantHash}".policy_manager (
138+
"id" SERIAL PRIMARY KEY,
139+
"title" VARCHAR(255) NOT NULL,
140+
"content_html" TEXT DEFAULT '',
141+
"status" VARCHAR(50) DEFAULT 'Draft',
142+
"tags" TEXT[] NOT NULL,
143+
"next_review_date" TIMESTAMP NOT NULL,
144+
"author_id" INTEGER NOT NULL NOT NULL,
145+
"assigned_reviewer_ids" INTEGER[],
146+
"last_updated_by" INTEGER NOT NULL,
147+
"last_updated_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
148+
"created_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
149+
FOREIGN KEY ("author_id") REFERENCES public.users(id) ON DELETE CASCADE,
150+
FOREIGN KEY ("last_updated_by") REFERENCES public.users(id) ON DELETE SET NULL
151+
);
152+
`, { transaction });
153+
}
154+
155+
await transaction.commit();
156+
} catch (error) {
157+
await transaction.rollback();
158+
throw error;
159+
}
160+
},
161+
162+
async down(queryInterface, Sequelize) { }
163+
};

0 commit comments

Comments
 (0)