Skip to content

Commit 82dcf5c

Browse files
author
Maurice Faber
committed
chore(release): 0.4.54
2 parents 9f2b909 + 195b94d commit 82dcf5c

File tree

15 files changed

+455
-350
lines changed

15 files changed

+455
-350
lines changed

.vscode/launch.json

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,26 @@
22
"version": "0.2.0",
33
"configurations": [
44
{
5-
"type": "node",
6-
"request": "attach",
7-
"name": "Attach to current script",
8-
"protocol": "inspector",
9-
"port": 4321,
10-
"restart": true,
11-
"cwd": "${workspaceRoot}"
12-
},
13-
{
14-
"type": "node",
5+
"name": "Debug src/app.ts",
6+
"type": "pwa-node",
157
"request": "launch",
16-
"name": "Debug npm run dev",
17-
"runtimeExecutable": "npm",
18-
"runtimeArgs": ["run-script", "dev"],
8+
"runtimeExecutable": "node",
9+
"runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
10+
"args": ["src/app.ts"],
1911
"cwd": "${workspaceRoot}",
20-
21-
"console": "integratedTerminal"
12+
"internalConsoleOptions": "openOnSessionStart",
13+
"skipFiles": ["<node_internals>/**", "node_modules/**"],
14+
"env": {
15+
"NODE_ENV": "test"
16+
},
17+
"resolveSourceMapLocations": ["!${workspaceFolder}/**"]
2218
},
2319
{
2420
"type": "node",
2521
"request": "launch",
26-
"name": "Debug npm run dev:no-authz",
22+
"name": "Debug npm run dev",
2723
"runtimeExecutable": "npm",
28-
"runtimeArgs": ["run-script", "dev:no-authz"],
24+
"runtimeArgs": ["run-script", "dev"],
2925
"cwd": "${workspaceRoot}",
3026

3127
"console": "integratedTerminal"
@@ -41,8 +37,7 @@
4137
},
4238
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/ts-mocha",
4339
"console": "integratedTerminal",
44-
"internalConsoleOptions": "neverOpen",
45-
"protocol": "inspector"
40+
"internalConsoleOptions": "neverOpen"
4641
},
4742
{
4843
"type": "node",

README.md

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ method.
9999
For the api client there is an `operationId` property defined. It can be used to client with expected method names (see
100100
relevant usage in otomi-web repo)
101101

102-
### 1.2 Authentication
102+
### 2.2 Authentication
103103

104104
The authentication ensures that a user is identified, so the request contains required headers.
105105

@@ -193,6 +193,80 @@ The `TeamSelfService` schema is composed by:
193193
- property that corresponds to a schema name from `api.yaml` file.
194194
- `enum` property that indicates JSON paths for attributes that shall be controlled.
195195

196+
**Note:**
197+
198+
- `delete` permission cannot be set for ABAC
199+
200+
For example:
201+
202+
```
203+
Service:
204+
x-acl:
205+
admin: [delete-any, read-any, create-any, update-any]
206+
team: [delete, read, create, update]
207+
type: object
208+
properties:
209+
name:
210+
type: string
211+
ingress:
212+
type: object
213+
x-acl:
214+
admin: [read, create]
215+
team: [read]
216+
```
217+
218+
From above:
219+
220+
A user with admin role can:
221+
222+
- perform all CRUD operations regardless resource ownership (RBAC)
223+
- all attributes can be edited except ingress that can be only set on resource creation event (ABAC)
224+
225+
A user with team role can:
226+
227+
- perform all CRUD operations only withing its own team (RBAC)
228+
- all attributes can be edited except ingress that isn be only read (ABAC)
229+
230+
#### 2.3.3 Limitations
231+
232+
##### 2.3.3.1 OpenAPI-generator limitations
233+
234+
<!-- Add more issues if you spot them and know the limitations/work-arounds -->
235+
236+
Known issues:
237+
238+
- https://github.com/redkubes/otomi-api/issues/155
239+
240+
###### Problem
241+
242+
It doesn't matter if you've entered a valid OpenAPI specification, it isn't useful as long as it isn't generated as a client library.
243+
244+
###### Cause
245+
246+
There are too many variations of this problem to be listed here and still make sense, but they follow the following cycle in general:
247+
248+
1. `src/openapi/\*.yaml` cannot be dereferenced/bundled by parsing JSON `$refs`.
249+
2. Dereferenced/bundled OpenAPI spec cannot be generated
250+
3. Client libary in `vendors/client/otomi-api/axios/...` cannot be compiled with `tsc`
251+
4. Code cannot be committed in version control (Git)
252+
5. Consume API methods and/or models
253+
254+
###### Solutions
255+
256+
In this paragraph the causes are addressed by the corresponding number under "Cause":
257+
258+
1. In the `npm run ...` scripts, `vendors/openapi/otomi-api.json` may be deleted to see if the spec can be successfully dereferenced/bundled and used as input for `openapi-generator`.
259+
2. The `openapi-generator` can throw useful/meaningful errors. But there are errors under known issues (see above) that need a work-around.
260+
3. These errors happen the most arbitrarily. See if you can go back in your small increments in `src/openapi/...` until you can successfully build the client library again.
261+
4. These errors are often due to our own code. E.g.: a generated model is used, and by changing the OpenAPI spec you change the schema. Models used to rely on the schema and now they are missing.
262+
5. If you change the name of a schema, add a title, etc., the respective reference might change. Then the consumption in the API library might break.
263+
264+
###### Note
265+
266+
- Also check if you can successfully generate the client library again after committing, just as a pre-caution.
267+
- To determine a successful generation of the client library, please check out the generated models in `vendors/client/otomi-api/axios/models` if they make sense or not.
268+
- As general advice, make sure to increment the specification VERY slowly and always see if a spec can be generated or not.
269+
196270
## 2. Viewing/consuming openapi spec
197271

198272
In order to inspect the api file it is recommended to either:

bin/generate-client.sh

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,18 @@ validate() {
2626
fi
2727
}
2828

29+
clean_up() {
30+
if [ -f vendors/openapi/otomi-api.json ]; then
31+
rm vendors/openapi/otomi-api.json
32+
fi
33+
rm -rf vendors/client/otomi-api >/dev/null
34+
}
35+
2936
generate_client() {
30-
echo "Generating client code from openapi specification $openapi_doc.."
31-
rm -rf $target_dir >/dev/null
37+
echo "Generating client code from openapi specification $openapi_doc..."
3238

3339
# npx openapi bundle --output src/openapi --ext yaml src/openapi/api.yaml
40+
npm run build:spec
3441

3542
docker run --rm -v $PWD:/local -w /local -u "$(id -u $USER)" \
3643
openapitools/openapi-generator-cli:v5.1.0 generate \
@@ -42,7 +49,7 @@ generate_client() {
4249
}
4350

4451
set_package_json() {
45-
echo "Updating $target_package_json file.."
52+
echo "Updating $target_package_json file..."
4653

4754
jq \
4855
--arg type 'git' \
@@ -68,17 +75,16 @@ set_bluebird() {
6875
}
6976

7077
build_npm_package() {
71-
echo "Building $target_npm_name npm package"
72-
cd $target_dir
78+
cd $target_dir && echo "Building $target_npm_name npm package..."
7379
npm install && npm run build
7480
cd -
7581
}
7682

77-
rm -rf $target_dir >/dev/null
7883
validate
84+
clean_up
7985
generate_client
8086
set_package_json
8187
set_bluebird
8288
build_npm_package
8389

84-
echo "The client code has been generated at $target_dir/ directory"
90+
echo "The client code has been generated at $target_dir/ directory."

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,15 @@
133133
"build": "tsc && copyup --error src/openapi/*.yaml src/*.json dist/src",
134134
"build:models": "npm run build:spec && openapi-typescript src/generated-schema.json -o src/generated-schema.ts",
135135
"build:spec": "ts-node-dev src/build-spec.ts",
136-
"build:client": "npm run build:spec && rm -rf vendors/client/otomi-api >/dev/null && bin/generate-client.sh",
136+
"build:client": "bin/generate-client.sh",
137+
"build:pre-commit": "npm run build:models && bin/generate-client.sh",
137138
"cz": "git-cz",
138139
"cz:retry": "git-cz --retry",
139140
"dev:watch": "run-p dev watch:openapi watch:ts",
140141
"dev": "ts-node-dev --watch 'src/openapi/*.yaml' --inspect=4321 --respawn --transpile-only src/app.ts",
141142
"dev:docker": "npm install && npm run dev",
142143
"husky:lint-staged": "lint-staged",
143-
"husky:pre-commit": "run-p lint husky:lint-staged build:models",
144+
"husky:pre-commit": "npm run build:pre-commit && npm run lint && npm run husky:lint-staged",
144145
"lint": "run-p types lint:es",
145146
"lint:es": "eslint --ext ts .",
146147
"lint:fix": "eslint --ext ts --fix .",

src/api.authz.test.ts

Lines changed: 69 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,76 @@ describe('Admin API tests', () => {
1616
sinon.stub(otomiStack)
1717
app = await initApp(otomiStack)
1818
})
19-
it('admin can get all settings', (done) => {
20-
request(app)
21-
.get('/v1/settings')
22-
.set('Accept', 'application/json')
23-
.set('Authorization', `Bearer ${adminToken}`)
24-
.expect(200)
25-
.end(done)
19+
20+
describe('Admin /settings/{setting} endpoint tests', () => {
21+
const endpoints = ['alerts', 'azure', 'customer', 'dns', 'kms', 'home', 'oidc', 'otomi', 'smtp']
22+
endpoints.forEach((ep) => {
23+
it(`admin can get /settings/${ep}`, (done) => {
24+
request(app)
25+
.get(`/v1/settings/${ep}`)
26+
.set('Accept', 'application/json')
27+
.set('Authorization', `Bearer ${adminToken}`)
28+
.expect(200)
29+
.expect('Content-Type', /json/)
30+
.end(done)
31+
})
32+
})
33+
34+
it('admin can put /settings/alerts with correct payload', (done) => {
35+
request(app)
36+
.put('/v1/settings/alerts')
37+
.send({
38+
alerts: {
39+
drone: 'msteams',
40+
groupInterval: '5m',
41+
msteams: {
42+
highPrio: 'bla',
43+
lowPrio: 'bla',
44+
},
45+
receivers: ['slack'],
46+
repeatInterval: '3h',
47+
},
48+
})
49+
.set('Accept', 'application/json')
50+
.set('Authorization', `Bearer ${adminToken}`)
51+
.expect(200)
52+
.end(done)
53+
})
54+
it('admin cannot put /settings/alerts with extra properties', (done) => {
55+
request(app)
56+
.put('/v1/settings/alerts')
57+
.send({
58+
alerts: {
59+
drone: 'msteams',
60+
groupInterval: '5m',
61+
msteams: {
62+
highPrio: 'bla',
63+
lowPrio: 'bla',
64+
},
65+
receivers: ['slack'],
66+
repeatInterval: '3h',
67+
randomProp: 'randomValue',
68+
},
69+
})
70+
.set('Accept', 'application/json')
71+
.set('Authorization', `Bearer ${adminToken}`)
72+
.expect(400)
73+
.end(done)
74+
})
75+
76+
it('admin can put empty payload, but it wont change anything', (done) => {
77+
request(app)
78+
.put('/v1/settings/dns')
79+
.send({
80+
zones: ['someZoneOne', 'someZoneTwo'],
81+
})
82+
.set('Accept', 'application/json')
83+
.set('Authorization', `Bearer ${adminToken}`)
84+
.expect(400)
85+
.end(done)
86+
})
2687
})
88+
2789
it('admin can update team self-service-flags', (done) => {
2890
request(app)
2991
.put('/v1/teams/team1')
@@ -39,41 +101,6 @@ describe('Admin API tests', () => {
39101
.expect(200)
40102
.end(done)
41103
})
42-
43-
it('admin can put with payload that matches the schema', (done) => {
44-
request(app)
45-
.put('/v1/settings')
46-
.send({
47-
alerts: {
48-
drone: 'msteams',
49-
},
50-
})
51-
.set('Accept', 'application/json')
52-
.set('Authorization', `Bearer ${adminToken}`)
53-
.expect(200)
54-
.expect('Content-Type', /json/)
55-
.end(done)
56-
})
57-
it('admin can put with empty body (empty object is valid JSON Schema 7)', (done) => {
58-
request(app)
59-
.put('/v1/settings')
60-
.send({})
61-
.set('Accept', 'application/json')
62-
.set('Authorization', `Bearer ${adminToken}`)
63-
.expect(200)
64-
.expect('Content-Type', /json/)
65-
.end(done)
66-
})
67-
it(`admin can't put with keys that don't match settings object`, (done) => {
68-
request(app)
69-
.put('/v1/settings')
70-
.send({ foo: 'bar' })
71-
.set('Accept', 'application/json')
72-
.set('Authorization', `Bearer ${adminToken}`)
73-
.expect(400)
74-
.expect('Content-Type', /json/)
75-
.end(done)
76-
})
77104
it('admin can get all teams', (done) => {
78105
request(app)
79106
.get('/v1/teams')

src/api/settings.ts

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

src/api/settings/{setting}.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Operation, OperationHandlerArray } from 'express-openapi'
2+
import OtomiStack from '../../otomi-stack'
3+
import { OpenApiRequest } from '../../otomi-models'
4+
5+
export default function (otomi: OtomiStack): OperationHandlerArray {
6+
const GET: Operation = [
7+
({ params: { setting } }: OpenApiRequest, res): void => {
8+
console.debug(`Get settings: ${JSON.stringify({ setting })}`)
9+
res.json(otomi.getSubSetting('settings', setting))
10+
},
11+
]
12+
const PUT: Operation = [
13+
({ params: { setting }, body }: OpenApiRequest, res): void => {
14+
console.debug(`Modify settings: ${JSON.stringify({ setting })}`)
15+
res.json(otomi.setSubSetting('settings', body, setting))
16+
},
17+
]
18+
const api = {
19+
GET,
20+
PUT,
21+
}
22+
return api
23+
}

src/app.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,5 @@ otomiStack
2828
})
2929
.catch((e) => {
3030
console.error(e)
31-
server.close()
3231
process.exit(1)
3332
})

0 commit comments

Comments
 (0)