@apolitical/server 4.3.0-pla-471.1 → 4.3.0-pla-471.3
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apolitical/server",
|
|
3
|
-
"version": "4.3.0-pla-471.
|
|
3
|
+
"version": "4.3.0-pla-471.3",
|
|
4
4
|
"description": "Node.js module to encapsulate Apolitical's express server setup",
|
|
5
5
|
"author": "Apolitical Group Limited <engineering@apolitical.co>",
|
|
6
6
|
"license": "MIT",
|
package/src/container.js
CHANGED
|
@@ -56,6 +56,7 @@ const expressService = require('./services/express.service');
|
|
|
56
56
|
const healthService = require('./services/health.service');
|
|
57
57
|
const jwtService = require('./services/jwt.service');
|
|
58
58
|
const serverService = require('./services/server.service');
|
|
59
|
+
const secretManagerService = require('./services/secret-manager.service');
|
|
59
60
|
const secretsService = require('./services/secrets.service');
|
|
60
61
|
|
|
61
62
|
// DI container
|
|
@@ -116,6 +117,7 @@ container.register({
|
|
|
116
117
|
healthService: asFunction(healthService).singleton(),
|
|
117
118
|
jwtService: asFunction(jwtService).singleton(),
|
|
118
119
|
serverService: asFunction(serverService).singleton(),
|
|
120
|
+
secretManagerService: asFunction(secretManagerService).singleton(),
|
|
119
121
|
secretsService: asFunction(secretsService).singleton(),
|
|
120
122
|
});
|
|
121
123
|
|
package/src/index.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { resolve } = require('./container');
|
|
4
|
-
const { SecretManagerService } = require('./services/secret-manager.service');
|
|
5
4
|
|
|
6
5
|
// OTel must load before the Express server is started
|
|
7
6
|
resolve('otelLoader')();
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
serverService.SecretManagerService = SecretManagerService;
|
|
11
|
-
|
|
12
|
-
module.exports = serverService;
|
|
8
|
+
module.exports = resolve('serverService');
|
|
@@ -1,18 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
module.exports = ({ secretManager, logger }) => {
|
|
4
|
+
let clientPromise = null;
|
|
4
5
|
|
|
5
|
-
/**
|
|
6
|
-
* Thin wrapper around Google Cloud Secret Manager.
|
|
7
|
-
*
|
|
8
|
-
* Every method is static because the class is consumed before the DI
|
|
9
|
-
* container is available (e.g. inside config loading at startup).
|
|
10
|
-
* The underlying client is lazily created and reused across all calls.
|
|
11
|
-
*
|
|
12
|
-
* Aligned with the backend/v2 implementation at:
|
|
13
|
-
* backend/v2/libs/externals/gcp/secrets/src/secret-manager.service.ts
|
|
14
|
-
*/
|
|
15
|
-
class SecretManagerService {
|
|
16
6
|
/**
|
|
17
7
|
* Derive the secret name prefix from the PLATFORM_BASE_URL subdomain.
|
|
18
8
|
* - https://apolitical.co → "live"
|
|
@@ -21,7 +11,7 @@ class SecretManagerService {
|
|
|
21
11
|
* - https://localhost → "tilt" (Local Tilt)
|
|
22
12
|
* - http://localhost → "pnpm" (Local standalone)
|
|
23
13
|
*/
|
|
24
|
-
|
|
14
|
+
function getSecretPrefix(useLocal) {
|
|
25
15
|
const baseURL = String(process.env.PLATFORM_BASE_URL ?? '');
|
|
26
16
|
try {
|
|
27
17
|
const hostname = new URL(baseURL).hostname;
|
|
@@ -35,14 +25,14 @@ class SecretManagerService {
|
|
|
35
25
|
return useLocal ? 'pnpm' : 'beta';
|
|
36
26
|
}
|
|
37
27
|
|
|
38
|
-
|
|
39
|
-
if (!
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return new SecretManagerServiceClient();
|
|
28
|
+
function getClient() {
|
|
29
|
+
if (!clientPromise) {
|
|
30
|
+
clientPromise = (async () => {
|
|
31
|
+
logger.info('[SecretManager] Initialising client.');
|
|
32
|
+
return new secretManager.SecretManagerServiceClient();
|
|
43
33
|
})();
|
|
44
34
|
}
|
|
45
|
-
return
|
|
35
|
+
return clientPromise;
|
|
46
36
|
}
|
|
47
37
|
|
|
48
38
|
/**
|
|
@@ -51,11 +41,11 @@ class SecretManagerService {
|
|
|
51
41
|
* The full secret name is built as `{prefix}_{secretBaseName}`, where the
|
|
52
42
|
* prefix is derived from PLATFORM_BASE_URL (e.g. "beta", "live").
|
|
53
43
|
*/
|
|
54
|
-
|
|
55
|
-
const client = await
|
|
44
|
+
async function accessSecret(secretBaseName, options) {
|
|
45
|
+
const client = await getClient();
|
|
56
46
|
const projectId = process.env.GCP_PROJECT_ID ?? (await client.auth.getProjectId());
|
|
57
47
|
|
|
58
|
-
const prefix =
|
|
48
|
+
const prefix = getSecretPrefix(options?.useLocal);
|
|
59
49
|
const secretName = `${prefix}_${secretBaseName}`;
|
|
60
50
|
const version = options?.version ?? 'latest';
|
|
61
51
|
const name = `projects/${projectId}/secrets/${secretName}/versions/${version}`;
|
|
@@ -68,6 +58,9 @@ class SecretManagerService {
|
|
|
68
58
|
|
|
69
59
|
return typeof payload === 'string' ? payload : payload.toString('utf8');
|
|
70
60
|
}
|
|
71
|
-
}
|
|
72
61
|
|
|
73
|
-
|
|
62
|
+
return {
|
|
63
|
+
getSecretPrefix,
|
|
64
|
+
accessSecret,
|
|
65
|
+
};
|
|
66
|
+
};
|
|
@@ -8,6 +8,7 @@ module.exports = ({
|
|
|
8
8
|
jwtService,
|
|
9
9
|
serverError,
|
|
10
10
|
requestHelper,
|
|
11
|
+
secretManagerService,
|
|
11
12
|
secretsService,
|
|
12
13
|
}) => {
|
|
13
14
|
// Register shutdown to clean up any resources used by the express app
|
|
@@ -23,6 +24,7 @@ module.exports = ({
|
|
|
23
24
|
authorisation: authorisationMiddleware,
|
|
24
25
|
},
|
|
25
26
|
request: requestHelper,
|
|
27
|
+
secretManager: secretManagerService,
|
|
26
28
|
secrets: secretsService,
|
|
27
29
|
};
|
|
28
30
|
};
|