Skip to content

Commit fa677fa

Browse files
committed
fix(settings): add getAllAccountsSettings
1 parent 41a85c8 commit fa677fa

File tree

6 files changed

+114
-161
lines changed

6 files changed

+114
-161
lines changed

src/api/test-data/deviceShadow.json

Lines changed: 0 additions & 67 deletions
This file was deleted.

src/settings/getAllAccountSettings.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { SSMClient } from '@aws-sdk/client-ssm'
2+
import { get } from '@bifravst/aws-ssm-settings-helpers'
3+
import { getAccountsFromAllSettings } from './getAllAccounts.js'
4+
import { validateSettings, type Settings } from './settings.js'
5+
import { NRFCLOUD_ACCOUNT_SCOPE } from './scope.js'
6+
7+
/**
8+
* Returns settings for all accounts
9+
*/
10+
export const getAllAccountSettings = async ({
11+
ssm,
12+
stackName,
13+
}: {
14+
ssm: SSMClient
15+
stackName: string
16+
}): Promise<Record<string, Settings>> => {
17+
const allSettings = await get(ssm)({
18+
stackName,
19+
scope: NRFCLOUD_ACCOUNT_SCOPE,
20+
})()
21+
22+
const accounts = getAccountsFromAllSettings(allSettings)
23+
24+
return [...accounts].reduce(
25+
(allAccountSettings, account) => ({
26+
...allAccountSettings,
27+
[account]: validateSettings(
28+
Object.entries(allSettings)
29+
.filter(([k]) => k.startsWith(`${account}/`))
30+
.map<[string, string]>(([k, v]) => [
31+
k.replace(new RegExp(`^${account}/`), ''),
32+
v,
33+
])
34+
.reduce((s, [k, v]) => ({ ...s, [k]: v }), {}),
35+
),
36+
}),
37+
{},
38+
)
39+
}
40+
41+
console.log(
42+
await getAllAccountSettings({
43+
ssm: new SSMClient(),
44+
stackName: 'hello-nrfcloud-backend',
45+
}),
46+
)

src/settings/getAllAccounts.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { SSMClient } from '@aws-sdk/client-ssm'
2-
import { Scopes } from './scope.js'
32
import { get } from '@bifravst/aws-ssm-settings-helpers'
3+
import { NRFCLOUD_ACCOUNT_SCOPE } from './scope.js'
44

