From 2a475673d681ae262ea62221d9f6f28ae90b30ef Mon Sep 17 00:00:00 2001 From: david-rocca Date: Mon, 13 Apr 2026 10:47:17 -0400 Subject: [PATCH 01/11] TEMP: Unlock Endpoint for dev --- src/controller/org.controller/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/org.controller/index.js b/src/controller/org.controller/index.js index f7805c496..1c5e6f110 100644 --- a/src/controller/org.controller/index.js +++ b/src/controller/org.controller/index.js @@ -640,7 +640,7 @@ router.put('/registry/org/:shortname', */ mw.useRegistry(), mw.validateUser, - mw.onlySecretariat, + // mw.onlySecretariat, parseError, parsePutParams, registryOrgController.UPDATE_ORG From b5b629b7f2411c4fe4bdc48df0b1fab9f138d9d2 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Mon, 13 Apr 2026 10:57:58 -0400 Subject: [PATCH 02/11] Stopped a user from passing in secret in update user --- .../registry-user.controller.js | 5 +++++ src/controller/user.controller/error.js | 7 +++++++ test/integration-tests/user/updateUserTest.js | 16 ++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/src/controller/registry-user.controller/registry-user.controller.js b/src/controller/registry-user.controller/registry-user.controller.js index fdfa630a8..6bf47187b 100644 --- a/src/controller/registry-user.controller/registry-user.controller.js +++ b/src/controller/registry-user.controller/registry-user.controller.js @@ -227,6 +227,11 @@ async function updateUser (req, res, next) { const body = req.ctx.body + if ('secret' in body) { + logger.info({ uuid: req.ctx.uuid, message: 'User attempted to update the secret.' }) + return res.status(400).json(error.secretUpdateNotAllowed()) + } + const requestingUserParameters = { org: req.ctx.org, username: req.ctx.user diff --git a/src/controller/user.controller/error.js b/src/controller/user.controller/error.js index 11ab679b2..7e0f7006f 100644 --- a/src/controller/user.controller/error.js +++ b/src/controller/user.controller/error.js @@ -64,6 +64,13 @@ class UserControllerError extends idrErr.IDRError { err.message = 'This information can only be viewed or modified by the Secretariat, an Org Admin or if the requester is the user.' return err } + + secretUpdateNotAllowed () { + const err = {} + err.error = 'SECRET_UPDATE_NOT_ALLOWED' + err.message = 'The secret field must be updated through the reset_secret endpoint' + return err + } } module.exports = { diff --git a/test/integration-tests/user/updateUserTest.js b/test/integration-tests/user/updateUserTest.js index d885536af..34e4f1f18 100644 --- a/test/integration-tests/user/updateUserTest.js +++ b/test/integration-tests/user/updateUserTest.js @@ -189,5 +189,21 @@ describe('Testing Edit user endpoint', () => { expect(res.body.error).to.contain('USER_ALREADY_IN_ORG') }) }) + it('Should return an error when attempting to update secret with registry enabled', async () => { + let user + await chai.request(app).get('/api/registry/org/win_5/user/jasminesmith@win_5.com').set(constants.nonSecretariatUserHeaders).then((res) => { user = res.body }) + await chai.request(app) + .put('/api/registry/org/win_5/user/jasminesmith@win_5.com') + .set(constants.nonSecretariatUserHeaders) + .send({ + ...user, + secret: 'some_new_secret_hash' + }) + .then((res, err) => { + expect(err).to.be.undefined + expect(res).to.have.status(400) + expect(res.body.error).to.equal('SECRET_UPDATE_NOT_ALLOWED') + }) + }) }) }) From dfa882c6ca9deaf3a3ba2455c6b619b92fc5a042 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Mon, 13 Apr 2026 15:09:30 -0400 Subject: [PATCH 03/11] unlocking for james --- src/controller/org.controller/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/org.controller/index.js b/src/controller/org.controller/index.js index f7805c496..1c5e6f110 100644 --- a/src/controller/org.controller/index.js +++ b/src/controller/org.controller/index.js @@ -640,7 +640,7 @@ router.put('/registry/org/:shortname', */ mw.useRegistry(), mw.validateUser, - mw.onlySecretariat, + // mw.onlySecretariat, parseError, parsePutParams, registryOrgController.UPDATE_ORG From 4f6dc58ee340c44854376c9ac1c8b1800f15a68c Mon Sep 17 00:00:00 2001 From: david-rocca Date: Mon, 13 Apr 2026 11:44:35 -0400 Subject: [PATCH 04/11] Fixed optionallyValidateUser and added more tests for it --- src/middleware/middleware.js | 4 +- test/integration-tests/cve-id/getCveIdTest.js | 47 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/middleware/middleware.js b/src/middleware/middleware.js index 03aee444c..67e47e7b8 100644 --- a/src/middleware/middleware.js +++ b/src/middleware/middleware.js @@ -61,7 +61,7 @@ async function optionallyValidateUser (req, res, next) { authenticated = false } else { result = await userRepo.findOneByUserNameAndOrgUUID(user, orgUUID) - if (!result || !result.active) { + if (!result || result.status === 'inactive') { authenticated = false } else { const isPwd = await argon2.verify(result.secret, key) @@ -133,7 +133,7 @@ async function validateUser (req, res, next) { return res.status(401).json(error.unauthorized()) } - if (result.active === false || result.status === 'inactive') { + if (result.status === 'inactive') { logger.warn(JSON.stringify({ uuid: req.ctx.uuid, message: 'User deactivated. Authentication failed for ' + user })) return res.status(401).json(error.unauthorized()) } diff --git a/test/integration-tests/cve-id/getCveIdTest.js b/test/integration-tests/cve-id/getCveIdTest.js index 12ed01c0b..233820fb7 100644 --- a/test/integration-tests/cve-id/getCveIdTest.js +++ b/test/integration-tests/cve-id/getCveIdTest.js @@ -188,6 +188,53 @@ describe('Testing Get CVE-ID endpoint', () => { expect(cveIdObject.requested_by.user).to.equal(constants.nonSecretariatUserHeaders['CVE-API-USER']) }) }) + it('For Secretariat users, should return full information when getting a single RESERVED CVE ID', async () => { + const cveId = await helpers.cveIdReserveHelper(1, '2023', constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'non-sequential') + + await chai.request(app) + .get(`/api/cve-id/${cveId}`) + .set(constants.headers) + .then(async (res, err) => { + expect(err).to.be.undefined + expect(res).to.have.status(200) + expect(res.body.cve_id).to.equal(cveId) + expect(res.body.state).to.equal('RESERVED') + // Secretariat user should see owning org details + expect(res.body.owning_cna).to.equal(constants.nonSecretariatUserHeaders['CVE-API-ORG']) + }) + }) + + it('For owning CNA users, should return full information when getting a single RESERVED CVE ID', async () => { + const cveId = await helpers.cveIdReserveHelper(1, '2023', constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'non-sequential') + + await chai.request(app) + .get(`/api/cve-id/${cveId}`) + .set(constants.nonSecretariatUserHeaders) + .then(async (res, err) => { + expect(err).to.be.undefined + expect(res).to.have.status(200) + expect(res.body.cve_id).to.equal(cveId) + expect(res.body.state).to.equal('RESERVED') + // Non-secretariat user from owning org should see owning org details + expect(res.body.owning_cna).to.equal(constants.nonSecretariatUserHeaders['CVE-API-ORG']) + }) + }) + + it('For non-owning CNA users, should return partial information and redacted owning_cna when getting a single RESERVED CVE ID', async function () { + const cveId = await helpers.cveIdReserveHelper(1, '2023', constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'non-sequential') + + await chai.request(app) + .get(`/api/cve-id/${cveId}`) + .set(constants.nonSecretariatUserHeaders3) // evidence_15 + .then(async (res, err) => { + expect(err).to.be.undefined + expect(res).to.have.status(200) + expect(res.body.cve_id).to.equal(cveId) + expect(res.body.state).to.equal('RESERVED') + expect(res.body.owning_cna).to.equal('[REDACTED]') + expect(res.body).to.not.have.property('requested_by') + }) + }) }) context('negative tests', () => { it('Feb 29 2100 should not be valid', async () => { From dc18dbf2fd379afda06ceea7f78797d3e45a193c Mon Sep 17 00:00:00 2001 From: david-rocca Date: Mon, 13 Apr 2026 13:33:13 -0400 Subject: [PATCH 05/11] Added a bunch more tests, and fixed an updating issue in users --- src/repositories/baseUserRepository.js | 25 ++++++++---- test/integration-tests/cve-id/getCveIdTest.js | 37 ++++++++++++++++++ test/integration-tests/helpers.js | 38 ++++++++++++++++++- 3 files changed, 92 insertions(+), 8 deletions(-) diff --git a/src/repositories/baseUserRepository.js b/src/repositories/baseUserRepository.js index 903f6d58a..98a0f5289 100644 --- a/src/repositories/baseUserRepository.js +++ b/src/repositories/baseUserRepository.js @@ -7,8 +7,15 @@ const BaseOrgModel = require('../model/baseorg') const RegistryUser = require('../model/registryuser') const cryptoRandomString = require('crypto-random-string') const UserRepository = require('./userRepository') -const _ = require('lodash') const getConstants = require('../constants').getConstants +const _ = require('lodash') + +const skipNulls = (objValue, srcValue) => { + if (_.isArray(objValue)) { + return srcValue + } + return undefined +} /** * @function setAggregateUserObj @@ -514,19 +521,23 @@ class BaseUserRepository extends BaseRepository { throw new Error('Legacy user not found') } + const { ...incomingUserBody } = incomingUser let legacyObjectRaw let registryObjectRaw if (!isRegistryObject) { - legacyObjectRaw = incomingUser - registryObjectRaw = this.convertLegacyToRegistry(incomingUser) + legacyObjectRaw = incomingUserBody + registryObjectRaw = this.convertLegacyToRegistry(incomingUserBody) } else { - registryObjectRaw = incomingUser - legacyObjectRaw = this.convertRegistryToLegacy(incomingUser) + registryObjectRaw = incomingUserBody + legacyObjectRaw = this.convertRegistryToLegacy(incomingUserBody) } - const updatedLegacyUser = _.merge(legacyUser, legacyObjectRaw) - const updatedRegistryUser = _.merge(registryUser, registryObjectRaw) + const protectedFieldsRegistry = ['_id', 'UUID', '__v', 'secret', 'created', 'last_updated'] + const protectedFieldsLegacy = ['_id', 'UUID', '__v', 'secret', 'time', 'org_UUID'] + + const updatedRegistryUser = registryUser.overwrite(_.mergeWith(_.pick(registryUser.toObject(), protectedFieldsRegistry), registryObjectRaw, skipNulls)) + const updatedLegacyUser = legacyUser.overwrite(_.mergeWith(_.pick(legacyUser.toObject(), protectedFieldsLegacy), legacyObjectRaw, skipNulls)) try { if (incomingUser.org_short_name) { diff --git a/test/integration-tests/cve-id/getCveIdTest.js b/test/integration-tests/cve-id/getCveIdTest.js index 233820fb7..81ff1cc6d 100644 --- a/test/integration-tests/cve-id/getCveIdTest.js +++ b/test/integration-tests/cve-id/getCveIdTest.js @@ -237,6 +237,43 @@ describe('Testing Get CVE-ID endpoint', () => { }) }) context('negative tests', () => { + it('An inactive user should be treated as unauthenticated for optionallyValidateUser endpoints (GET /api/cve-id/:id)', async function () { + const cveId = await helpers.cveIdReserveHelper(1, '2023', constants.nonSecretariatUserHeaders['CVE-API-ORG'], 'non-sequential') + + // Deactivate user + await helpers.userDeactivateAsSecHelper(constants.nonSecretariatUserHeaders['CVE-API-USER'], constants.nonSecretariatUserHeaders['CVE-API-ORG']) + + await chai.request(app) + .get(`/api/cve-id/${cveId}`) + .set(constants.nonSecretariatUserHeaders) + .then(async (res, err) => { + expect(err).to.be.undefined + expect(res).to.have.status(200) + expect(res.body.cve_id).to.equal(cveId) + expect(res.body.owning_cna).to.equal('[REDACTED]') // Should be redacted because user is treated as unauthenticated + + // Reactivate user for other tests + await helpers.userReactivateAsSecHelper(constants.nonSecretariatUserHeaders['CVE-API-USER'], constants.nonSecretariatUserHeaders['CVE-API-ORG']) + }) + }) + + it('An inactive user should be denied access for validateUser endpoints (GET /api/cve-id)', async function () { + // Deactivate user + await helpers.userDeactivateAsSecHelper(constants.nonSecretariatUserHeaders['CVE-API-USER'], constants.nonSecretariatUserHeaders['CVE-API-ORG']) + + await chai.request(app) + .get('/api/cve-id') + .set(constants.nonSecretariatUserHeaders) + .then(async (res, err) => { + expect(err).to.be.undefined + expect(res).to.have.status(401) + expect(res.body.error).to.equal('UNAUTHORIZED') + + // Reactivate user for other tests + await helpers.userReactivateAsSecHelper(constants.nonSecretariatUserHeaders['CVE-API-USER'], constants.nonSecretariatUserHeaders['CVE-API-ORG']) + }) + }) + it('Feb 29 2100 should not be valid', async () => { await chai.request(app) .get('/api/cve-id?time_modified.gt=2100-02-29T00:00:00Z') diff --git a/test/integration-tests/helpers.js b/test/integration-tests/helpers.js index 4fd5cce6f..2b8685d4e 100644 --- a/test/integration-tests/helpers.js +++ b/test/integration-tests/helpers.js @@ -116,6 +116,40 @@ async function updateOwningOrgAsSecHelper (cveId, newOrgShortName) { }) } +async function userDeactivateAsSecHelper (userName, orgShortName) { + const user = await chai.request(app) + .get(`/api/registry/org/${orgShortName}/user/${userName}`) + .set(constants.headers) + .then(res => res.body) + + await chai.request(app) + .put(`/api/registry/org/${orgShortName}/user/${userName}`) + .set(constants.headers) + .send({ ...user, status: 'inactive' }) + .then((res, err) => { + // Safety Expect + expect(res).to.have.status(200) + }) +} + +async function userReactivateAsSecHelper (userName, orgShortName) { + const user = await chai.request(app) + .get(`/api/registry/org/${orgShortName}/user/${userName}`) + .set(constants.headers) + .then(res => res.body) + + user.status = 'active' + + await chai.request(app) + .put(`/api/registry/org/${orgShortName}/user/${userName}`) + .set(constants.headers) + .send(user) + .then((res, err) => { + // Safety Expect + expect(res).to.have.status(200) + }) +} + module.exports = { cveIdReserveHelper, cveIdBulkReserveHelper, @@ -126,5 +160,7 @@ module.exports = { cveUpdateAsSecHelper, cveUpdateAsCnaHelperWithAdpContainer, userOrgUpdateAsSecHelper, - updateOwningOrgAsSecHelper + updateOwningOrgAsSecHelper, + userDeactivateAsSecHelper, + userReactivateAsSecHelper } From 34aa717eb4046da381bb9c0fc7074a3c30311dcb Mon Sep 17 00:00:00 2001 From: david-rocca Date: Mon, 13 Apr 2026 14:23:57 -0400 Subject: [PATCH 06/11] Fixing failing test --- test/unit-tests/middleware/mockObjects.middleware.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/unit-tests/middleware/mockObjects.middleware.js b/test/unit-tests/middleware/mockObjects.middleware.js index 81fdfd9ce..a353d8444 100644 --- a/test/unit-tests/middleware/mockObjects.middleware.js +++ b/test/unit-tests/middleware/mockObjects.middleware.js @@ -34,7 +34,8 @@ const existentUser = { }, secret: '$argon2i$v=19$m=4096,t=3,p=1$+qGHEfH5h4/tk404iWBxFw$xV96/b4NvQVvlZIq57wTS8s7gfKzsfMXRiOyf3ffgcw', username: 'cpadro', - active: true + active: true, + status: 'active' } const deactivatedUser = { @@ -49,7 +50,8 @@ const deactivatedUser = { }, secret: '$argon2i$v=19$m=4096,t=3,p=1$+qGHEfH5h4/tk404iWBxFw$xV96/b4NvQVvlZIq57wTS8s7gfKzsfMXRiOyf3ffgcw', username: 'flast', - active: false + active: false, + status: 'inactive' } module.exports = { From 1431899387ed611c5b62d1c11c559a1019767792 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Mon, 13 Apr 2026 15:54:34 -0400 Subject: [PATCH 07/11] check the org in the url --- .../registry-user.controller.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/controller/registry-user.controller/registry-user.controller.js b/src/controller/registry-user.controller/registry-user.controller.js index 6bf47187b..46cb2c969 100644 --- a/src/controller/registry-user.controller/registry-user.controller.js +++ b/src/controller/registry-user.controller/registry-user.controller.js @@ -253,6 +253,18 @@ async function updateUser (req, res, next) { : await userRepo.findOneByUsernameAndOrgShortname(userToEditParameters.username, userToEditParameters.org, { session }) const org = await orgRepo.findOneByShortName(userToEditParameters.org) + if (!org) { + logger.info({ uuid: req.ctx.uuid, message: `Target organization ${userToEditParameters.org} does not exist.` }) + return res.status(404).json(error.orgDnePathParam(userToEditParameters.org)) + } + + if (body.org_short_name) { + const targetOrg = await orgRepo.findOneByShortName(body.org_short_name) + if (!targetOrg) { + logger.info({ uuid: req.ctx.uuid, message: `Target organization ${body.org_short_name} does not exist.` }) + return res.status(404).json(error.orgDnePathParam(body.org_short_name)) + } + } if (body.org_short_name && !isSecretariat) { logger.info({ uuid: req.ctx.uuid, message: 'Only Secretariat can reassign user organization.' }) From ddfedd4e1bbf4fcf4210bd07b2baaa845e4df533 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Mon, 13 Apr 2026 16:20:30 -0400 Subject: [PATCH 08/11] conflicts --- .../registry-user.controller.js | 10 +++--- test/integration-tests/user/updateUserTest.js | 31 +++++++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/controller/registry-user.controller/registry-user.controller.js b/src/controller/registry-user.controller/registry-user.controller.js index 46cb2c969..bd8d9e234 100644 --- a/src/controller/registry-user.controller/registry-user.controller.js +++ b/src/controller/registry-user.controller/registry-user.controller.js @@ -258,6 +258,11 @@ async function updateUser (req, res, next) { return res.status(404).json(error.orgDnePathParam(userToEditParameters.org)) } + if (body.org_short_name && !isSecretariat) { + logger.info({ uuid: req.ctx.uuid, message: 'Only Secretariat can reassign user organization.' }) + return res.status(403).json(error.notAllowedToChangeOrganization()) + } + if (body.org_short_name) { const targetOrg = await orgRepo.findOneByShortName(body.org_short_name) if (!targetOrg) { @@ -266,11 +271,6 @@ async function updateUser (req, res, next) { } } - if (body.org_short_name && !isSecretariat) { - logger.info({ uuid: req.ctx.uuid, message: 'Only Secretariat can reassign user organization.' }) - return res.status(403).json(error.notAllowedToChangeOrganization()) - } - if (body.org_short_name && isSecretariat && userToEditParameters.org === org.short_name && body.org_short_name === org.short_name) { logger.info({ uuid: req.ctx.uuid, message: `User ${userToEditParameters.username} is already in organization ${userToEditParameters.org}.` }) return res.status(403).json(error.alreadyInOrg(org.short_name, userToEditParameters.username)) diff --git a/test/integration-tests/user/updateUserTest.js b/test/integration-tests/user/updateUserTest.js index 34e4f1f18..610438687 100644 --- a/test/integration-tests/user/updateUserTest.js +++ b/test/integration-tests/user/updateUserTest.js @@ -205,5 +205,36 @@ describe('Testing Edit user endpoint', () => { expect(res.body.error).to.equal('SECRET_UPDATE_NOT_ALLOWED') }) }) + it('Should return 404 when target organization in path does not exist', async () => { + const user = constants.headers['CVE-API-USER'] + await chai.request(app) + .put(`/api/registry/org/non_existent_org/user/${user}`) + .set(constants.headers) + .send({ + name: { + first: 'NewFirst', + last: 'NewLast' + } + }) + .then((res) => { + expect(res).to.have.status(404) + expect(res.body.error).to.contain('ORG_DNE_PARAM') + }) + }) + + it('Should return 404 when target organization in body does not exist', async () => { + const user = constants.headers['CVE-API-USER'] + const org = constants.headers['CVE-API-ORG'] + await chai.request(app) + .put(`/api/registry/org/${org}/user/${user}`) + .set(constants.headers) + .send({ + org_short_name: 'non_existent_org' + }) + .then((res) => { + expect(res).to.have.status(404) + expect(res.body.error).to.contain('ORG_DNE_PARAM') + }) + }) }) }) From 36ff32d124bba6f2cfc57f0fea6e77cd20a54993 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Mon, 13 Apr 2026 16:27:35 -0400 Subject: [PATCH 09/11] Updating version numbher --- api-docs/openapi.json | 2 +- package.json | 2 +- src/swagger.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api-docs/openapi.json b/api-docs/openapi.json index f91d19ecf..d96597b1c 100644 --- a/api-docs/openapi.json +++ b/api-docs/openapi.json @@ -1,7 +1,7 @@ { "openapi": "3.0.2", "info": { - "version": "2.7.3", + "version": "2.7.4", "title": "CVE Services API", "description": "The CVE Services API supports automation tooling for the CVE Program. Credentials are required for most service endpoints. Representatives of CVE Numbering Authorities (CNAs) should use one of the methods below to obtain credentials:
  • If your organization already has an Organizational Administrator (OA) account for the CVE Services, ask your admin for credentials
  • Contact your Root (Google, INCIBE, JPCERT/CC, or Red Hat) or Top-Level Root (CISA ICS or MITRE) to request credentials

CVE data is to be in the JSON 5.2 CVE Record format. Details of the JSON 5.2 schema are located here.

Contact the CVE Services team", "contact": { diff --git a/package.json b/package.json index 8bb790cfc..16da323ab 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "cve-services", "author": "Automation Working Group", - "version": "2.7.3", + "version": "2.7.4", "license": "(CC0)", "devDependencies": { "@faker-js/faker": "^7.6.0", diff --git a/src/swagger.js b/src/swagger.js index 8df39f4d7..4fc21c77e 100644 --- a/src/swagger.js +++ b/src/swagger.js @@ -22,7 +22,7 @@ const fullCnaContainerRequest = require('../schemas/cve/create-cve-record-cna-re /* eslint-disable no-multi-str */ const doc = { info: { - version: '2.7.3', + version: '2.7.4', title: 'CVE Services API', description: "The CVE Services API supports automation tooling for the CVE Program. Credentials are \ required for most service endpoints. Representatives of \ From 1d147d5799e6c7f574f386709359aee96eb8c410 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Mon, 13 Apr 2026 16:58:02 -0400 Subject: [PATCH 10/11] Fixing AWS specific issues --- .../registry-user.controller/registry-user.controller.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/controller/registry-user.controller/registry-user.controller.js b/src/controller/registry-user.controller/registry-user.controller.js index bd8d9e234..3133c197e 100644 --- a/src/controller/registry-user.controller/registry-user.controller.js +++ b/src/controller/registry-user.controller/registry-user.controller.js @@ -213,7 +213,7 @@ async function updateUser (req, res, next) { We need to make sure that either way we convert to one or the other. For now, I am going shortname / username */ - const session = await mongoose.startSession() + const session = await mongoose.startSession({ causalConsistency: false }) // Check to see if identifier is set const identifier = req.ctx.params.identifier @@ -315,6 +315,7 @@ async function updateUser (req, res, next) { let result let updatedUser + let updatedUserUUID try { session.startTransaction() try { @@ -349,6 +350,8 @@ async function updateUser (req, res, next) { } } + // UUID of the user will not change, lets get it before we write to avoid read after write issues. + updatedUserUUID = await userRepo.getUserUUID(req.ctx.user, org.UUID) updatedUser = await userRepo.updateUserFull(userToEdit.UUID, body, { session }) await session.commitTransaction() } catch (error) { @@ -363,9 +366,9 @@ async function updateUser (req, res, next) { change: userToEditParameters.username + ' was successfully updated.', req_UUID: req.ctx.uuid, org_UUID: org.UUID, - user: updatedUser + user: updatedUser, + user_UUID: updatedUserUUID } - payload.user_UUID = await userRepo.getUserUUID(req.ctx.user, payload.org_UUID) logger.info(JSON.stringify(payload)) return res.status(200).json( From b55cef87fa4a86d9c1a6c6cb0a0cc98e18b19d54 Mon Sep 17 00:00:00 2001 From: david-rocca Date: Mon, 13 Apr 2026 17:11:00 -0400 Subject: [PATCH 11/11] relocking dev --- src/controller/org.controller/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/org.controller/index.js b/src/controller/org.controller/index.js index 1c5e6f110..f7805c496 100644 --- a/src/controller/org.controller/index.js +++ b/src/controller/org.controller/index.js @@ -640,7 +640,7 @@ router.put('/registry/org/:shortname', */ mw.useRegistry(), mw.validateUser, - // mw.onlySecretariat, + mw.onlySecretariat, parseError, parsePutParams, registryOrgController.UPDATE_ORG