@continuoussecuritytooling/keycloak-reporter 0.4.0 → 0.5.0
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/.bin/wait-for-server.sh +1 -0
- package/.eslintrc.cjs +3 -3
- package/.github/CONTRIBUTING.md +5 -5
- package/.github/workflows/pipeline.yml +13 -10
- package/.prettierrc +6 -0
- package/charts/keycloak-reporter/Chart.yaml +3 -2
- package/charts/keycloak-reporter/README.md +2 -2
- package/charts/keycloak-reporter/values.yaml +1 -0
- package/cli.ts +49 -22
- package/dist/cli.js +34 -17
- package/dist/cli.js.map +1 -1
- package/dist/lib/output.js +53 -50
- package/dist/lib/output.js.map +1 -1
- package/e2e/spec/webhooks.js +80 -10
- package/lib/output.ts +63 -57
- package/package.json +3 -1
- package/renovate.json +15 -7
package/.bin/wait-for-server.sh
CHANGED
|
@@ -7,6 +7,7 @@ until $(curl --output /dev/null --silent --head --fail http://localhost:8080/rea
|
|
|
7
7
|
sleep 5
|
|
8
8
|
if [[ "$counter" -gt 24 ]]; then
|
|
9
9
|
printf "Keycloak server failed to start. Timeout!"
|
|
10
|
+
curl --head --fail http://localhost:8080/realms/master/.well-known/openid-configuration
|
|
10
11
|
exit 1
|
|
11
12
|
fi
|
|
12
13
|
counter=$((counter + 1))
|
package/.eslintrc.cjs
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
module.exports = {
|
|
3
3
|
env: {
|
|
4
4
|
node: true,
|
|
5
|
-
commonjs: true
|
|
5
|
+
commonjs: true
|
|
6
6
|
},
|
|
7
7
|
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
|
|
8
8
|
parser: '@typescript-eslint/parser',
|
|
9
9
|
plugins: ['@typescript-eslint'],
|
|
10
10
|
root: true,
|
|
11
11
|
rules: {
|
|
12
|
-
quotes: [2, 'single', { avoidEscape: true }]
|
|
13
|
-
}
|
|
12
|
+
quotes: [2, 'single', { avoidEscape: true }]
|
|
13
|
+
}
|
|
14
14
|
};
|
package/.github/CONTRIBUTING.md
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
We'd love for you to contribute to our source code and to make this package even better than it is
|
|
4
4
|
today! Here are the guidelines we'd like you to follow:
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
- [ Found an Issue?](#-found-an-issue)
|
|
7
|
+
- [ Want a Feature?](#-want-a-feature)
|
|
8
|
+
- [ Coding Rules](#-coding-rules)
|
|
9
|
+
- [ Git Commit Guidelines](#-git-commit-guidelines)
|
|
10
10
|
|
|
11
11
|
## <a name="issue"></a> Found an Issue?
|
|
12
12
|
|
|
@@ -17,7 +17,7 @@ with a fix. But first search if the issue is already described!
|
|
|
17
17
|
If not create a new issue:
|
|
18
18
|
|
|
19
19
|
* Tell about your environment:
|
|
20
|
-
*
|
|
20
|
+
* NodeJS version
|
|
21
21
|
* used platform and version
|
|
22
22
|
* Describe your issue
|
|
23
23
|
* describe your steps leading to the issue
|
|
@@ -11,7 +11,6 @@ jobs:
|
|
|
11
11
|
strategy:
|
|
12
12
|
matrix:
|
|
13
13
|
node_version:
|
|
14
|
-
- 16
|
|
15
14
|
- 18
|
|
16
15
|
- 20
|
|
17
16
|
os:
|
|
@@ -47,7 +46,7 @@ jobs:
|
|
|
47
46
|
|
|
48
47
|
- uses: actions/setup-python@v4
|
|
49
48
|
with:
|
|
50
|
-
python-version:
|
|
49
|
+
python-version: "3.9"
|
|
51
50
|
check-latest: true
|
|
52
51
|
|
|
53
52
|
- name: Helm Chart Testing
|
|
@@ -81,16 +80,11 @@ jobs:
|
|
|
81
80
|
end2end:
|
|
82
81
|
name: "End2End Test on Node ${{ matrix.node_version }} and ${{ matrix.os }}"
|
|
83
82
|
runs-on: "${{ matrix.os }}"
|
|
84
|
-
needs:
|
|
85
|
-
- build
|
|
86
|
-
- chart
|
|
87
83
|
strategy:
|
|
88
84
|
matrix:
|
|
89
85
|
node_version:
|
|
90
|
-
-
|
|
91
|
-
|
|
92
|
-
#- 18
|
|
93
|
-
#- 20
|
|
86
|
+
- 18
|
|
87
|
+
- 20
|
|
94
88
|
os:
|
|
95
89
|
- ubuntu-latest
|
|
96
90
|
steps:
|
|
@@ -99,10 +93,17 @@ jobs:
|
|
|
99
93
|
uses: actions/setup-node@v3
|
|
100
94
|
with:
|
|
101
95
|
node-version: "${{ matrix.node_version }}"
|
|
96
|
+
- name: Install Java
|
|
97
|
+
uses: actions/setup-java@v3
|
|
98
|
+
with:
|
|
99
|
+
distribution: "temurin" # See 'Supported distributions' for available options
|
|
100
|
+
java-version: "17"
|
|
102
101
|
- name: npm build and test
|
|
103
102
|
run: |
|
|
104
103
|
npm run clean
|
|
105
104
|
npm run build
|
|
105
|
+
- name: Tune GitHub-hosted runner network
|
|
106
|
+
uses: smorimoto/tune-github-hosted-runner-network@v1
|
|
106
107
|
|
|
107
108
|
- name: Start Keycloak server
|
|
108
109
|
run: npm run end2end:start-server &
|
|
@@ -120,11 +121,13 @@ jobs:
|
|
|
120
121
|
name: Build Container Image
|
|
121
122
|
runs-on: ubuntu-latest
|
|
122
123
|
needs:
|
|
124
|
+
- build
|
|
125
|
+
- chart
|
|
123
126
|
- end2end
|
|
124
127
|
steps:
|
|
125
128
|
- uses: actions/checkout@v4
|
|
126
129
|
- uses: actions/setup-node@v3
|
|
127
|
-
|
|
130
|
+
# TODO: Support Node 16+
|
|
128
131
|
with:
|
|
129
132
|
node-version: "16"
|
|
130
133
|
- name: "Build Package"
|
package/.prettierrc
ADDED
|
@@ -15,13 +15,14 @@ type: application
|
|
|
15
15
|
# This is the chart version. This version number should be incremented each time you make changes
|
|
16
16
|
# to the chart and its templates, including the app version.
|
|
17
17
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
|
18
|
-
version: 0.
|
|
18
|
+
version: 0.5.0
|
|
19
19
|
|
|
20
20
|
# This is the version number of the application being deployed. This version number should be
|
|
21
21
|
# incremented each time you make changes to the application. Versions are not expected to
|
|
22
22
|
# follow Semantic Versioning. They should reflect the version the application is using.
|
|
23
23
|
# It is recommended to use it with quotes.
|
|
24
|
-
|
|
24
|
+
# renovate: datasource=github-tags depName=ContinuousSecurityTooling/keycloak-reporter
|
|
25
|
+
appVersion: "0.5.0"
|
|
25
26
|
maintainers:
|
|
26
27
|
# Martin Reinhardt
|
|
27
28
|
- name: hypery2k
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# keycloak-reporter
|
|
2
2
|
|
|
3
|
-
  
|
|
4
4
|
|
|
5
5
|
A Helm chart for Kubernetes
|
|
6
6
|
|
|
@@ -31,7 +31,7 @@ A Helm chart for Kubernetes
|
|
|
31
31
|
| keycloak.config.clientSecret | string | `""` | |
|
|
32
32
|
| keycloak.config.output | string | `"webhook"` | |
|
|
33
33
|
| keycloak.config.url | string | `""` | |
|
|
34
|
-
| keycloak.config.webhookMessage | string | `""` |
|
|
34
|
+
| keycloak.config.webhookMessage | string | `""` | optional message for the webhook post |
|
|
35
35
|
| keycloak.config.webhookType | string | `""` | |
|
|
36
36
|
| keycloak.config.webhookUrl | string | `""` | |
|
|
37
37
|
| keycloak.volumes.reports | string | `""` | |
|
package/cli.ts
CHANGED
|
@@ -9,11 +9,10 @@ import {
|
|
|
9
9
|
listClients,
|
|
10
10
|
Options,
|
|
11
11
|
convertJSON2CSV,
|
|
12
|
-
post2Webhook
|
|
12
|
+
post2Webhook
|
|
13
13
|
} from './index.js';
|
|
14
14
|
import config from './src/config.js';
|
|
15
15
|
|
|
16
|
-
|
|
17
16
|
class WebhookConfig {
|
|
18
17
|
type: string;
|
|
19
18
|
url: string;
|
|
@@ -50,7 +49,15 @@ async function convert(
|
|
|
50
49
|
}
|
|
51
50
|
if (reports.directory) {
|
|
52
51
|
const date = new Date();
|
|
53
|
-
writeFileSync(
|
|
52
|
+
writeFileSync(
|
|
53
|
+
path.join(
|
|
54
|
+
`${reports.directory}`,
|
|
55
|
+
`${reports.name}_${date.getFullYear()}-${
|
|
56
|
+
date.getMonth() + 1
|
|
57
|
+
}-${date.getDate()}.${format.toLowerCase()}`
|
|
58
|
+
),
|
|
59
|
+
outputContent
|
|
60
|
+
);
|
|
54
61
|
}
|
|
55
62
|
switch (output) {
|
|
56
63
|
case 'webhook':
|
|
@@ -60,11 +67,23 @@ async function convert(
|
|
|
60
67
|
config.url,
|
|
61
68
|
config.title,
|
|
62
69
|
outputContent,
|
|
63
|
-
config.message
|
|
70
|
+
config.message
|
|
64
71
|
);
|
|
65
72
|
} catch (e) {
|
|
66
|
-
|
|
67
|
-
|
|
73
|
+
switch (e.code || e.message) {
|
|
74
|
+
case 'Request failed with status code 400':
|
|
75
|
+
console.error('Invalid Teams Webhook Payload. Check your params.');
|
|
76
|
+
throw new Error('Invalid Teams Payload');
|
|
77
|
+
case 'slack_webhook_http_error':
|
|
78
|
+
console.error('Invalid Slack Webhook Payload. Check your params.');
|
|
79
|
+
throw new Error('Invalid Slack Payload');
|
|
80
|
+
default:
|
|
81
|
+
console.error(
|
|
82
|
+
`Error during sending webhook.(${e?.code})`,
|
|
83
|
+
e?.original
|
|
84
|
+
);
|
|
85
|
+
throw e;
|
|
86
|
+
}
|
|
68
87
|
}
|
|
69
88
|
break;
|
|
70
89
|
// defaulting to standard out
|
|
@@ -81,22 +100,26 @@ yargs(hideBin(process.argv))
|
|
|
81
100
|
() => {},
|
|
82
101
|
async (argv) => {
|
|
83
102
|
const users = await listUsers(<Options>{
|
|
84
|
-
clientId: argv.clientId ? argv.clientId as string: config.clientId,
|
|
85
|
-
clientSecret: argv.clientSecret
|
|
86
|
-
|
|
103
|
+
clientId: argv.clientId ? (argv.clientId as string) : config.clientId,
|
|
104
|
+
clientSecret: argv.clientSecret
|
|
105
|
+
? (argv.clientSecret as string)
|
|
106
|
+
: config.clientSecret,
|
|
107
|
+
rootUrl: argv.url ? (argv.url as string) : config.url
|
|
87
108
|
});
|
|
88
109
|
await convert(
|
|
89
110
|
argv.format as string,
|
|
90
111
|
argv.output as string,
|
|
91
112
|
{
|
|
92
113
|
name: 'user_listing',
|
|
93
|
-
directory: argv.reports as string
|
|
114
|
+
directory: argv.reports as string
|
|
94
115
|
},
|
|
95
116
|
new WebhookConfig(
|
|
96
117
|
argv.webhookType as string,
|
|
97
118
|
argv.webhookUrl as string,
|
|
98
119
|
'User Listing',
|
|
99
|
-
argv.webhookMessage
|
|
120
|
+
argv.webhookMessage
|
|
121
|
+
? (argv.webhookMessage as string)
|
|
122
|
+
: config.webhookMessage
|
|
100
123
|
),
|
|
101
124
|
users
|
|
102
125
|
);
|
|
@@ -109,22 +132,26 @@ yargs(hideBin(process.argv))
|
|
|
109
132
|
() => {},
|
|
110
133
|
async (argv) => {
|
|
111
134
|
const clients = await listClients(<Options>{
|
|
112
|
-
clientId: argv.clientId ? argv.clientId as string: config.clientId,
|
|
113
|
-
clientSecret: argv.clientSecret
|
|
114
|
-
|
|
135
|
+
clientId: argv.clientId ? (argv.clientId as string) : config.clientId,
|
|
136
|
+
clientSecret: argv.clientSecret
|
|
137
|
+
? (argv.clientSecret as string)
|
|
138
|
+
: config.clientSecret,
|
|
139
|
+
rootUrl: argv.url ? (argv.url as string) : config.url
|
|
115
140
|
});
|
|
116
141
|
await convert(
|
|
117
142
|
argv.format as string,
|
|
118
143
|
argv.output as string,
|
|
119
144
|
{
|
|
120
145
|
name: 'client_listing',
|
|
121
|
-
directory: argv.reports as string
|
|
146
|
+
directory: argv.reports as string
|
|
122
147
|
},
|
|
123
148
|
new WebhookConfig(
|
|
124
149
|
argv.webhookType as string,
|
|
125
150
|
argv.webhookUrl as string,
|
|
126
151
|
'Client Listing',
|
|
127
|
-
argv.webhookMessage
|
|
152
|
+
argv.webhookMessage
|
|
153
|
+
? (argv.webhookMessage as string)
|
|
154
|
+
: config.webhookMessage
|
|
128
155
|
),
|
|
129
156
|
clients
|
|
130
157
|
);
|
|
@@ -134,33 +161,33 @@ yargs(hideBin(process.argv))
|
|
|
134
161
|
alias: 'f',
|
|
135
162
|
type: 'string',
|
|
136
163
|
default: 'json',
|
|
137
|
-
description: 'output format, e.g. JSON|CSV'
|
|
164
|
+
description: 'output format, e.g. JSON|CSV'
|
|
138
165
|
})
|
|
139
166
|
.option('output', {
|
|
140
167
|
alias: 'o',
|
|
141
168
|
type: 'string',
|
|
142
169
|
default: 'stdout',
|
|
143
|
-
description: 'output channel'
|
|
170
|
+
description: 'output channel'
|
|
144
171
|
})
|
|
145
172
|
.option('webhookType', {
|
|
146
173
|
alias: 'w',
|
|
147
174
|
type: 'string',
|
|
148
175
|
default: 'slack',
|
|
149
|
-
description: 'Webhook Type'
|
|
176
|
+
description: 'Webhook Type'
|
|
150
177
|
})
|
|
151
178
|
.option('webhookMessage', {
|
|
152
179
|
alias: 'm',
|
|
153
180
|
type: 'string',
|
|
154
|
-
description: 'Webhook Message'
|
|
181
|
+
description: 'Webhook Message'
|
|
155
182
|
})
|
|
156
183
|
.option('webhookUrl', {
|
|
157
184
|
alias: 't',
|
|
158
185
|
type: 'string',
|
|
159
|
-
description: 'Webhook URL'
|
|
186
|
+
description: 'Webhook URL'
|
|
160
187
|
})
|
|
161
188
|
.option('reports', {
|
|
162
189
|
alias: 'r',
|
|
163
190
|
type: 'string',
|
|
164
|
-
description: 'Reports directory'
|
|
191
|
+
description: 'Reports directory'
|
|
165
192
|
})
|
|
166
193
|
.parse();
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { writeFileSync } from 'node:fs';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import yargs from 'yargs/yargs';
|
|
5
5
|
import { hideBin } from 'yargs/helpers';
|
|
6
|
-
import { listUsers, listClients, convertJSON2CSV, post2Webhook
|
|
6
|
+
import { listUsers, listClients, convertJSON2CSV, post2Webhook } from './index.js';
|
|
7
7
|
import config from './src/config.js';
|
|
8
8
|
class WebhookConfig {
|
|
9
9
|
constructor(type, url, title, message) {
|
|
@@ -35,8 +35,17 @@ async function convert(format, output, reports, config, json) {
|
|
|
35
35
|
await post2Webhook(config.type, config.url, config.title, outputContent, config.message);
|
|
36
36
|
}
|
|
37
37
|
catch (e) {
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
switch (e.code || e.message) {
|
|
39
|
+
case 'Request failed with status code 400':
|
|
40
|
+
console.error('Invalid Teams Webhook Payload. Check your params.');
|
|
41
|
+
throw new Error('Invalid Teams Payload');
|
|
42
|
+
case 'slack_webhook_http_error':
|
|
43
|
+
console.error('Invalid Slack Webhook Payload. Check your params.');
|
|
44
|
+
throw new Error('Invalid Slack Payload');
|
|
45
|
+
default:
|
|
46
|
+
console.error(`Error during sending webhook.(${e === null || e === void 0 ? void 0 : e.code})`, e === null || e === void 0 ? void 0 : e.original);
|
|
47
|
+
throw e;
|
|
48
|
+
}
|
|
40
49
|
}
|
|
41
50
|
break;
|
|
42
51
|
// defaulting to standard out
|
|
@@ -50,59 +59,67 @@ yargs(hideBin(process.argv))
|
|
|
50
59
|
() => { }, async (argv) => {
|
|
51
60
|
const users = await listUsers({
|
|
52
61
|
clientId: argv.clientId ? argv.clientId : config.clientId,
|
|
53
|
-
clientSecret: argv.clientSecret
|
|
54
|
-
|
|
62
|
+
clientSecret: argv.clientSecret
|
|
63
|
+
? argv.clientSecret
|
|
64
|
+
: config.clientSecret,
|
|
65
|
+
rootUrl: argv.url ? argv.url : config.url
|
|
55
66
|
});
|
|
56
67
|
await convert(argv.format, argv.output, {
|
|
57
68
|
name: 'user_listing',
|
|
58
|
-
directory: argv.reports
|
|
59
|
-
}, new WebhookConfig(argv.webhookType, argv.webhookUrl, 'User Listing', argv.webhookMessage
|
|
69
|
+
directory: argv.reports
|
|
70
|
+
}, new WebhookConfig(argv.webhookType, argv.webhookUrl, 'User Listing', argv.webhookMessage
|
|
71
|
+
? argv.webhookMessage
|
|
72
|
+
: config.webhookMessage), users);
|
|
60
73
|
})
|
|
61
74
|
.command('listClients [url] [clientId] [clientSecret]', 'fetches all clients in the realms.',
|
|
62
75
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
63
76
|
() => { }, async (argv) => {
|
|
64
77
|
const clients = await listClients({
|
|
65
78
|
clientId: argv.clientId ? argv.clientId : config.clientId,
|
|
66
|
-
clientSecret: argv.clientSecret
|
|
67
|
-
|
|
79
|
+
clientSecret: argv.clientSecret
|
|
80
|
+
? argv.clientSecret
|
|
81
|
+
: config.clientSecret,
|
|
82
|
+
rootUrl: argv.url ? argv.url : config.url
|
|
68
83
|
});
|
|
69
84
|
await convert(argv.format, argv.output, {
|
|
70
85
|
name: 'client_listing',
|
|
71
|
-
directory: argv.reports
|
|
72
|
-
}, new WebhookConfig(argv.webhookType, argv.webhookUrl, 'Client Listing', argv.webhookMessage
|
|
86
|
+
directory: argv.reports
|
|
87
|
+
}, new WebhookConfig(argv.webhookType, argv.webhookUrl, 'Client Listing', argv.webhookMessage
|
|
88
|
+
? argv.webhookMessage
|
|
89
|
+
: config.webhookMessage), clients);
|
|
73
90
|
})
|
|
74
91
|
.option('format', {
|
|
75
92
|
alias: 'f',
|
|
76
93
|
type: 'string',
|
|
77
94
|
default: 'json',
|
|
78
|
-
description: 'output format, e.g. JSON|CSV'
|
|
95
|
+
description: 'output format, e.g. JSON|CSV'
|
|
79
96
|
})
|
|
80
97
|
.option('output', {
|
|
81
98
|
alias: 'o',
|
|
82
99
|
type: 'string',
|
|
83
100
|
default: 'stdout',
|
|
84
|
-
description: 'output channel'
|
|
101
|
+
description: 'output channel'
|
|
85
102
|
})
|
|
86
103
|
.option('webhookType', {
|
|
87
104
|
alias: 'w',
|
|
88
105
|
type: 'string',
|
|
89
106
|
default: 'slack',
|
|
90
|
-
description: 'Webhook Type'
|
|
107
|
+
description: 'Webhook Type'
|
|
91
108
|
})
|
|
92
109
|
.option('webhookMessage', {
|
|
93
110
|
alias: 'm',
|
|
94
111
|
type: 'string',
|
|
95
|
-
description: 'Webhook Message'
|
|
112
|
+
description: 'Webhook Message'
|
|
96
113
|
})
|
|
97
114
|
.option('webhookUrl', {
|
|
98
115
|
alias: 't',
|
|
99
116
|
type: 'string',
|
|
100
|
-
description: 'Webhook URL'
|
|
117
|
+
description: 'Webhook URL'
|
|
101
118
|
})
|
|
102
119
|
.option('reports', {
|
|
103
120
|
alias: 'r',
|
|
104
121
|
type: 'string',
|
|
105
|
-
description: 'Reports directory'
|
|
122
|
+
description: 'Reports directory'
|
|
106
123
|
})
|
|
107
124
|
.parse();
|
|
108
125
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,MAAM,aAAa,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EACL,SAAS,EACT,WAAW,EAEX,eAAe,EACf,YAAY,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/output.js
CHANGED
|
@@ -25,19 +25,19 @@ export async function post2Webhook(type, url, title, reportContent, text) {
|
|
|
25
25
|
facts: [
|
|
26
26
|
{
|
|
27
27
|
title: 'Type',
|
|
28
|
-
value: title
|
|
28
|
+
value: title
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
title: 'Date',
|
|
32
|
-
value: `${date.getDate()}-${date.getMonth() + 1}-${date.getFullYear()}
|
|
33
|
-
}
|
|
34
|
-
]
|
|
32
|
+
value: `${date.getDate()}-${date.getMonth() + 1}-${date.getFullYear()}`
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
type: 'TextBlock',
|
|
38
38
|
text: text != null ? text : '',
|
|
39
|
-
wrap: true
|
|
40
|
-
}
|
|
39
|
+
wrap: true
|
|
40
|
+
}
|
|
41
41
|
],
|
|
42
42
|
actions: [
|
|
43
43
|
{
|
|
@@ -49,59 +49,62 @@ export async function post2Webhook(type, url, title, reportContent, text) {
|
|
|
49
49
|
{
|
|
50
50
|
type: 'TextBlock',
|
|
51
51
|
text: reportContent,
|
|
52
|
-
wrap: true
|
|
53
|
-
}
|
|
52
|
+
wrap: true
|
|
53
|
+
}
|
|
54
54
|
],
|
|
55
|
-
$schema: 'http://adaptivecards.io/schemas/adaptive-card.json'
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
]
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
]
|
|
55
|
+
$schema: 'http://adaptivecards.io/schemas/adaptive-card.json'
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
62
|
});
|
|
63
63
|
// defaulting to Slack
|
|
64
64
|
default:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
65
|
+
// eslint-disable-next-line no-case-declarations
|
|
66
|
+
const blockEntries = [
|
|
67
|
+
{
|
|
68
|
+
type: 'section',
|
|
69
|
+
fields: [
|
|
70
|
+
{ type: 'mrkdwn', text: `*Type*: ${title}` },
|
|
71
|
+
{
|
|
72
|
+
type: 'mrkdwn',
|
|
73
|
+
text: `*Date*: ${date.getDate()}-${date.getMonth() + 1}-${date.getFullYear()}`
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
type: 'divider'
|
|
79
|
+
}
|
|
80
|
+
];
|
|
81
|
+
if (text != null) {
|
|
82
|
+
blockEntries.push({
|
|
83
|
+
type: 'context',
|
|
84
|
+
elements: [{ type: 'plain_text', text: text }]
|
|
85
|
+
});
|
|
86
|
+
blockEntries.push({
|
|
87
|
+
type: 'divider'
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
blockEntries.push({
|
|
91
|
+
type: 'context',
|
|
92
|
+
elements: [
|
|
77
93
|
{
|
|
78
|
-
type: '
|
|
79
|
-
|
|
80
|
-
{
|
|
81
|
-
type: 'context',
|
|
82
|
-
elements: [{ type: 'plain_text', text: text != null ? text : '' }],
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
type: 'divider',
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
type: 'context',
|
|
89
|
-
elements: [
|
|
90
|
-
{
|
|
91
|
-
type: 'mrkdwn',
|
|
92
|
-
text: `
|
|
94
|
+
type: 'mrkdwn',
|
|
95
|
+
text: `
|
|
93
96
|
\`\`\`
|
|
94
97
|
${reportContent}
|
|
95
98
|
\`\`\`
|
|
96
99
|
`
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}, {
|
|
103
|
+
type: 'context',
|
|
104
|
+
elements: [{ type: 'plain_text', text: 'Raw report data' }]
|
|
105
|
+
});
|
|
106
|
+
return new SlackWebhook(url).send({
|
|
107
|
+
blocks: blockEntries
|
|
105
108
|
});
|
|
106
109
|
}
|
|
107
110
|
}
|
package/dist/lib/output.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../lib/output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,IAAI,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEnE,OAAO,EAAE,eAAe,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEjE,IAAK,WAGJ;AAHD,WAAK,WAAW;IACd,8BAAe,CAAA;IACf,8BAAe,CAAA;AACjB,CAAC,EAHI,WAAW,KAAX,WAAW,QAGf;AAOD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAY,EACZ,GAAW,EACX,KAAa,EACb,aAAqB,EACrB,IAAa;IAEb,oCAAoC;IACpC,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;IACxB,QAAQ,IAAI,EAAE;QACZ,KAAK,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE;YAC/B,OAAO,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBAChC,IAAI,EAAE,SAAS;gBACf,WAAW,EAAE;oBACX;wBACE,WAAW,EAAE,yCAAyC;wBACtD,OAAO,EAAE;4BACP,OAAO,EAAE,oDAAoD;4BAC7D,IAAI,EAAE,cAAc;4BACpB,OAAO,EAAE,KAAK;4BACd,IAAI,EAAE;gCACJ;oCACE,IAAI,EAAE,SAAS;oCACf,KAAK,EAAE;wCACL;4CACE,KAAK,EAAE,MAAM;4CACb,KAAK,EAAE,KAAK;yCACb;wCACD;4CACE,KAAK,EAAE,MAAM;4CACb,KAAK,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,IACtB,IAAI,CAAC,QAAQ,EAAE,GAAG,CACpB,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;yCACzB;qCACF;iCACF;gCACD;oCACE,IAAI,EAAE,WAAW;oCACjB,IAAI,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../lib/output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,IAAI,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEnE,OAAO,EAAE,eAAe,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEjE,IAAK,WAGJ;AAHD,WAAK,WAAW;IACd,8BAAe,CAAA;IACf,8BAAe,CAAA;AACjB,CAAC,EAHI,WAAW,KAAX,WAAW,QAGf;AAOD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAY,EACZ,GAAW,EACX,KAAa,EACb,aAAqB,EACrB,IAAa;IAEb,oCAAoC;IACpC,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;IACxB,QAAQ,IAAI,EAAE;QACZ,KAAK,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE;YAC/B,OAAO,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBAChC,IAAI,EAAE,SAAS;gBACf,WAAW,EAAE;oBACX;wBACE,WAAW,EAAE,yCAAyC;wBACtD,OAAO,EAAE;4BACP,OAAO,EAAE,oDAAoD;4BAC7D,IAAI,EAAE,cAAc;4BACpB,OAAO,EAAE,KAAK;4BACd,IAAI,EAAE;gCACJ;oCACE,IAAI,EAAE,SAAS;oCACf,KAAK,EAAE;wCACL;4CACE,KAAK,EAAE,MAAM;4CACb,KAAK,EAAE,KAAK;yCACb;wCACD;4CACE,KAAK,EAAE,MAAM;4CACb,KAAK,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,IACtB,IAAI,CAAC,QAAQ,EAAE,GAAG,CACpB,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;yCACzB;qCACF;iCACF;gCACD;oCACE,IAAI,EAAE,WAAW;oCACjB,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;oCAC9B,IAAI,EAAE,IAAI;iCACX;6BACF;4BACD,OAAO,EAAE;gCACP;oCACE,IAAI,EAAE,iBAAiB;oCACvB,KAAK,EAAE,sBAAsB;oCAC7B,IAAI,EAAE;wCACJ,IAAI,EAAE,cAAc;wCACpB,IAAI,EAAE;4CACJ;gDACE,IAAI,EAAE,WAAW;gDACjB,IAAI,EAAE,aAAa;gDACnB,IAAI,EAAE,IAAI;6CACX;yCACF;wCACD,OAAO,EACL,oDAAoD;qCACvD;iCACF;6BACF;yBACF;qBACF;iBACF;aACF,CAAC,CAAC;QACL,sBAAsB;QACtB;YACE,gDAAgD;YAChD,MAAM,YAAY,GAA+C;gBAC/D;oBACE,IAAI,EAAE,SAAS;oBACf,MAAM,EAAE;wBACN,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,KAAK,EAAE,EAAE;wBAC5C;4BACE,IAAI,EAAE,QAAQ;4BACd,IAAI,EAAE,WAAW,IAAI,CAAC,OAAO,EAAE,IAC7B,IAAI,CAAC,QAAQ,EAAE,GAAG,CACpB,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;yBACzB;qBACF;iBACF;gBACD;oBACE,IAAI,EAAE,SAAS;iBAChB;aACF,CAAC;YACF,IAAI,IAAI,IAAI,IAAI,EAAE;gBAChB,YAAY,CAAC,IAAI,CAAC;oBAChB,IAAI,EAAE,SAAS;oBACf,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;iBAC/C,CAAC,CAAC;gBACH,YAAY,CAAC,IAAI,CAAC;oBAChB,IAAI,EAAE,SAAS;iBAChB,CAAC,CAAC;aACJ;YACD,YAAY,CAAC,IAAI,CACf;gBACE,IAAI,EAAE,SAAS;gBACf,QAAQ,EAAE;oBACR;wBACE,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE;;EAElB,aAAa;;CAEd;qBACY;iBACF;aACF,EACD;gBACE,IAAI,EAAE,SAAS;gBACf,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC;aAC5D,CACF,CAAC;YACF,OAAO,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBAChC,MAAM,EAAE,YAAY;aACrB,CAAC,CAAC;KACN;AACH,CAAC;AAED;GACG"}
|
package/e2e/spec/webhooks.js
CHANGED
|
@@ -4,7 +4,7 @@ import { test } from 'tape';
|
|
|
4
4
|
import { spawn } from 'node:child_process';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
|
|
7
|
-
test('Should post message to Teams',
|
|
7
|
+
test('Should post message to Teams', { timeout: 10000 }, (t) => {
|
|
8
8
|
const cli = spawn(
|
|
9
9
|
path.join(path.dirname('.'), 'node'),
|
|
10
10
|
[
|
|
@@ -15,26 +15,64 @@ test('Should post message to Teams', { timeout: 10000 }, (t) => {
|
|
|
15
15
|
'3UYhI2hryFwoVtcd7ljlaDuD9HXrGV5r',
|
|
16
16
|
'--output=webhook',
|
|
17
17
|
'--webhookType=teams',
|
|
18
|
-
'--webhookUrl=' + process.env.WEBHOOK_TESTING_TEAMS
|
|
18
|
+
'--webhookUrl=' + process.env.WEBHOOK_TESTING_TEAMS
|
|
19
19
|
],
|
|
20
20
|
{
|
|
21
21
|
env: {
|
|
22
|
-
...process.env
|
|
23
|
-
}
|
|
22
|
+
...process.env
|
|
23
|
+
}
|
|
24
24
|
}
|
|
25
25
|
);
|
|
26
26
|
cli.stdout.on('data', (chunk) => {
|
|
27
27
|
console.log(chunk.toString());
|
|
28
28
|
});
|
|
29
29
|
cli.stderr.on('data', (msg) => {
|
|
30
|
-
t.fail(msg)
|
|
30
|
+
t.fail(msg);
|
|
31
31
|
});
|
|
32
32
|
cli.stdout.on('end', () => {
|
|
33
33
|
t.end();
|
|
34
34
|
});
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
-
test(
|
|
37
|
+
test(
|
|
38
|
+
'Should post message to Teams with additional message',
|
|
39
|
+
{ timeout: 10000 },
|
|
40
|
+
(t) => {
|
|
41
|
+
const cli = spawn(
|
|
42
|
+
path.join(path.dirname('.'), 'node'),
|
|
43
|
+
[
|
|
44
|
+
'dist/cli.js',
|
|
45
|
+
'listUsers',
|
|
46
|
+
'http://localhost:8080',
|
|
47
|
+
'keycloak-reporter',
|
|
48
|
+
'3UYhI2hryFwoVtcd7ljlaDuD9HXrGV5r',
|
|
49
|
+
'--output=webhook',
|
|
50
|
+
'--webhookType=teams',
|
|
51
|
+
'--webhookUrl=' + process.env.WEBHOOK_TESTING_TEAMS,
|
|
52
|
+
'--webhookMessage="From Github Actions"'
|
|
53
|
+
],
|
|
54
|
+
{
|
|
55
|
+
env: {
|
|
56
|
+
...process.env
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
cli.stdout.on('data', (chunk) => {
|
|
61
|
+
console.log(chunk.toString());
|
|
62
|
+
});
|
|
63
|
+
cli.stderr.on('data', (msg) => {
|
|
64
|
+
t.fail(msg);
|
|
65
|
+
});
|
|
66
|
+
cli.stdout.on('end', () => {
|
|
67
|
+
t.end();
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
test(
|
|
73
|
+
'Should post message to Slack with additional message',
|
|
74
|
+
{ timeout: 10000 },
|
|
75
|
+
(t) => {
|
|
38
76
|
const cli = spawn(
|
|
39
77
|
path.join(path.dirname('.'), 'node'),
|
|
40
78
|
[
|
|
@@ -46,20 +84,52 @@ test('Should post message to Slack', { timeout: 10000 }, (t) => {
|
|
|
46
84
|
'--output=webhook',
|
|
47
85
|
'--webhookType=slack',
|
|
48
86
|
'--webhookUrl=' + process.env.WEBHOOK_TESTING_SLACK,
|
|
87
|
+
'--webhookMessage="From Github Actions"'
|
|
49
88
|
],
|
|
50
89
|
{
|
|
51
90
|
env: {
|
|
52
|
-
...process.env
|
|
53
|
-
}
|
|
91
|
+
...process.env
|
|
92
|
+
}
|
|
54
93
|
}
|
|
55
94
|
);
|
|
56
95
|
cli.stdout.on('data', (chunk) => {
|
|
57
|
-
console.log(chunk.toString())
|
|
96
|
+
console.log(chunk.toString());
|
|
58
97
|
});
|
|
59
98
|
cli.stderr.on('data', (msg) => {
|
|
60
|
-
t.fail(msg)
|
|
99
|
+
t.fail(msg);
|
|
61
100
|
});
|
|
62
101
|
cli.stdout.on('end', () => {
|
|
63
102
|
t.end();
|
|
64
103
|
});
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
test('Should post message to Slack', { timeout: 10000 }, (t) => {
|
|
108
|
+
const cli = spawn(
|
|
109
|
+
path.join(path.dirname('.'), 'node'),
|
|
110
|
+
[
|
|
111
|
+
'dist/cli.js',
|
|
112
|
+
'listUsers',
|
|
113
|
+
'http://localhost:8080',
|
|
114
|
+
'keycloak-reporter',
|
|
115
|
+
'3UYhI2hryFwoVtcd7ljlaDuD9HXrGV5r',
|
|
116
|
+
'--output=webhook',
|
|
117
|
+
'--webhookType=slack',
|
|
118
|
+
'--webhookUrl=' + process.env.WEBHOOK_TESTING_SLACK
|
|
119
|
+
],
|
|
120
|
+
{
|
|
121
|
+
env: {
|
|
122
|
+
...process.env
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
cli.stdout.on('data', (chunk) => {
|
|
127
|
+
console.log(chunk.toString());
|
|
65
128
|
});
|
|
129
|
+
cli.stderr.on('data', (msg) => {
|
|
130
|
+
t.fail(msg);
|
|
131
|
+
});
|
|
132
|
+
cli.stdout.on('end', () => {
|
|
133
|
+
t.end();
|
|
134
|
+
});
|
|
135
|
+
});
|
package/lib/output.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { IncomingWebhook as TeamsWebhook } from 'ms-teams-webhook';
|
|
2
|
-
import { Block, SectionBlock } from '@slack/types';
|
|
2
|
+
import { Block, ContextBlock, SectionBlock } from '@slack/types';
|
|
3
3
|
import { IncomingWebhook as SlackWebhook } from '@slack/webhook';
|
|
4
4
|
|
|
5
5
|
enum WebhookType {
|
|
6
6
|
SLACK = 'slack',
|
|
7
|
-
TEAMS = 'teams'
|
|
7
|
+
TEAMS = 'teams'
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export interface WebhookMessage {
|
|
@@ -17,7 +17,7 @@ export async function post2Webhook(
|
|
|
17
17
|
url: string,
|
|
18
18
|
title: string,
|
|
19
19
|
reportContent: string,
|
|
20
|
-
text?: string
|
|
20
|
+
text?: string
|
|
21
21
|
): Promise<unknown> {
|
|
22
22
|
//const title= 'Keycloak Reporting';
|
|
23
23
|
const date = new Date();
|
|
@@ -38,21 +38,21 @@ export async function post2Webhook(
|
|
|
38
38
|
facts: [
|
|
39
39
|
{
|
|
40
40
|
title: 'Type',
|
|
41
|
-
value: title
|
|
41
|
+
value: title
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
title: 'Date',
|
|
45
45
|
value: `${date.getDate()}-${
|
|
46
46
|
date.getMonth() + 1
|
|
47
|
-
}-${date.getFullYear()}
|
|
48
|
-
}
|
|
49
|
-
]
|
|
47
|
+
}-${date.getFullYear()}`
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
52
|
type: 'TextBlock',
|
|
53
|
-
text: text!=null ? text : '',
|
|
54
|
-
wrap: true
|
|
55
|
-
}
|
|
53
|
+
text: text != null ? text : '',
|
|
54
|
+
wrap: true
|
|
55
|
+
}
|
|
56
56
|
],
|
|
57
57
|
actions: [
|
|
58
58
|
{
|
|
@@ -64,62 +64,68 @@ export async function post2Webhook(
|
|
|
64
64
|
{
|
|
65
65
|
type: 'TextBlock',
|
|
66
66
|
text: reportContent,
|
|
67
|
-
wrap: true
|
|
68
|
-
}
|
|
67
|
+
wrap: true
|
|
68
|
+
}
|
|
69
69
|
],
|
|
70
70
|
$schema:
|
|
71
|
-
'http://adaptivecards.io/schemas/adaptive-card.json'
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
]
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
]
|
|
71
|
+
'http://adaptivecards.io/schemas/adaptive-card.json'
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
78
|
});
|
|
79
79
|
// defaulting to Slack
|
|
80
80
|
default:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
{
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
81
|
+
// eslint-disable-next-line no-case-declarations
|
|
82
|
+
const blockEntries: Array<Block | ContextBlock | SectionBlock> = [
|
|
83
|
+
{
|
|
84
|
+
type: 'section',
|
|
85
|
+
fields: [
|
|
86
|
+
{ type: 'mrkdwn', text: `*Type*: ${title}` },
|
|
87
|
+
{
|
|
88
|
+
type: 'mrkdwn',
|
|
89
|
+
text: `*Date*: ${date.getDate()}-${
|
|
90
|
+
date.getMonth() + 1
|
|
91
|
+
}-${date.getFullYear()}`
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
type: 'divider'
|
|
97
|
+
}
|
|
98
|
+
];
|
|
99
|
+
if (text != null) {
|
|
100
|
+
blockEntries.push({
|
|
101
|
+
type: 'context',
|
|
102
|
+
elements: [{ type: 'plain_text', text: text }]
|
|
103
|
+
});
|
|
104
|
+
blockEntries.push({
|
|
105
|
+
type: 'divider'
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
blockEntries.push(
|
|
109
|
+
{
|
|
110
|
+
type: 'context',
|
|
111
|
+
elements: [
|
|
112
|
+
{
|
|
113
|
+
type: 'mrkdwn',
|
|
114
|
+
text: `
|
|
111
115
|
\`\`\`
|
|
112
116
|
${reportContent}
|
|
113
117
|
\`\`\`
|
|
114
118
|
`
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
type: 'context',
|
|
124
|
+
elements: [{ type: 'plain_text', text: 'Raw report data' }]
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
return new SlackWebhook(url).send({
|
|
128
|
+
blocks: blockEntries
|
|
123
129
|
});
|
|
124
130
|
}
|
|
125
131
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@continuoussecuritytooling/keycloak-reporter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Reporting Tools for Keycloak",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -44,6 +44,8 @@
|
|
|
44
44
|
"@typescript-eslint/eslint-plugin": "^5.59.6",
|
|
45
45
|
"@typescript-eslint/parser": "^5.59.6",
|
|
46
46
|
"eslint": "^8.40.0",
|
|
47
|
+
"eslint-config-prettier": "^9.0.0",
|
|
48
|
+
"eslint-plugin-prettier": "^5.0.0",
|
|
47
49
|
"gunzip-maybe": "^1.4.2",
|
|
48
50
|
"jest": "^29.5.0",
|
|
49
51
|
"jest-extended": "^4.0.0",
|
package/renovate.json
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
3
|
-
"extends": [
|
|
4
|
-
"config:base",":dependencyDashboard"
|
|
5
|
-
],
|
|
6
|
-
"automerge": true,
|
|
3
|
+
"extends": ["config:base", ":rebaseStalePrs"],
|
|
7
4
|
"platformAutomerge": true,
|
|
8
5
|
"packageRules": [
|
|
9
6
|
{
|
|
10
|
-
"description": "
|
|
11
|
-
"matchUpdateTypes": ["minor", "patch"],
|
|
12
|
-
"automerge": true
|
|
7
|
+
"description": "Automatically merge minor and patch-level updates",
|
|
8
|
+
"matchUpdateTypes": ["minor", "patch", "digest"],
|
|
9
|
+
"automerge": true,
|
|
10
|
+
"automergeType": "branch"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"regexManagers": [
|
|
14
|
+
{
|
|
15
|
+
"description": "Update version entries in YAML files",
|
|
16
|
+
"fileMatch": [".*y[a]?ml$"],
|
|
17
|
+
"matchStrings": [
|
|
18
|
+
"# renovate: datasource=(?<datasource>[a-z-]+?)(?: lookupName=(?<lookupName>.+?))?(?: versioning=(?<versioning>[a-z-]+?))?\\sRUN install-[a-z]+? (?<depName>[a-z-]+?) (?<currentValue>.+?)\\s"
|
|
19
|
+
],
|
|
20
|
+
"versioningTemplate": "{{#if versioning}}{{versioning}}{{else}}semver{{/if}}"
|
|
13
21
|
}
|
|
14
22
|
],
|
|
15
23
|
"prHourlyLimit": 10
|