samanbayaka 0.0.15 → 0.0.16
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/README.md +12 -8
- package/commit-hash.mjs +1 -1
- package/helper/utility/access-token-validator.mjs +171 -0
- package/index.mjs +1 -4
- package/package.json +3 -1
- package/public/signin.html +93 -0
- package/services/about/index.mjs +11 -1
- package/services/bff/index.mjs +37 -0
- package/services/gateway/index.mjs +32 -4
- package/services/kafka/index.mjs +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Once the package is installed, you can import the library using import or requir
|
|
|
35
35
|
import sbk from "samanbayaka"
|
|
36
36
|
```
|
|
37
37
|
# Prerequisites
|
|
38
|
-
It is assumed that NATS, Redpanda, and
|
|
38
|
+
It is assumed that NATS, Redpanda, Redis, and Etcd are installed and properly configured. All services should be discoverable through the /etc/hosts file.
|
|
39
39
|
#### Minimum required Node.js version: >= 22.x.x
|
|
40
40
|
```bash
|
|
41
41
|
node -v
|
|
@@ -256,7 +256,7 @@ pnpm install samanbayaka
|
|
|
256
256
|
touch index.mjs
|
|
257
257
|
```
|
|
258
258
|
|
|
259
|
-
Open index.mjs and paste the following:
|
|
259
|
+
Open `index.mjs` and paste the following:
|
|
260
260
|
```bash
|
|
261
261
|
import sbk from "samanbayaka"
|
|
262
262
|
await sbk.loadGatewayService()
|
|
@@ -280,7 +280,7 @@ pnpm install samanbayaka
|
|
|
280
280
|
touch index.mjs
|
|
281
281
|
```
|
|
282
282
|
|
|
283
|
-
Open index.mjs and paste the following:
|
|
283
|
+
Open `index.mjs` and paste the following:
|
|
284
284
|
```bash
|
|
285
285
|
import sbk from "samanbayaka"
|
|
286
286
|
await sbk.loadFeatureService({
|
|
@@ -339,7 +339,7 @@ pnpm install samanbayaka
|
|
|
339
339
|
touch index.mjs
|
|
340
340
|
```
|
|
341
341
|
|
|
342
|
-
Open index.mjs and paste the following:
|
|
342
|
+
Open `index.mjs` and paste the following:
|
|
343
343
|
```bash
|
|
344
344
|
import sbk from "samanbayaka"
|
|
345
345
|
await sbk.auxBrokerService(
|
|
@@ -372,13 +372,13 @@ touch index.mjs
|
|
|
372
372
|
```
|
|
373
373
|
An auxiliary service, such as a `consumer` that subscribe messages from the `STUDENT` topic having group name `junior`, can be created as follows:
|
|
374
374
|
```js
|
|
375
|
-
mkdir
|
|
376
|
-
cd
|
|
375
|
+
mkdir consumer-kafka-student-junior
|
|
376
|
+
cd consumer-kafka-student-junior
|
|
377
377
|
pnpm init
|
|
378
378
|
pnpm install samanbayaka
|
|
379
379
|
touch index.mjs
|
|
380
380
|
```
|
|
381
|
-
Open index.mjs and paste the following:
|
|
381
|
+
Open `index.mjs` and paste the following:
|
|
382
382
|
```bash
|
|
383
383
|
import sbk from "samanbayaka"
|
|
384
384
|
await sbk.auxBrokerService(
|
|
@@ -426,7 +426,7 @@ pnpm init
|
|
|
426
426
|
pnpm install samanbayaka
|
|
427
427
|
touch demo.mjs
|
|
428
428
|
```
|
|
429
|
-
Open and edit the demo.mjs file as follows
|
|
429
|
+
Open and edit the `demo.mjs` file as follows
|
|
430
430
|
```bash
|
|
431
431
|
import sbk from "samanbayaka"
|
|
432
432
|
await sbk.loadDemo()
|
|
@@ -436,6 +436,10 @@ Run the service, demo
|
|
|
436
436
|
node demo.mjs
|
|
437
437
|
```
|
|
438
438
|
|
|
439
|
+
## Documentation
|
|
440
|
+
|
|
441
|
+
- [docker](docs/dockers.md)
|
|
442
|
+
|
|
439
443
|
<p align="center" style="margin-top: 100px;">
|
|
440
444
|
<img src="https://moleculer.services/images/banner.png" alt="Moleculer Logo" width="600">
|
|
441
445
|
</p>
|
package/commit-hash.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const COMMIT_HASH = '
|
|
1
|
+
export const COMMIT_HASH = '6442e51';
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import ApiGateway from "moleculer-web"
|
|
2
|
+
import jwt from "jsonwebtoken"
|
|
3
|
+
import jwksClient from "jwks-rsa"
|
|
4
|
+
|
|
5
|
+
const OPENID_CONFIG = {
|
|
6
|
+
url: "https://accounts.google.com/.well-known/openid-configuration",
|
|
7
|
+
clientId: "184045176764-ugg28aegdro383pintufun14uubtt374.apps.googleusercontent.com",
|
|
8
|
+
jwksClient: {
|
|
9
|
+
cache: true,
|
|
10
|
+
cacheMaxEntries: 5,
|
|
11
|
+
cacheMaxAge: 10 * 60 * 1000,
|
|
12
|
+
rateLimit: true,
|
|
13
|
+
jwksRequestsPerMinute: 10,
|
|
14
|
+
},
|
|
15
|
+
jwtVerifyAlgo: ["RS256"],
|
|
16
|
+
client: {},
|
|
17
|
+
issuer: "",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// let client
|
|
21
|
+
// let issuer
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Retrieves the public signing key corresponding to a JWT `kid`.
|
|
25
|
+
*
|
|
26
|
+
* Used by JWT verification libraries (such as `jsonwebtoken`)
|
|
27
|
+
* to dynamically resolve signing keys from a JWKS endpoint.
|
|
28
|
+
*
|
|
29
|
+
* @param {Object} header - Decoded JWT header.
|
|
30
|
+
* @param {string} header.kid - Key ID used to identify the signing key.
|
|
31
|
+
* @param {Function} callback - Callback function invoked after key retrieval.
|
|
32
|
+
* @param {Error|null} callback.err - Error object if key retrieval fails.
|
|
33
|
+
* @param {string|null} callback.key - PEM formatted public key.
|
|
34
|
+
*
|
|
35
|
+
* @returns {void}
|
|
36
|
+
*/
|
|
37
|
+
const getKey = (header, callback) => {
|
|
38
|
+
|
|
39
|
+
OPENID_CONFIG.client.getSigningKey(
|
|
40
|
+
header.kid,
|
|
41
|
+
(err, key) => {
|
|
42
|
+
|
|
43
|
+
if (err) {
|
|
44
|
+
callback(err)
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
callback(
|
|
49
|
+
null,
|
|
50
|
+
key.publicKey || key.rsaPublicKey
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Initializes OpenID Connect configuration and JWKS client.
|
|
60
|
+
*
|
|
61
|
+
* Fetches the OpenID configuration document from the configured
|
|
62
|
+
* issuer endpoint and creates a cached JWKS client for JWT
|
|
63
|
+
* signature verification.
|
|
64
|
+
*
|
|
65
|
+
* The JWKS client supports:
|
|
66
|
+
* - Automatic key retrieval
|
|
67
|
+
* - In-memory caching
|
|
68
|
+
* - Request rate limiting
|
|
69
|
+
*
|
|
70
|
+
* @async
|
|
71
|
+
* @function initOpenId
|
|
72
|
+
*
|
|
73
|
+
* @throws {Error} Throws if the OpenID configuration request fails
|
|
74
|
+
* or the response cannot be parsed.
|
|
75
|
+
*
|
|
76
|
+
* @returns {Promise<void>}
|
|
77
|
+
*/
|
|
78
|
+
export const initOpenId = async () => {
|
|
79
|
+
|
|
80
|
+
const response = await fetch(OPENID_CONFIG.url)
|
|
81
|
+
|
|
82
|
+
if ( !response.ok ) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`OpenID configuration endpoint failed with status "${response.status}"`
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const config = await response.json()
|
|
89
|
+
|
|
90
|
+
OPENID_CONFIG.issuer = config.issuer
|
|
91
|
+
|
|
92
|
+
OPENID_CONFIG.client = jwksClient({
|
|
93
|
+
...OPENID_CONFIG.jwksClient,
|
|
94
|
+
...{jwksUri: config.jwks_uri},
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Authorizes the requester by validating the access token.
|
|
102
|
+
* The token can be provided either in the Bearer Authorization header
|
|
103
|
+
* or in cookies.
|
|
104
|
+
*
|
|
105
|
+
* @param {Context} ctx - Moleculer service context
|
|
106
|
+
* @param {Object} route - REST route configuration object
|
|
107
|
+
* @param {HTTP request<Object>} req - HTTP request object
|
|
108
|
+
* @returns {Promise<Object>} Authenticated user / authorization result
|
|
109
|
+
*/
|
|
110
|
+
export const authorize = async (ctx, route, req) => {
|
|
111
|
+
|
|
112
|
+
let token = null
|
|
113
|
+
|
|
114
|
+
const auth =
|
|
115
|
+
req.headers.authorization
|
|
116
|
+
|
|
117
|
+
if (auth?.startsWith("Bearer ")) {
|
|
118
|
+
token = auth.replace(/^Bearer\s+/i, "")
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
if (
|
|
123
|
+
!token &&
|
|
124
|
+
req.cookies?.id_token
|
|
125
|
+
) {
|
|
126
|
+
token = req.cookies.id_token
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (!token) {
|
|
130
|
+
throw new ApiGateway.Errors.UnAuthorizedError(
|
|
131
|
+
ApiGateway.Errors.ERR_NO_TOKEN
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
|
|
137
|
+
const decoded =
|
|
138
|
+
await new Promise((resolve, reject) => {
|
|
139
|
+
|
|
140
|
+
jwt.verify(
|
|
141
|
+
token,
|
|
142
|
+
getKey,
|
|
143
|
+
{
|
|
144
|
+
algorithms: OPENID_CONFIG.jwtVerifyAlgo,
|
|
145
|
+
issuer: OPENID_CONFIG.issuer,
|
|
146
|
+
audience: OPENID_CONFIG.clientId,
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
(err, decoded) => {
|
|
150
|
+
|
|
151
|
+
if (err) {
|
|
152
|
+
reject(err)
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
resolve(decoded)
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
ctx.broker.logger.debug({message: "Decoded Token Object", token: decoded})
|
|
162
|
+
ctx.meta.user = { name: decoded?.name, email: decoded?.email }
|
|
163
|
+
return decoded
|
|
164
|
+
|
|
165
|
+
} catch (err) {
|
|
166
|
+
throw new ApiGateway.Errors.UnAuthorizedError(
|
|
167
|
+
ApiGateway.Errors.ERR_INVALID_TOKEN
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
package/index.mjs
CHANGED
|
@@ -19,7 +19,6 @@ import HybridCacher from "#hMol/HybridCacher.mjs"
|
|
|
19
19
|
import about from '#sAbt/index.mjs'
|
|
20
20
|
import apiGateway from '#sApi/index.mjs'
|
|
21
21
|
import { auxBrokerParamsValidator } from '#hUti/aux-broker-params-validator.mjs'
|
|
22
|
-
|
|
23
22
|
import * as kafka from '#sKfk/index.mjs'
|
|
24
23
|
import * as demo from '#sDmo/index.mjs'
|
|
25
24
|
|
|
@@ -27,7 +26,6 @@ import * as demo from '#sDmo/index.mjs'
|
|
|
27
26
|
const BROKER_CONFIG = await getConfig('nats')
|
|
28
27
|
const CATCHER_CONFIG = await getConfig('catcher')
|
|
29
28
|
const TELEMETRY_CONFIG = await getConfig('telemetry')
|
|
30
|
-
const KAFKA_CONFIG = await getConfig('kafkajs')
|
|
31
29
|
|
|
32
30
|
const sbkLoggers = {
|
|
33
31
|
"CustomPino": customLogger
|
|
@@ -155,7 +153,7 @@ export default {
|
|
|
155
153
|
auxBroker = kafka
|
|
156
154
|
}
|
|
157
155
|
else {
|
|
158
|
-
throw new Error("The \"type\" value must be either \"kafka\" or \"mqtt\"
|
|
156
|
+
throw new Error("The \"type\" value must be either \"kafka\" or \"mqtt\" or \"amqp\"")
|
|
159
157
|
}
|
|
160
158
|
|
|
161
159
|
opts.logLevel = logLevel
|
|
@@ -179,7 +177,6 @@ export default {
|
|
|
179
177
|
)
|
|
180
178
|
}
|
|
181
179
|
|
|
182
|
-
|
|
183
180
|
/**
|
|
184
181
|
* Start broker
|
|
185
182
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "samanbayaka",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"description": "Moleculer Gateway service with kafka transporter",
|
|
5
5
|
"homepage": "https://gitlab.com/dalal.suvendu/samanbayaka#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -43,6 +43,8 @@
|
|
|
43
43
|
"cookie-parser": "^1.4.7",
|
|
44
44
|
"helmet": "^8.1.0",
|
|
45
45
|
"ioredis": "^5.10.1",
|
|
46
|
+
"jsonwebtoken": "^9.0.3",
|
|
47
|
+
"jwks-rsa": "^4.0.1",
|
|
46
48
|
"kafkajs": "^2.2.4",
|
|
47
49
|
"lru-cache": "^11.3.5",
|
|
48
50
|
"moleculer": "0.15.0",
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<button onclick="login()">Login with Google</button>
|
|
2
|
+
<button onclick="callAPI()">Call API</button>
|
|
3
|
+
|
|
4
|
+
<script>
|
|
5
|
+
const CLIENT_ID = "184045176764-fmdarpud3fkpojo5p73mloetgrqrg65p.apps.googleusercontent.com";
|
|
6
|
+
const REDIRECT_URI = "http://localhost:3000";
|
|
7
|
+
const AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
8
|
+
const TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
9
|
+
|
|
10
|
+
// --- PKCE helpers ---
|
|
11
|
+
function generateRandomString(length) {
|
|
12
|
+
const chars =
|
|
13
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
14
|
+
let result = "";
|
|
15
|
+
for (let i = 0; i < length; i++) {
|
|
16
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function sha256(verifier) {
|
|
22
|
+
const encoder = new TextEncoder();
|
|
23
|
+
const data = encoder.encode(verifier);
|
|
24
|
+
const hash = await crypto.subtle.digest("SHA-256", data);
|
|
25
|
+
return btoa(String.fromCharCode(...new Uint8Array(hash)))
|
|
26
|
+
.replace(/\+/g, "-")
|
|
27
|
+
.replace(/\//g, "_")
|
|
28
|
+
.replace(/=+$/, "");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// --- Step 1: login redirect ---
|
|
32
|
+
async function login() {
|
|
33
|
+
const codeVerifier = generateRandomString(64);
|
|
34
|
+
const codeChallenge = await sha256(codeVerifier);
|
|
35
|
+
|
|
36
|
+
localStorage.setItem("code_verifier", codeVerifier);
|
|
37
|
+
|
|
38
|
+
const url =
|
|
39
|
+
`${AUTH_URL}?response_type=code` +
|
|
40
|
+
`&client_id=${CLIENT_ID}` +
|
|
41
|
+
`&redirect_uri=${REDIRECT_URI}` +
|
|
42
|
+
`&scope=openid%20email%20profile` +
|
|
43
|
+
`&code_challenge=${codeChallenge}` +
|
|
44
|
+
`&code_challenge_method=S256`;
|
|
45
|
+
|
|
46
|
+
window.location = url;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// --- Step 2: handle redirect ---
|
|
50
|
+
async function handleRedirect() {
|
|
51
|
+
const params = new URLSearchParams(window.location.search);
|
|
52
|
+
const code = params.get("code");
|
|
53
|
+
|
|
54
|
+
if (!code) return;
|
|
55
|
+
|
|
56
|
+
const codeVerifier = localStorage.getItem("code_verifier");
|
|
57
|
+
|
|
58
|
+
const res = await fetch(TOKEN_URL, {
|
|
59
|
+
method: "POST",
|
|
60
|
+
headers: {
|
|
61
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
62
|
+
},
|
|
63
|
+
body: new URLSearchParams({
|
|
64
|
+
client_id: CLIENT_ID,
|
|
65
|
+
grant_type: "authorization_code",
|
|
66
|
+
code,
|
|
67
|
+
code_verifier: codeVerifier,
|
|
68
|
+
redirect_uri: REDIRECT_URI,
|
|
69
|
+
}),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const data = await res.json();
|
|
73
|
+
|
|
74
|
+
console.log("Access Token:", data.access_token);
|
|
75
|
+
|
|
76
|
+
localStorage.setItem("access_token", data.access_token);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// --- Step 3: call API ---
|
|
80
|
+
async function callAPI() {
|
|
81
|
+
const token = localStorage.getItem("access_token");
|
|
82
|
+
|
|
83
|
+
const res = await fetch("http://localhost:4000/api/resource", {
|
|
84
|
+
headers: {
|
|
85
|
+
Authorization: `Bearer ${token}`,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
console.log(await res.json());
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
handleRedirect();
|
|
93
|
+
</script>
|
package/services/about/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { pkgDtls } from '#hFil/esm-loading.mjs'
|
|
|
3
3
|
export default {
|
|
4
4
|
name: "about",
|
|
5
5
|
actions: {
|
|
6
|
-
|
|
6
|
+
project: {
|
|
7
7
|
rest: {
|
|
8
8
|
method: "GET",
|
|
9
9
|
path: "/"
|
|
@@ -34,5 +34,15 @@ export default {
|
|
|
34
34
|
return `${pkgDtls.fullName} ${pkgDtls.version}`
|
|
35
35
|
},
|
|
36
36
|
},
|
|
37
|
+
profile: {
|
|
38
|
+
rest: {
|
|
39
|
+
method: "GET",
|
|
40
|
+
path: "/me"
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
handler: async(ctx) => {
|
|
44
|
+
return ctx.meta.user
|
|
45
|
+
}
|
|
46
|
+
}
|
|
37
47
|
},
|
|
38
48
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { pkgDtls } from '#hFil/esm-loading.mjs'
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
name: "bff",
|
|
5
|
+
actions: {
|
|
6
|
+
signin: {
|
|
7
|
+
rest: {
|
|
8
|
+
method: "GET",
|
|
9
|
+
path: "/signin"
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
handler: async(ctx) => {
|
|
13
|
+
return `Welcome to ${pkgDtls.name} is a microservices-based project built with moleculer and moleculer-web, designed for scalable, high-performance service communication and API management.`
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
callback: {
|
|
17
|
+
rest: {
|
|
18
|
+
method: "GET",
|
|
19
|
+
path: "/callback"
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
handler: async(ctx) => {
|
|
23
|
+
return `${pkgDtls.fullName} ${pkgDtls.version}`
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
signout: {
|
|
27
|
+
rest: {
|
|
28
|
+
method: "GET",
|
|
29
|
+
path: "/signout"
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
handler: async(ctx) => {
|
|
33
|
+
return ctx.meta.user
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// index.mjs
|
|
2
2
|
import ApiGateway from "moleculer-web"
|
|
3
3
|
import OpenApi from "moleculer-auto-openapi"
|
|
4
4
|
import cookieParser from "cookie-parser"
|
|
@@ -6,6 +6,7 @@ import helmet from "helmet"
|
|
|
6
6
|
import compression from "compression"
|
|
7
7
|
|
|
8
8
|
import {formatHttpErrors} from '#hUti/error-handler.mjs'
|
|
9
|
+
import { initOpenId, authorize } from '#hUti/access-token-validator.mjs'
|
|
9
10
|
|
|
10
11
|
export default {
|
|
11
12
|
name: "gateway",
|
|
@@ -13,6 +14,13 @@ export default {
|
|
|
13
14
|
ApiGateway,
|
|
14
15
|
],
|
|
15
16
|
|
|
17
|
+
async started() {
|
|
18
|
+
/**
|
|
19
|
+
* Initialize OpenID config
|
|
20
|
+
*/
|
|
21
|
+
await initOpenId()
|
|
22
|
+
},
|
|
23
|
+
|
|
16
24
|
settings: {
|
|
17
25
|
port: process.env.SBK_PORT || 8765,
|
|
18
26
|
|
|
@@ -42,14 +50,33 @@ export default {
|
|
|
42
50
|
|
|
43
51
|
|
|
44
52
|
routes: [
|
|
53
|
+
// Public routes
|
|
54
|
+
{
|
|
55
|
+
path: "/",
|
|
56
|
+
authorization: false,
|
|
57
|
+
|
|
58
|
+
whitelist: [
|
|
59
|
+
"bff.*",
|
|
60
|
+
],
|
|
61
|
+
|
|
62
|
+
autoAliases: true,
|
|
63
|
+
mappingPolicy: "restrict",
|
|
64
|
+
|
|
65
|
+
bodyParsers: {
|
|
66
|
+
json: true,
|
|
67
|
+
urlencoded: { extended: true }
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
|
|
45
71
|
/**
|
|
46
|
-
* API routes
|
|
72
|
+
* Protected API routes
|
|
47
73
|
*/
|
|
48
74
|
{
|
|
49
75
|
path: "/api",
|
|
76
|
+
authorization: true,
|
|
50
77
|
whitelist: [
|
|
51
78
|
/**
|
|
52
|
-
* Access any actions except 'system' service
|
|
79
|
+
* Access any actions except 'gateway' and 'system' service
|
|
53
80
|
*/
|
|
54
81
|
/^(?!(gateway|system)\.)\w+(?:\.\w+)*$/
|
|
55
82
|
],
|
|
@@ -124,6 +151,7 @@ export default {
|
|
|
124
151
|
// this.logger.error(" Request error!", err.name, ":", err.message, "\n", err.stack, "\nData:", err.data);
|
|
125
152
|
// }
|
|
126
153
|
this.sendError(req, res, err)
|
|
127
|
-
}
|
|
154
|
+
},
|
|
155
|
+
authorize,
|
|
128
156
|
},
|
|
129
157
|
}
|