Skip to content

Commit d696960

Browse files
authored
Merge pull request #1991 from CVEProject/jd_remove_phone
Add database migrations, remove public org phones, and introduce disabled flag
2 parents 0a27c07 + 605c2a0 commit d696960

38 files changed

Lines changed: 772 additions & 235 deletions

README.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,30 @@ Download MongoDB Compass (MongoDB GUI)
8989

9090
- https://www.mongodb.com/download-center/compass
9191

92-
Create a `cve_dev` database in Compass. The collections will be automatically created when the API starts storing documents.
92+
Create a `cve_dev` database in Compass.
9393

94-
You can populate the database with test data using:
94+
You can reset the local development database, run pending database migrations, and populate Cve, Cve-Id-Range, Cve-Id, Org, BaseOrg, User, BaseUser, and Glossary seed data using:
9595

9696
```sh
9797
npm run populate:dev
9898
```
9999

100+
To populate without automatically applying versioned migrations, use the following command, then run the migrations manually when ready:
101+
102+
```sh
103+
npm run populate:dev -- --skip-migrations
104+
npm run db:migrate:dev
105+
```
106+
107+
If the database only needs versioned data migrations without a local data reset, check the migration status and then apply pending migrations:
108+
109+
```sh
110+
npm run db:migrate:status
111+
npm run db:migrate:dev
112+
```
113+
114+
Migrations are managed by `migrate-mongo` using `migrate-mongo-config.js`. The applied migration records are stored in the `migrations_changelog` collection. Existing `migrate:*` scripts are legacy data sync scripts and are separate from these versioned database migrations.
115+
100116
3. Start the node application
101117

102118
In order to start a dev environment:

api-docs/openapi.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3906,7 +3906,7 @@
39063906
"Registry Organization"
39073907
],
39083908
"summary": "Updates information about the organization specified by short name (accessible to Secretariat or same-organization Admin)",
3909-
"description": " <h2>Access Control</h2> <p>User must belong to an organization with the <b>Secretariat</b> role or be an <b>Admin</b> of the requested organization.</p> <p>With Joint Approval required for the following fields:</p> <h2>Expected Behavior</h2> <b>This endpoint expects a full organization object in the request body.</b> <p><b>Secretariat:</b> Updates any organization's information</p> <p><b>Organization Admin:</b> Requests changes to its organization's information</p> <ul> <li>short_name</li> <li>long_name</li> <li>authority</li> <li>aliases</li> <li>oversees</li> <li>top_level_root</li> <li>charter_or_scope</li> <li>product_list</li> <li>disclosure_policy</li> <li>contact_info.websites</li> <li>contact_info.emails</li> <li>contact_info.phone</li> <li>partner_role_type</li> <li>partner_country</li> <li>advisory_locations</li> <li>advisory_location_require_credentials</li> <li>vulnerability_advisory_location_for_web_scraping</li> <li>industry</li> <li>tl_root_start_date</li> <li>is_cna_discussion_list</li> </ul>",
3909+
"description": " <h2>Access Control</h2> <p>User must belong to an organization with the <b>Secretariat</b> role or be an <b>Admin</b> of the requested organization.</p> <p>With Joint Approval required for the following fields:</p> <h2>Expected Behavior</h2> <b>This endpoint expects a full organization object in the request body.</b> <p><b>Secretariat:</b> Updates any organization's information</p> <p><b>Organization Admin:</b> Requests changes to its organization's information</p> <ul> <li>short_name</li> <li>long_name</li> <li>authority</li> <li>aliases</li> <li>oversees</li> <li>top_level_root</li> <li>is_top_level_root</li> <li>is_last_resort</li> <li>charter_or_scope</li> <li>product_list</li> <li>disclosure_policy</li> <li>contact_info.websites</li> <li>contact_info.emails</li> <li>partner_role_type</li> <li>partner_country</li> <li>advisory_locations</li> <li>advisory_location_require_credentials</li> <li>vulnerability_advisory_location_for_web_scraping</li> <li>industry</li> <li>tl_root_start_date</li> <li>is_cna_discussion_list</li> </ul>",
39103910
"operationId": "registryOrgUpdateSingle",
39113911
"parameters": [
39123912
{
@@ -8193,4 +8193,4 @@
81938193
}
81948194
}
81958195
}
8196-
}
8196+
}

