|
1 | 1 | const argon2 = require('argon2') |
| 2 | +const mongoose = require('mongoose') |
2 | 3 | const uuid = require('uuid') |
3 | 4 | const logger = require('../../middleware/logger') |
4 | 5 | const { getConstants } = require('../../constants') |
@@ -89,110 +90,68 @@ async function getOrg (req, res, next) { |
89 | 90 |
|
90 | 91 | async function createOrg (req, res, next) { |
91 | 92 | try { |
92 | | - const CONSTANTS = getConstants() |
93 | | - const userRepo = req.ctx.repositories.getRegistryUserRepository() |
94 | | - const registryOrgRepo = req.ctx.repositories.getRegistryOrgRepository() |
| 93 | + const session = await mongoose.startSession() |
| 94 | + const repo = req.ctx.repositories.getBaseOrgRepository() |
95 | 95 | const body = req.ctx.body |
| 96 | + let createdOrg |
96 | 97 |
|
97 | | - // Short circuit if UUID provided |
98 | | - const bodyKeys = Object.keys(body).map(k => k.toLowerCase()) |
99 | | - if (bodyKeys.includes('uuid')) { |
| 98 | + // Do not allow the user to pass in a UUID |
| 99 | + if ((body?.UUID ?? null) || (body?.uuid ?? null)) { |
100 | 100 | return res.status(400).json(error.uuidProvided('org')) |
101 | 101 | } |
102 | 102 |
|
103 | | - const newOrg = new RegistryOrg() |
104 | | - bodyKeys.forEach(k => { |
105 | | - if (k === 'long_name') { |
106 | | - newOrg.long_name = body[k] |
107 | | - } else if (k === 'short_name') { |
108 | | - newOrg.short_name = body[k] |
109 | | - } else if (k === 'aliases') { |
110 | | - newOrg.aliases = [...new Set(body[k])] |
111 | | - } else if (k === 'cve_program_org_function') { |
112 | | - newOrg.cve_program_org_function = body[k] |
113 | | - } else if (k === 'authority') { |
114 | | - if ('active_roles' in body[k]) { |
115 | | - newOrg.authority.active_roles = [...new Set(body[k].active_roles)] |
116 | | - } |
117 | | - } else if (k === 'reports_to') { |
118 | | - // TODO: org check logic? |
119 | | - } else if (k === 'oversees') { |
120 | | - // TODO: org check logic? |
121 | | - } else if (k === 'root_or_tlr') { |
122 | | - newOrg.root_or_tlr = body[k] |
123 | | - } else if (k === 'users') { |
124 | | - // TODO: users logic? |
125 | | - } else if (k === 'charter_or_scope') { |
126 | | - newOrg.charter_or_scope = body[k] |
127 | | - } else if (k === 'disclosure_policy') { |
128 | | - newOrg.disclosure_policy = body[k] |
129 | | - } else if (k === 'product_list') { |
130 | | - newOrg.product_list = body[k] |
131 | | - } else if (k === 'soft_quota') { |
132 | | - newOrg.soft_quota = body[k] |
133 | | - } else if (k === 'hard_quota') { |
134 | | - newOrg.hard_quota = body[k] |
135 | | - } else if (k === 'contact_info') { |
136 | | - const { additionalContactUsers, admins, ...contactInfo } = body[k] |
137 | | - newOrg.contact_info = { |
138 | | - additional_contact_users: [...(additionalContactUsers || [])], |
139 | | - poc: '', |
140 | | - poc_email: '', |
141 | | - poc_phone: '', |
142 | | - admins: [...(admins || [])], |
143 | | - org_email: '', |
144 | | - website: '', |
145 | | - ...contactInfo |
146 | | - } |
| 103 | + try { |
| 104 | + session.startTransaction() |
| 105 | + const result = repo.validateOrg(req.ctx.body, { session }) |
| 106 | + if (!result.isValid) { |
| 107 | + logger.error(JSON.stringify({ uuid: req.ctx.uuid, message: 'CVE JSON schema validation FAILED.' })) |
| 108 | + await session.abortTransaction() |
| 109 | + |
| 110 | + // TODO: Investigate this, right now we are accepting either a one one-dimensional array of strings or just a string. |
| 111 | + // However, we are taking the "highest" authority |
| 112 | + // |
| 113 | + // |
| 114 | + // if (!Array.isArray(body?.authority) || body?.authority.some(item => typeof item !== 'string')) { |
| 115 | + // return res.status(400).json({ message: 'Parameters were invalid', details: [{ param: 'authority', msg: 'Parameter must be a one-dimensional array of strings' }] }) |
| 116 | + // } |
| 117 | + return res.status(400).json({ message: 'Parameters were invalid', errors: result.errors }) |
147 | 118 | } |
148 | | - }) |
149 | 119 |
|
150 | | - const doesExist = await registryOrgRepo.findOneByShortName(newOrg.short_name) |
151 | | - if (doesExist) { |
152 | | - logger.info({ uuid: req.ctx.uuid, message: newOrg.short_name + ' organization was not created because it already exists.' }) |
153 | | - return res.status(400).json(error.orgExists(newOrg.short_name)) |
154 | | - } |
| 120 | + // Check for duplicate short_name |
| 121 | + if (await repo.orgExists(body?.short_name, { session })) { |
| 122 | + logger.info({ |
| 123 | + uuid: req.ctx.uuid, |
| 124 | + message: `${body?.short_name} organization was not created because it already exists.` |
| 125 | + }) |
| 126 | + await session.abortTransaction() |
| 127 | + return res.status(400).json(error.orgExists(body?.short_name)) |
| 128 | + } |
155 | 129 |
|
156 | | - if (newOrg.reports_to === undefined) { |
157 | | - // TODO: This may need to be set to mitre, will ask the awg |
158 | | - newOrg.reports_to = null |
159 | | - } |
160 | | - if (newOrg.root_or_tlr === undefined) { |
161 | | - newOrg.root_or_tlr = false |
162 | | - } |
163 | | - if (newOrg.soft_quota === undefined) { // set to default quota if none is specified |
164 | | - newOrg.soft_quota = CONSTANTS.DEFAULT_ID_QUOTA |
165 | | - } |
166 | | - if (newOrg.hard_quota === undefined) { // set to default quota if none is specified |
167 | | - newOrg.hard_quota = CONSTANTS.DEFAULT_ID_QUOTA |
168 | | - } |
169 | | - if (newOrg.authority.active_roles.length === 1 && newOrg.authority.active_roles[0] === 'ADP') { // ADPs have quota of 0 |
170 | | - newOrg.soft_quota = 0 |
171 | | - newOrg.hard_quota = 0 |
172 | | - } |
| 130 | + // Create the org – repo.createOrg will handle field mapping |
| 131 | + createdOrg = await repo.createOrg(body, { session, upsert: true }) |
173 | 132 |
|
174 | | - newOrg.in_use = false |
175 | | - newOrg.UUID = uuid.v4() |
| 133 | + await session.commitTransaction() |
| 134 | + } catch (createErr) { |
| 135 | + await session.abortTransaction() |
| 136 | + throw createErr |
| 137 | + } finally { |
| 138 | + await session.endSession() |
| 139 | + } |
176 | 140 |
|
177 | | - await registryOrgRepo.updateByUUID(newOrg.UUID, newOrg, { upsert: true }) |
178 | | - const agt = setAggregateOrgObj({ UUID: newOrg.UUID }) |
179 | | - let result = await registryOrgRepo.aggregate(agt) |
180 | | - result = result.length > 0 ? result[0] : null |
| 141 | + const responseMessage = { |
| 142 | + message: `${body?.short_name} organization was successfully created.`, |
| 143 | + created: createdOrg |
| 144 | + } |
181 | 145 |
|
182 | 146 | const payload = { |
183 | | - action: 'create_registry_org', |
184 | | - change: result.short_name + ' was successfully created.', |
| 147 | + action: 'create_org', |
| 148 | + change: `${body?.short_name} organization was successfully created.`, |
185 | 149 | req_UUID: req.ctx.uuid, |
186 | | - org_UUID: await registryOrgRepo.getOrgUUID(req.ctx.org), |
187 | | - org: result |
| 150 | + org_UUID: createdOrg.UUID, |
| 151 | + org: createdOrg |
188 | 152 | } |
189 | | - payload.user_UUID = await userRepo.getUserUUID(req.ctx.user, payload.org_UUID) |
190 | | - logger.info(JSON.stringify(payload)) |
191 | 153 |
|
192 | | - const responseMessage = { |
193 | | - message: result.short_name + ' was successfully created.', |
194 | | - created: result |
195 | | - } |
| 154 | + logger.info(JSON.stringify(payload)) |
196 | 155 | return res.status(200).json(responseMessage) |
197 | 156 | } catch (err) { |
198 | 157 | next(err) |
|
0 commit comments