@canmingir/link-express 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.test +3 -0
- package/.eslintrc.js +20 -0
- package/.gitattributes +1 -0
- package/.github/workflows/publish.yml +9 -0
- package/README.md +1 -0
- package/index.js +1 -0
- package/package.json +51 -0
- package/prepare.js +15 -0
- package/src/authorization.js +102 -0
- package/src/config.js +20 -0
- package/src/dynamodb.js +18 -0
- package/src/error.js +46 -0
- package/src/express.js +58 -0
- package/src/lib/settings.js +36 -0
- package/src/lib/test.js +58 -0
- package/src/models/Organization.js +17 -0
- package/src/models/Permission.js +33 -0
- package/src/models/Project.js +37 -0
- package/src/models/Settings.js +21 -0
- package/src/models/index.js +51 -0
- package/src/openapi.js +40 -0
- package/src/platform.js +46 -0
- package/src/postgres.js +211 -0
- package/src/routes/index.js +15 -0
- package/src/routes/metrics.js +12 -0
- package/src/routes/oauth.js +100 -0
- package/src/routes/organizations.js +42 -0
- package/src/routes/permissions.js +50 -0
- package/src/routes/projects.js +125 -0
- package/src/routes/settings.js +25 -0
- package/src/routes/test/oauth.spec.js +113 -0
- package/src/routes/test/permissions.spec.js +154 -0
- package/src/routes/test/projects.spec.js +186 -0
- package/src/routes/test/settings.spec.js +40 -0
- package/src/schemas/Organization.js +13 -0
- package/src/schemas/Permission.js +20 -0
- package/src/schemas/Project.js +14 -0
- package/src/schemas/index.js +5 -0
- package/src/seeds/Organization.json +17 -0
- package/src/seeds/Permission.json +165 -0
- package/src/seeds/Project.json +42 -0
- package/src/seeds/Settings.json +25 -0
- package/src/test.js +105 -0
package/src/platform.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const authorization = require("./authorization");
|
|
3
|
+
const error = require("./error");
|
|
4
|
+
|
|
5
|
+
let _express;
|
|
6
|
+
let _postgres;
|
|
7
|
+
let _dynamodb;
|
|
8
|
+
|
|
9
|
+
function init(config = {}) {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
try {
|
|
12
|
+
require.extensions[".md"] = function (module, filename) {
|
|
13
|
+
module.exports = fs.readFileSync(filename, "utf8").trim();
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const { postgres, dynamodb } = require("./config").init(config);
|
|
17
|
+
|
|
18
|
+
_express = require("./express");
|
|
19
|
+
|
|
20
|
+
if (postgres) {
|
|
21
|
+
_postgres = require("./postgres");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (dynamodb) {
|
|
25
|
+
_dynamodb = require("./dynamodb");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
resolve();
|
|
29
|
+
} catch (err) {
|
|
30
|
+
reject(err);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = {
|
|
36
|
+
init,
|
|
37
|
+
express: () => _express,
|
|
38
|
+
module: () => ({
|
|
39
|
+
Postgres: _postgres,
|
|
40
|
+
DynamoDB: _dynamodb,
|
|
41
|
+
Kafka: {},
|
|
42
|
+
}),
|
|
43
|
+
require: (pkg) => require(pkg),
|
|
44
|
+
authorization,
|
|
45
|
+
error,
|
|
46
|
+
};
|
package/src/postgres.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
const { Sequelize, Model } = require("sequelize");
|
|
2
|
+
const config = require("./config");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
postgres: { uri, debug = false, sync },
|
|
8
|
+
project,
|
|
9
|
+
} = config();
|
|
10
|
+
|
|
11
|
+
const originalDestroy = Model.prototype.destroy;
|
|
12
|
+
|
|
13
|
+
Model.prototype.destroy = function (options = {}) {
|
|
14
|
+
return originalDestroy.call(this, {
|
|
15
|
+
...options,
|
|
16
|
+
individualHooks: true,
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const sequelize = new Sequelize(process.env.PG || uri, {
|
|
21
|
+
logging: debug && console.log,
|
|
22
|
+
define: {
|
|
23
|
+
freezeTableName: true,
|
|
24
|
+
underscored: true,
|
|
25
|
+
timestamps: false,
|
|
26
|
+
paranoid: false,
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const seed = async () => {
|
|
31
|
+
const currentWorkingDirectory = process.cwd();
|
|
32
|
+
const baseDir = path.join(currentWorkingDirectory, "src", "models");
|
|
33
|
+
const seedDir = path.join(currentWorkingDirectory, "src", "seeds");
|
|
34
|
+
|
|
35
|
+
if (!fs.existsSync(seedDir)) {
|
|
36
|
+
console.error(`[NUC] Seed directory not found at path: ${seedDir}`);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!fs.existsSync(baseDir)) {
|
|
41
|
+
console.error(`[NUC] Model directory not found at path: ${baseDir}`);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let transaction = await sequelize.transaction();
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
if (project) {
|
|
49
|
+
const Organization = require("./models/Organization");
|
|
50
|
+
const { seed: companiesSeed } = require("./seeds/Organization.json");
|
|
51
|
+
|
|
52
|
+
await Organization.bulkCreate(companiesSeed, {
|
|
53
|
+
transaction,
|
|
54
|
+
validate: true,
|
|
55
|
+
});
|
|
56
|
+
console.log(`[NUC] Loading internal seed data for Organization`);
|
|
57
|
+
|
|
58
|
+
if (fs.existsSync(path.join(seedDir, "Organization.json"))) {
|
|
59
|
+
const seedData = require(path.join(seedDir, "Organization.json"));
|
|
60
|
+
const seed = seedData["seed"];
|
|
61
|
+
await Organization.bulkCreate(seed, {
|
|
62
|
+
transaction,
|
|
63
|
+
validate: true,
|
|
64
|
+
});
|
|
65
|
+
console.log(`[NUC] Loading seed data for Organization`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const Project = require("./models/Project");
|
|
69
|
+
const { seed: projectSeed } = require("./seeds/Project.json");
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
const { seed: extProjectSeed } = require(path.join(
|
|
73
|
+
seedDir,
|
|
74
|
+
"Project.json"
|
|
75
|
+
));
|
|
76
|
+
if (extProjectSeed) {
|
|
77
|
+
projectSeed.push(...extProjectSeed);
|
|
78
|
+
}
|
|
79
|
+
console.log(
|
|
80
|
+
`[NUC] Loading internal${
|
|
81
|
+
extProjectSeed ? " and external" : ""
|
|
82
|
+
} seed data for Project`
|
|
83
|
+
);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.log(`[NUC] Loading internal seed data for Project`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
await Project.bulkCreate(projectSeed, {
|
|
89
|
+
transaction,
|
|
90
|
+
validate: true,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const fileNames = fs
|
|
95
|
+
.readdirSync(baseDir)
|
|
96
|
+
.filter(
|
|
97
|
+
(fileName) =>
|
|
98
|
+
path.extname(fileName) === ".js" &&
|
|
99
|
+
!["index.js", "models.js"].includes(fileName)
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const fileSequences = fileNames
|
|
103
|
+
.map((fileName) => {
|
|
104
|
+
const seedName = fileName.split(".")[0];
|
|
105
|
+
const seederPath = path.join(seedDir, `${seedName}.json`);
|
|
106
|
+
|
|
107
|
+
if (fs.existsSync(seederPath)) {
|
|
108
|
+
const seedData = require(seederPath);
|
|
109
|
+
return { sequence: seedData.sequence, fileName };
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
})
|
|
113
|
+
.filter(Boolean)
|
|
114
|
+
.sort((a, b) => a.sequence - b.sequence);
|
|
115
|
+
|
|
116
|
+
for (const { fileName } of fileSequences) {
|
|
117
|
+
const seedName = fileName.split(".")[0];
|
|
118
|
+
const seederPath = path.join(seedDir, `${seedName}.json`);
|
|
119
|
+
const filePath = path.join(baseDir, fileName);
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const model = require(filePath);
|
|
123
|
+
const seedData = require(seederPath);
|
|
124
|
+
const seed = seedData["seed"];
|
|
125
|
+
|
|
126
|
+
console.log(`[NUC] Loading seed data for ${fileName}`);
|
|
127
|
+
await model.bulkCreate(seed, {
|
|
128
|
+
transaction,
|
|
129
|
+
validate: true,
|
|
130
|
+
});
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.error(`[NUC] Error loading seed data for ${fileName}:`, error);
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (project) {
|
|
138
|
+
const Permission = require("./models/Permission");
|
|
139
|
+
const { seed: permissionsSeed } = require("./seeds/Permission.json");
|
|
140
|
+
try {
|
|
141
|
+
const { seed: extPermissionsSeed } = require(path.join(
|
|
142
|
+
seedDir,
|
|
143
|
+
"Permission.json"
|
|
144
|
+
));
|
|
145
|
+
if (extPermissionsSeed) {
|
|
146
|
+
permissionsSeed.push(...extPermissionsSeed);
|
|
147
|
+
}
|
|
148
|
+
console.log(
|
|
149
|
+
`[NUC] Loading internal${
|
|
150
|
+
extPermissionsSeed ? " and external" : ""
|
|
151
|
+
} seed data for Permission`
|
|
152
|
+
);
|
|
153
|
+
} catch (error) {
|
|
154
|
+
console.log(`[NUC] Loading internal seed data for Permission`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
await Permission.bulkCreate(permissionsSeed, {
|
|
158
|
+
transaction,
|
|
159
|
+
validate: true,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const Settings = require("./models/Settings");
|
|
163
|
+
const { seed: settingsSeed } = require("./seeds/Settings.json");
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
const { seed: extSettingsSeed } = require(path.join(
|
|
167
|
+
seedDir,
|
|
168
|
+
"Settings.json"
|
|
169
|
+
));
|
|
170
|
+
if (extSettingsSeed) {
|
|
171
|
+
settingsSeed.push(...extSettingsSeed);
|
|
172
|
+
}
|
|
173
|
+
console.log(
|
|
174
|
+
`[NUC] Loading internal${
|
|
175
|
+
extSettingsSeed ? " and external" : ""
|
|
176
|
+
} seed data for Settings`
|
|
177
|
+
);
|
|
178
|
+
} catch (error) {
|
|
179
|
+
console.log(`[NUC] Loading internal seed data for Settings`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
await Settings.bulkCreate(settingsSeed, {
|
|
183
|
+
transaction,
|
|
184
|
+
validate: true,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
await transaction.commit();
|
|
189
|
+
} catch (error) {
|
|
190
|
+
if (transaction && !transaction.finished) {
|
|
191
|
+
await transaction.rollback();
|
|
192
|
+
}
|
|
193
|
+
console.error("[NUC] Error during seed operation:", error);
|
|
194
|
+
throw error;
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const associateModels = async () => {
|
|
199
|
+
const models = require("./models");
|
|
200
|
+
await models.init();
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
if (sync) {
|
|
204
|
+
setImmediate(async () => {
|
|
205
|
+
project && (await associateModels());
|
|
206
|
+
await sequelize.sync({ force: true });
|
|
207
|
+
await seed();
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
module.exports = { sequelize };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const metrics = require("./metrics");
|
|
2
|
+
const permissions = require("./permissions");
|
|
3
|
+
const oauth = require("./oauth");
|
|
4
|
+
const organizations = require("./organizations");
|
|
5
|
+
const projects = require("./projects");
|
|
6
|
+
const settings = require("./settings");
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
metrics,
|
|
10
|
+
permissions,
|
|
11
|
+
oauth,
|
|
12
|
+
organizations,
|
|
13
|
+
projects,
|
|
14
|
+
settings,
|
|
15
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
const Joi = require("joi");
|
|
2
|
+
const router = require("express").Router();
|
|
3
|
+
const jwt = require("jsonwebtoken");
|
|
4
|
+
const axios = require("axios");
|
|
5
|
+
const config = require("../config");
|
|
6
|
+
const { AuthenticationError } = require("../error");
|
|
7
|
+
const Permission = require("../models/Permission");
|
|
8
|
+
const { project } = config();
|
|
9
|
+
|
|
10
|
+
router.post("/", async (req, res) => {
|
|
11
|
+
let { appId, projectId, code, refreshToken, redirectUri } = Joi.attempt(
|
|
12
|
+
req.body,
|
|
13
|
+
Joi.object({
|
|
14
|
+
appId: Joi.string().required(),
|
|
15
|
+
projectId: Joi.string().optional(),
|
|
16
|
+
code: Joi.string().optional(),
|
|
17
|
+
refreshToken: Joi.string().optional(),
|
|
18
|
+
redirectUri: Joi.string().optional(),
|
|
19
|
+
})
|
|
20
|
+
.required()
|
|
21
|
+
.options({ stripUnknown: true })
|
|
22
|
+
);
|
|
23
|
+
if (!code && !refreshToken) {
|
|
24
|
+
return res.status(400).send("Missing OAuth Code and Refresh Token");
|
|
25
|
+
}
|
|
26
|
+
if (code && redirectUri) {
|
|
27
|
+
const params = new URLSearchParams();
|
|
28
|
+
params.append("client_id", project.oauth.clientId);
|
|
29
|
+
params.append("client_secret", process.env.OAUTH_CLIENT_SECRET);
|
|
30
|
+
params.append("code", code);
|
|
31
|
+
params.append("redirect_uri", redirectUri);
|
|
32
|
+
params.append("grant_type", "authorization_code");
|
|
33
|
+
const { data } = await axios.post(
|
|
34
|
+
project.oauth.tokenUrl,
|
|
35
|
+
params.toString(),
|
|
36
|
+
{
|
|
37
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const urlParams = new URLSearchParams(data);
|
|
42
|
+
|
|
43
|
+
if (urlParams.get("error")) {
|
|
44
|
+
throw new AuthenticationError(urlParams.get("error_description"));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
refreshToken = urlParams.get("access_token");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const { data } = await axios.get(project.oauth.userUrl, {
|
|
51
|
+
headers: {
|
|
52
|
+
Authorization: `Bearer ${refreshToken}`,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const userId = data[project.oauth.jwt.identifier].toString();
|
|
57
|
+
|
|
58
|
+
let accessToken;
|
|
59
|
+
|
|
60
|
+
if (projectId) {
|
|
61
|
+
const permissions = await Permission.findAll({
|
|
62
|
+
where: { userId, projectId, appId },
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (!permissions.length) {
|
|
66
|
+
accessToken = jwt.sign(
|
|
67
|
+
{ sub: userId, iss: "nuc", aid: appId },
|
|
68
|
+
process.env.JWT_SECRET,
|
|
69
|
+
{
|
|
70
|
+
expiresIn: "12h",
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
} else {
|
|
74
|
+
accessToken = jwt.sign(
|
|
75
|
+
{
|
|
76
|
+
sub: userId,
|
|
77
|
+
iss: "nuc",
|
|
78
|
+
aud: projectId,
|
|
79
|
+
oid: permissions[0].organizationId,
|
|
80
|
+
aid: appId,
|
|
81
|
+
rls: permissions.map((permission) => permission.role),
|
|
82
|
+
},
|
|
83
|
+
process.env.JWT_SECRET,
|
|
84
|
+
{ expiresIn: "12h" }
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
accessToken = jwt.sign(
|
|
89
|
+
{ sub: userId, iss: "nuc", aid: appId },
|
|
90
|
+
process.env.JWT_SECRET,
|
|
91
|
+
{
|
|
92
|
+
expiresIn: "12h",
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
res.status(200).json({ accessToken, refreshToken });
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
module.exports = router;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const router = require("express").Router();
|
|
2
|
+
const Organization = require("../models/Organization");
|
|
3
|
+
const Permission = require("../models/Permission");
|
|
4
|
+
|
|
5
|
+
router.post("/", async (req, res) => {
|
|
6
|
+
const organization = req.body;
|
|
7
|
+
|
|
8
|
+
Organization.create(organization).then((organization) => {
|
|
9
|
+
res.status(201).json(organization);
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
router.get("/", async (req, res) => {
|
|
14
|
+
const { userId } = req.session;
|
|
15
|
+
|
|
16
|
+
const organizations = await Organization.findAll({
|
|
17
|
+
include: [
|
|
18
|
+
{
|
|
19
|
+
model: Permission,
|
|
20
|
+
as: "permissions",
|
|
21
|
+
where: { userId },
|
|
22
|
+
attributes: [],
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
res.status(200).json(organizations);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
router.get("/:id", async (req, res) => {
|
|
31
|
+
const { organizationId } = req.session;
|
|
32
|
+
const { id } = req.params;
|
|
33
|
+
|
|
34
|
+
if (organizationId !== id) {
|
|
35
|
+
return res.status(401).end();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const organization = await Organization.findByPk(organizationId);
|
|
39
|
+
res.status(200).json(organization);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
module.exports = router;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const router = require("express").Router();
|
|
2
|
+
const Permission = require("../models/Permission");
|
|
3
|
+
|
|
4
|
+
router.post("/", async (req, res) => {
|
|
5
|
+
const { userId } = req.body;
|
|
6
|
+
const { projectId, organizationId, appId, roles } = req.session;
|
|
7
|
+
const permissionInstance = await Permission.create({
|
|
8
|
+
userId,
|
|
9
|
+
projectId,
|
|
10
|
+
organizationId,
|
|
11
|
+
appId,
|
|
12
|
+
role: roles[0],
|
|
13
|
+
});
|
|
14
|
+
res.status(201).json(permissionInstance);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
router.get("/", async (req, res) => {
|
|
18
|
+
const { projectId, organizationId } = req.session;
|
|
19
|
+
|
|
20
|
+
const permissions = await Permission.findAll({
|
|
21
|
+
where: {
|
|
22
|
+
projectId,
|
|
23
|
+
organizationId,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
if (permissions.length === 0) {
|
|
28
|
+
res.status(404).end();
|
|
29
|
+
} else {
|
|
30
|
+
res.status(200).json(permissions);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
router.delete("/:userId", async (req, res) => {
|
|
35
|
+
const { projectId, organizationId } = req.session;
|
|
36
|
+
const userId = req.params.userId;
|
|
37
|
+
|
|
38
|
+
const instance = await Permission.findOne({
|
|
39
|
+
where: { userId: userId, projectId, organizationId },
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (instance) {
|
|
43
|
+
await instance.destroy();
|
|
44
|
+
res.status(204).end();
|
|
45
|
+
} else {
|
|
46
|
+
res.status(404).end();
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
module.exports = router;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
const Joi = require("joi");
|
|
2
|
+
const router = require("express").Router();
|
|
3
|
+
const Project = require("../models/Project");
|
|
4
|
+
const Organization = require("../models/Organization");
|
|
5
|
+
const Permission = require("../models/Permission");
|
|
6
|
+
const schemas = require("../schemas");
|
|
7
|
+
const config = require("../config");
|
|
8
|
+
|
|
9
|
+
router.post("/", async (req, res) => {
|
|
10
|
+
const project = Joi.attempt(req.body, schemas.Project);
|
|
11
|
+
|
|
12
|
+
if (config.link && config.link.project) {
|
|
13
|
+
Joi.attempt(project.type, config.link.project.type);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const projectInstance = await Project.create(project);
|
|
17
|
+
|
|
18
|
+
await Permission.create({
|
|
19
|
+
userId: req.session.userId,
|
|
20
|
+
organizationId: project.organizationId,
|
|
21
|
+
role: "OWNER",
|
|
22
|
+
projectId: projectInstance.id,
|
|
23
|
+
appId: req.session.appId,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
res.status(201).json(projectInstance);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
router.get("/", async (req, res) => {
|
|
30
|
+
const { userId, appId } = req.session;
|
|
31
|
+
|
|
32
|
+
const projects = await Project.findAll({
|
|
33
|
+
include: [
|
|
34
|
+
{
|
|
35
|
+
model: Permission,
|
|
36
|
+
where: { userId, appId },
|
|
37
|
+
attributes: [],
|
|
38
|
+
as: "permissions",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
model: Organization,
|
|
42
|
+
as: "organization",
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
attributes: {
|
|
46
|
+
exclude: ["organizationId"],
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
res.status(200).json(projects);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
router.get("/:id", async (req, res) => {
|
|
54
|
+
const { userId, organizationId } = req.session;
|
|
55
|
+
const { id } = req.params;
|
|
56
|
+
|
|
57
|
+
const project = await Project.findOne({
|
|
58
|
+
include: [
|
|
59
|
+
{
|
|
60
|
+
model: Permission,
|
|
61
|
+
where: { userId, organizationId },
|
|
62
|
+
attributes: [],
|
|
63
|
+
as: "permissions",
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
where: { id },
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
if (project) {
|
|
70
|
+
res.status(200).json(project);
|
|
71
|
+
} else {
|
|
72
|
+
res.status(404).end();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
router.delete("/:id", async (req, res) => {
|
|
77
|
+
const { userId, organizationId } = req.session;
|
|
78
|
+
const { id } = req.params;
|
|
79
|
+
|
|
80
|
+
const project = await Project.findOne({
|
|
81
|
+
include: [
|
|
82
|
+
{
|
|
83
|
+
model: Permission,
|
|
84
|
+
where: { userId, organizationId },
|
|
85
|
+
attributes: [],
|
|
86
|
+
as: "permissions",
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
where: { id },
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (project) {
|
|
93
|
+
await project.destroy();
|
|
94
|
+
res.status(204).end();
|
|
95
|
+
} else {
|
|
96
|
+
res.status(404).end();
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
router.patch("/:id", async (req, res) => {
|
|
101
|
+
const { userId, organizationId } = req.session;
|
|
102
|
+
const { id } = req.params;
|
|
103
|
+
|
|
104
|
+
const project = await Project.findOne({
|
|
105
|
+
include: [
|
|
106
|
+
{
|
|
107
|
+
model: Permission,
|
|
108
|
+
where: { userId, organizationId },
|
|
109
|
+
attributes: [],
|
|
110
|
+
as: "permissions",
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
where: { id },
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
if (project) {
|
|
117
|
+
const updatedProject = Joi.attempt(req.body, schemas.Project);
|
|
118
|
+
await project.update(updatedProject);
|
|
119
|
+
res.status(200).json(project);
|
|
120
|
+
} else {
|
|
121
|
+
res.status(404).end();
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
module.exports = router;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const express = require("express");
|
|
2
|
+
const router = express.Router({ mergeParams: true });
|
|
3
|
+
|
|
4
|
+
const settings = require("../lib/settings");
|
|
5
|
+
const { AuthorizationError } = require("../error");
|
|
6
|
+
|
|
7
|
+
router.get("/", async (req, res) => {
|
|
8
|
+
if (req.params.projectId !== req.session.projectId) {
|
|
9
|
+
throw new AuthorizationError();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const setting = await settings.get(req.session, req.params);
|
|
13
|
+
res.json(setting);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
router.patch("/", async (req, res) => {
|
|
17
|
+
if (req.params.projectId !== req.session.projectId) {
|
|
18
|
+
throw new AuthorizationError();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
await settings.upsert(req.session, req.body, req.params);
|
|
22
|
+
res.end();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
module.exports = router;
|