datadump/pre-population/orgs.json

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -323,11 +323,6 @@
323323
}
324324
},
325325
{
326-
"authority": {
327-
"active_roles": [
328-
"CNA"
329-
]
330-
},
331326
"name": "Chase, May and Jones",
332327
"short_name": "sister_20",
333328
"time": {
@@ -338,4 +333,4 @@
338333
"id_quota": 1408
339334
}
340335
}
341-
]
336+
]

docker/README.md

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -76,34 +76,34 @@ If you do not require special configuration to access the internet, you can safe
7676

7777
### Pre-load Data
7878

79-
Populate mongoDB with test data included in `datadump/pre-population/`
79+
Populate MongoDB with local development seed data included in `datadump/pre-population/`. This resets the local development database, runs pending database migrations, and populates Cve, Cve-Id-Range, Cve-Id, Org, BaseOrg, User, BaseUser, and Glossary.
8080

81-
Run the command below using `populate:dev` or `populate:int` depending on your environment:
81+
Run the command below for development environments:
8282
```
83-
docker-compose exec cveawg npm run populate:int
83+
docker-compose exec cveawg npm run populate:dev
8484
```
8585

8686
You should see the following:
8787
```
8888
> cve-services@0.0.3 populate:dev /app
8989
> NODE_ENV=development node-dev src/scripts/populate.js
9090
91-
2022-06-07 19:58:32 [info]: "Using NODE_ENV 'development' and app environment 'development'"
92-
2022-06-07 19:58:32 [info]: "Using dbName = cve_dev"
93-
2022-06-07 19:58:32 [info]: "Will try to connect to database cve_dev at docdb:27017"
9491
2022-06-07 19:58:32 [info]: "Successfully connected to database!"
95-
Are you sure you wish to pre-populate the database for the development environment? Doing so will drop the Cve, Cve-Id-Range, Cve-Id, User, Org collection(s) in the cve_dev database. (y/n) y
92+
Are you sure you wish to pre-populate the database for the development environment? Doing so will drop and rebuild the database, populate the Org, BaseOrg, User, BaseUser, Glossary collection(s), and run migrations in the cve_dev database. (y/n) y
9693
94+
2022-06-07 19:58:37 [info]: "Dropping cve_dev database before population..."
95+
2022-06-07 19:58:37 [info]: "Successfully dropped cve_dev database."
9796
2022-06-07 19:58:37 [info]: "Populating Org collection..."
9897
2022-06-07 19:58:37 [info]: "Org populated!"
9998
2022-06-07 19:58:37 [info]: "Populating User collection..."
10099
2022-06-07 19:58:38 [info]: "User populated!"
101-
2022-06-07 19:58:38 [info]: "Populating Cve-Id-Range collection..."
102-
2022-06-07 19:58:38 [info]: "Populating Cve collection..."
103-
2022-06-07 19:58:38 [info]: "Populating Cve-Id collection..."
104-
2022-06-07 19:58:38 [info]: "Cve-Id-Range populated!"
105-
2022-06-07 19:58:38 [info]: "Cve populated!"
106-
2022-06-07 19:58:39 [info]: "Cve-Id populated!"
100+
2022-06-07 19:58:38 [info]: "Populating BaseOrg collection..."
101+
2022-06-07 19:58:38 [info]: "BaseOrg populated!"
102+
2022-06-07 19:58:38 [info]: "Populating BaseUser collection..."
103+
2022-06-07 19:58:38 [info]: "BaseUser populated!"
104+
2022-06-07 19:58:38 [info]: "Populating Glossary collection..."
105+
2022-06-07 19:58:39 [info]: "Glossary populated!"
106+
2022-06-07 19:58:39 [info]: "Successfully ran database migrations."
107107
2022-06-07 19:58:39 [info]: "Successfully populated the database!"
108108
109109
```
@@ -112,14 +112,6 @@ Are you sure you wish to pre-populate the database for the development environme
112112

113113
The API token key is generated or stored differently depending on the value of the `NODE_ENV` environment variable.
114114

115-
#### Integration
116-
117-
For `integration` Node environments, the API key will be generate and saved to the `user-secret.txt` file when the database is populated.
118-
119-
Display the key with:
120-
121-
`docker-compose exec cveawg grep admin2 user-secret.txt`
122-
123115
#### Development
124116