55
export const getAllAccounts = async ({
66
ssm,
@@ -9,12 +9,15 @@ export const getAllAccounts = async ({
99
ssm: SSMClient
1010
stackName: string
1111
}): Promise<string[]> => [
12-
...new Set(
13-
Object.keys(
14-
await get(ssm)({
15-
stackName,
16-
scope: Scopes.NRFCLOUD_ACCOUNT_PREFIX,
17-
})(),
18-
).map((key) => key.split('/')[0] as string),
12+
...getAccountsFromAllSettings(
13+
await get(ssm)({
14+
stackName,
15+
scope: NRFCLOUD_ACCOUNT_SCOPE,
16+
})(),
1917
),
2018
]
19+
20+
export const getAccountsFromAllSettings = (
21+
settings: Record<string, string>,
22+
): Set<string> =>
23+
new Set(Object.keys(settings).map((key) => key.split('/')[0] as string))

src/settings/initializeAccount.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { SSMClient } from '@aws-sdk/client-ssm'
22
import chalk from 'chalk'
3-
import { nrfCloudAccount } from './scope.js'
3+
import { NRFCLOUD_ACCOUNT_SCOPE, nrfCloudAccount } from './scope.js'
44
import { get } from '@bifravst/aws-ssm-settings-helpers'
55
import { createAccountDevice } from '../api/createAccountDevice.js'
66
import { deleteAccountDevice } from '../api/deleteAccountDevice.js'
@@ -30,7 +30,8 @@ export const initializeAccount =
3030
async (reset = false): Promise<void> => {
3131
const settingsReader = get(ssm)({
3232
stackName,
33-
...nrfCloudAccount(account),
33+
scope: NRFCLOUD_ACCOUNT_SCOPE,
34+
context: nrfCloudAccount(account),
3435
})
3536

3637
const { apiKey, apiEndpoint } = await settingsReader()

src/settings/scope.ts

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,7 @@
1-
export enum Scopes {
2-
STACK = 'stack',
3-
NRFCLOUD_BRIDGE_CERTIFICATE = 'nRFCloudBridgeCertificate',
4-
NRFCLOUD_ACCOUNT_PREFIX = 'thirdParty',
5-
}
6-
7-
export type ScopeContext = {
8-
scope: string
9-
context: string
10-
}
11-
12-
export const ScopeContexts = {
13-
STACK_CONFIG: <ScopeContext>{ scope: Scopes.STACK, context: 'context' },
14-
STACK_MQTT_BRIDGE: <ScopeContext>{
15-
scope: Scopes.STACK,
16-
context: 'mqttBridge',
17-
},
18-
STACK_COAP_HEALTH_CHECK: <ScopeContext>{
19-
scope: Scopes.STACK,
20-
context: 'coap-health-check',
21-
},
22-
NRFCLOUD_BRIDGE_CERTIFICATE_MQTT: <ScopeContext>{
23-
scope: Scopes.NRFCLOUD_BRIDGE_CERTIFICATE,
24-
context: 'MQTT',
25-
},
26-
NRFCLOUD_BRIDGE_CERTIFICATE_CA: <ScopeContext>{
27-
scope: Scopes.NRFCLOUD_BRIDGE_CERTIFICATE,
28-
context: 'CA',
29-
},
30-
} as const
31-
1+
export const NRFCLOUD_ACCOUNT_SCOPE = 'thirdParty'
322
const nameRx = /^[a-zA-Z0-9_.-]+$/
333

34-
export const nrfCloudAccount = (account: string): ScopeContext => {
4+
export const nrfCloudAccount = (account: string): string => {
355
if (!nameRx.test(account)) throw new Error(`Invalid account name: ${account}`)
36-
return {
37-
scope: Scopes.NRFCLOUD_ACCOUNT_PREFIX,
38-
context: account,
39-
}
6+
return account
407
}

src/settings/settings.ts

Lines changed: 51 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { SSMClient } from '@aws-sdk/client-ssm'
2-
import { nrfCloudAccount } from './scope.js'
2+
import { NRFCLOUD_ACCOUNT_SCOPE, nrfCloudAccount } from './scope.js'
33
import {
44
get as getSSMSettings,
55
put as putSSMSettings,
@@ -32,50 +32,10 @@ export const getSettings = ({
3232
}): (() => Promise<Settings>) => {
3333
const settingsReader = getSSMSettings(ssm)({
3434
stackName,
35-
...nrfCloudAccount(account),
35+
scope: NRFCLOUD_ACCOUNT_SCOPE,
36+
context: nrfCloudAccount(account),
3637
})
37-
return async (): Promise<Settings> => {
38-
const p = await settingsReader()
39-
const {
40-
apiEndpoint,
41-
apiKey,
42-
accountDeviceClientCert,
43-
accountDevicePrivateKey,
44-
mqttEndpoint,
45-
accountDeviceClientId,
46-
mqttTopicPrefix,
47-
coapEndpoint,
48-
coapPort,
49-
} = p
50-
if (apiKey === undefined)
51-
throw new Error(`No nRF Cloud API key configured!`)
52-
if (accountDeviceClientCert === undefined)
53-
throw new Error(`No nRF Cloud account device clientCert configured!`)
54-
if (accountDevicePrivateKey === undefined)
55-
throw new Error(`No nRF Cloud account device privateKey configured!`)
56-
if (accountDeviceClientId === undefined)
57-
throw new Error(`No nRF Cloud Account Device client ID configured!`)
58-
if (mqttTopicPrefix === undefined)
59-
throw new Error(`No nRF Cloud MQTT topic prefix configured!`)
60-
if (mqttEndpoint === undefined)
61-
throw new Error(`No nRF Cloud MQTT endpoint configured!`)
62-
63-
return {
64-
apiEndpoint:
65-
apiEndpoint === undefined ? defaultApiEndpoint : new URL(apiEndpoint),
66-
apiKey,
67-
mqttEndpoint,
68-
accountDeviceClientCert,
69-
accountDevicePrivateKey,
70-
accountDeviceClientId,
71-
mqttTopicPrefix,
72-
coapEndpoint:
73-
coapEndpoint === undefined
74-
? defaultCoAPEndpoint
75-
: new URL(coapEndpoint),
76-
coapPort: parseInt(coapPort ?? `5684`, 10),
77-
}
78-
}
38+
return async (): Promise<Settings> => validateSettings(await settingsReader())
7939
}
8040

8141
export const getAPISettings = ({
@@ -89,7 +49,8 @@ export const getAPISettings = ({
8949
}): (() => Promise<Pick<Settings, 'apiKey' | 'apiEndpoint'>>) => {
9050
const settingsReader = getSSMSettings(ssm)({
9151
stackName,
92-
...nrfCloudAccount(account),
52+
scope: NRFCLOUD_ACCOUNT_SCOPE,
53+
context: nrfCloudAccount(account),
9354
})
9455
return async (): Promise<Pick<Settings, 'apiKey' | 'apiEndpoint'>> => {
9556
const p = await settingsReader()
@@ -116,7 +77,8 @@ export const putSettings = ({
11677
}): ((settings: Partial<Settings>) => Promise<void>) => {
11778
const settingsWriter = putSSMSettings(ssm)({
11879
stackName,
119-
...nrfCloudAccount(account),
80+
scope: NRFCLOUD_ACCOUNT_SCOPE,
81+
context: nrfCloudAccount(account),
12082
})
12183
return async (settings): Promise<void> => {
12284
await Promise.all(
@@ -145,7 +107,8 @@ export const putSetting = ({
145107
) => ReturnType<typeof settingsWriter>) => {
146108
const settingsWriter = putSSMSettings(ssm)({
147109
stackName,
148-
...nrfCloudAccount(account),
110+
scope: NRFCLOUD_ACCOUNT_SCOPE,
111+
context: nrfCloudAccount(account),
149112
})
150113
return async (property, value, deleteBeforeUpdate) =>
151114
settingsWriter({
@@ -166,7 +129,47 @@ export const deleteSettings = ({
166129
}): ((property: string) => ReturnType<typeof settingsDeleter>) => {
167130
const settingsDeleter = deleteSSMSettings(ssm)({
168131
stackName,
169-
...nrfCloudAccount(account),
132+
scope: NRFCLOUD_ACCOUNT_SCOPE,
133+
context: nrfCloudAccount(account),
170134
})
171135
return async (property) => settingsDeleter({ property })
172136
}
137+
138+
export const validateSettings = (p: Record<string, string>): Settings => {
139+
const {
140+
apiEndpoint,
141+
apiKey,
142+
accountDeviceClientCert,
143+
accountDevicePrivateKey,
144+
mqttEndpoint,
145+
accountDeviceClientId,
146+
mqttTopicPrefix,
147+
coapEndpoint,
148+
coapPort,
149+
} = p
150+
if (apiKey === undefined) throw new Error(`No nRF Cloud API key configured!`)
151+
if (accountDeviceClientCert === undefined)
152+
throw new Error(`No nRF Cloud account device clientCert configured!`)
153+
if (accountDevicePrivateKey === undefined)
154+
throw new Error(`No nRF Cloud account device privateKey configured!`)
155+
if (accountDeviceClientId === undefined)
156+
throw new Error(`No nRF Cloud Account Device client ID configured!`)
157+
if (mqttTopicPrefix === undefined)
158+
throw new Error(`No nRF Cloud MQTT topic prefix configured!`)
159+
if (mqttEndpoint === undefined)
160+
throw new Error(`No nRF Cloud MQTT endpoint configured!`)
161+
162+
return {
163+
apiEndpoint:
164+
apiEndpoint === undefined ? defaultApiEndpoint : new URL(apiEndpoint),
165+
apiKey,
166+
mqttEndpoint,
167+
accountDeviceClientCert,
168+
accountDevicePrivateKey,
169+
accountDeviceClientId,
170+
mqttTopicPrefix,
171+
coapEndpoint:
172+
coapEndpoint === undefined ? defaultCoAPEndpoint : new URL(coapEndpoint),
173+
coapPort: parseInt(coapPort ?? `5684`, 10),
174+
}
175+
}

0 commit comments

Comments
 (0)