125117
In `development` environments, the API is the value of the `LOCAL_KEY` variable in the `.docker-env` file.
@@ -189,7 +181,7 @@ docker compose -f docker-compose.mongo-cluster.yml up -d docdb docdb-read-1 docd
189181
Use this connection string from the host, including MongoDB Compass:
190182

191183
```text
192-
mongodb://localhost:27017,localhost:27018,localhost:27019/cve_test?replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false
184+
mongodb://127.0.0.1:27017,127.0.0.1:27018,127.0.0.1:27019/cve_test?replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false
193185
```
194186

195187
To run the same local replica topology with Mongo 8, override the image:
@@ -199,6 +191,8 @@ cd docker/
199191
MONGO_IMAGE=mongo:8.0 docker compose -f docker-compose.mongo-cluster.yml up -d --force-recreate docdb docdb-read-1 docdb-read-2 mongo-init
200192
```
201193

194+
The Mongo-only compose file overrides `GLIBC_TUNABLES` for compatibility with Docker Desktop Linux kernels 6.19 through 7.0.13. MongoDB's default TCMalloc configuration refuses to start on those kernel versions. The override can be removed after all development environments use kernel 7.0.14 or newer.
195+
202196
If you already created the local volumes with Mongo 5, Mongo 8 may fail to start against those files. For a fresh Mongo 8 local cluster, remove the Mongo-only volumes first. This deletes local Mongo data for this compose file:
203197

204198
```bash

docker/docker-compose.mongo-cluster.yml

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@ services:
22
docdb:
33
image: ${MONGO_IMAGE:-mongo:5.0}
44
container_name: mongo
5+
environment:
6+
# MongoDB's default rseq setting is incompatible with Docker kernels 6.19 through 7.0.13.
7+
GLIBC_TUNABLES: glibc.pthread.rseq=1
58
ports:
6-
- "27017:27017"
7-
- "27018:27018"
8-
- "27019:27019"
9+
- "127.0.0.1:27017:27017"
10+
- "127.0.0.1:27018:27018"
11+
- "127.0.0.1:27019:27019"
912
volumes:
1013
- docdb-host-data:/data/db
1114
command: ["mongod", "--replSet", "rs0", "--bind_ip_all", "--port", "27017"]
1215
healthcheck:
13-
test: ["CMD-SHELL", "mongosh --quiet --port 27017 --eval 'db.adminCommand({ ping: 1 }).ok' || exit 1"]
16+
test: ["CMD-SHELL", "mongosh --quiet --host 127.0.0.1 --port 27017 --eval 'db.adminCommand({ ping: 1 }).ok' || exit 1"]
1417
interval: 10s
1518
timeout: 10s
1619
retries: 12
@@ -19,6 +22,8 @@ services:
1922
docdb-read-1:
2023
image: ${MONGO_IMAGE:-mongo:5.0}
2124
container_name: mongo-read-1
25+
environment:
26+
GLIBC_TUNABLES: glibc.pthread.rseq=1
2227
network_mode: "service:docdb"
2328
depends_on:
2429
docdb:
@@ -27,7 +32,7 @@ services:
2732
- docdb-host-read-1-data:/data/db
2833
command: ["mongod", "--replSet", "rs0", "--bind_ip_all", "--port", "27018"]
2934
healthcheck:
30-
test: ["CMD-SHELL", "mongosh --quiet --port 27018 --eval 'db.adminCommand({ ping: 1 }).ok' || exit 1"]
35+
test: ["CMD-SHELL", "mongosh --quiet --host 127.0.0.1 --port 27018 --eval 'db.adminCommand({ ping: 1 }).ok' || exit 1"]
3136
interval: 10s
3237
timeout: 10s
3338
retries: 12
@@ -36,6 +41,8 @@ services:
3641
docdb-read-2:
3742
image: ${MONGO_IMAGE:-mongo:5.0}
3843
container_name: mongo-read-2
44+
environment:
45+
GLIBC_TUNABLES: glibc.pthread.rseq=1
3946
network_mode: "service:docdb"
4047
depends_on:
4148
docdb:
@@ -44,7 +51,7 @@ services:
4451
- docdb-host-read-2-data:/data/db
4552
command: ["mongod", "--replSet", "rs0", "--bind_ip_all", "--port", "27019"]
4653
healthcheck:
47-
test: ["CMD-SHELL", "mongosh --quiet --port 27019 --eval 'db.adminCommand({ ping: 1 }).ok' || exit 1"]
54+
test: ["CMD-SHELL", "mongosh --quiet --host 127.0.0.1 --port 27019 --eval 'db.adminCommand({ ping: 1 }).ok' || exit 1"]
4855
interval: 10s
4956
timeout: 10s
5057
retries: 12
@@ -62,13 +69,13 @@ services:
6269
condition: service_healthy
6370
command: >
6471
sh -c "
65-
mongosh --host localhost --port 27017 --eval '
72+
mongosh --host 127.0.0.1 --port 27017 --eval '
6673
const desiredConfig = {
6774
_id: \"rs0\",
6875
members: [
69-
{ _id: 0, host: \"localhost:27017\", priority: 2 },
70-
{ _id: 1, host: \"localhost:27018\", priority: 1 },
71-
{ _id: 2, host: \"localhost:27019\", priority: 1 }
76+
{ _id: 0, host: \"127.0.0.1:27017\", priority: 2 },
77+
{ _id: 1, host: \"127.0.0.1:27018\", priority: 1 },
78+
{ _id: 2, host: \"127.0.0.1:27019\", priority: 1 }
7279
]
7380
};
7481
@@ -86,7 +93,7 @@ services:
8693
rs.status();
8794
const currentConfig = rs.conf();
8895
if (configMatches(currentConfig)) {
89-
print(\"Replica set already initialized with the expected localhost members.\");
96+
print(\"Replica set already initialized with the expected IPv4 members.\");
9097
} else {
9198
print(\"Updating replica set members...\");
9299
rs.reconfig({ ...desiredConfig, version: currentConfig.version + 1 });

migrate-mongo-config.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
require('dotenv').config()
2+
3+
const config = require('config')
4+
5+
const appEnv = process.env.NODE_ENV || 'development'
6+
7+
function getConfiguredValue (key) {
8+
const configPath = `${appEnv}.${key}`
9+
return config.has(configPath) ? config.get(configPath) : null
10+
}
11+
12+
function getMongoConnectionString () {
13+
if (process.env.MONGO_CONN_STRING) {
14+
return process.env.MONGO_CONN_STRING
15+
}
16+
17+
const dbUser = process.env.MONGO_USER || getConfiguredValue('username')
18+
const dbPassword = process.env.MONGO_PASSWORD || getConfiguredValue('password')
19+
const dbHost = process.env.MONGO_HOST || getConfiguredValue('host')
20+
const dbPort = process.env.MONGO_PORT || getConfiguredValue('port')
21+
const dbName = getMongoDatabaseName()
22+
const dbLoginPrepend = dbUser && dbPassword ? `${dbUser}:${dbPassword}@` : ''
23+
24+
if (process.env.useAWS) {
25+
return `mongodb://${dbLoginPrepend}${dbHost}:${dbPort}/${dbName}?replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false`
26+
}
27+
28+
return `mongodb://${dbLoginPrepend}${dbHost}:${dbPort}/${dbName}`
29+
}
30+
31+
function getDatabaseNameFromUri () {
32+
if (!process.env.MONGO_CONN_STRING) {
33+
return null
34+
}
35+
36+
try {
37+
const uri = new URL(process.env.MONGO_CONN_STRING)
38+
const databaseName = uri.pathname.replace(/^\//, '')
39+
return databaseName || null
40+
} catch (err) {
41+
return null
42+
}
43+
}
44+
45+
function getMongoDatabaseName () {
46+
return process.env.MONGO_DB_NAME || getDatabaseNameFromUri() || getConfiguredValue('database')
47+
}
48+
49+
function getMongoConnectionOptions () {
50+
if (process.env.useAWS) {
51+
return {
52+
authMechanism: 'SCRAM-SHA-1',
53+
tls: false
54+
}
55+
}
56+
57+
return {
58+
tls: false
59+
}
60+
}
61+
62+
const migrationConfig = {
63+
mongodb: {
64+
url: getMongoConnectionString(),
65+
databaseName: getMongoDatabaseName(),
66+
options: getMongoConnectionOptions()
67+
},
68+
migrationsDir: 'migrations',
69+
changelogCollectionName: 'migrations_changelog',
70+
lockCollectionName: 'migrations_changelog_lock',
71+
lockTtl: 0,
72+
migrationFileExtension: '.js',
73+
useFileHash: false,
74+
moduleSystem: 'commonjs'
75+
}
76+
77+
module.exports = migrationConfig

0 commit comments

Comments
 (0)