@suffolklitlab/alkiln 5.12.0-delete2 → 5.12.0-delete4
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/.github/workflows/github_server.yml +50 -9
- package/.github/workflows/log_code_tests.yml +2 -0
- package/.github/workflows/playground.yml +7 -2
- package/CHANGELOG.md +3 -2
- package/lib/docassemble/docassemble_api_REST.js +21 -0
- package/lib/docassemble/docassemble_api_interface.js +63 -12
- package/lib/scope.js +13 -3
- package/lib/steps.js +25 -25
- package/package.json +1 -1
- package/tests/log_codes/check_codes.sh +1 -1
|
@@ -43,18 +43,22 @@ jobs:
|
|
|
43
43
|
#### Developer note: You can probably leave out these specific
|
|
44
44
|
#### environment variables. You may not even need the `env`
|
|
45
45
|
#### keyword or values at all. See
|
|
46
|
-
#### https://suffolklitlab.org/
|
|
46
|
+
#### https://assemblyline.suffolklitlab.org/docs/alkiln/writing#env-vars
|
|
47
47
|
env:
|
|
48
48
|
SECRET_VAR1: secret-var1-value
|
|
49
49
|
SECRET_VAR2: secret-var2-value
|
|
50
50
|
SECRET_FOR_MISSING_FIELD: secret for missing field
|
|
51
|
+
INVALID_API_KEY: invalidAPIkey
|
|
52
|
+
EMPTY_STRING: ""
|
|
53
|
+
USER_NO_PERMISSIONS_EMAIL: alkiln@example.com
|
|
54
|
+
USER_NO_PERMISSIONS_PASSWORD: User123^
|
|
51
55
|
|
|
52
56
|
steps:
|
|
53
57
|
# Place the root directory in this branch to access
|
|
54
58
|
# relative paths to action files
|
|
55
59
|
- uses: actions/checkout@v4
|
|
56
60
|
|
|
57
|
-
- name: ALKiln - Start the isolated temporary docassemble server on GitHub
|
|
61
|
+
- name: "ALKiln - Start the isolated temporary docassemble server on GitHub"
|
|
58
62
|
id: github_server
|
|
59
63
|
#### Developer note: you'll need to replace `uses: ./action_for_github_server`
|
|
60
64
|
#### with the path to ALKiln’s repository name and branch name. For example,
|
|
@@ -71,13 +75,50 @@ jobs:
|
|
|
71
75
|
shell: bash
|
|
72
76
|
|
|
73
77
|
#### Developer note: You can probably leave this out
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
- name: "Create a new normal user with an API key env var"
|
|
79
|
+
env:
|
|
80
|
+
SERVER_URL: "${{ steps.github_server.outputs.SERVER_URL }}"
|
|
81
|
+
KEY: ${{ steps.github_server.outputs.DOCASSEMBLE_DEVELOPER_API_KEY }}
|
|
82
|
+
run: |
|
|
83
|
+
# Create user and their API key
|
|
84
|
+
sudo apt-get install jq
|
|
85
|
+
|
|
86
|
+
# https://docassemble.org/docs/api.html#user_new
|
|
87
|
+
user_data=$(curl -X POST \
|
|
88
|
+
${{ env.SERVER_URL }}/api/user/new \
|
|
89
|
+
-H 'Content-Type: application/json' \
|
|
90
|
+
-d '{
|
|
91
|
+
"key": "${{ env.KEY }}",
|
|
92
|
+
"username": "${{ env.USER_NO_PERMISSIONS_EMAIL }}",
|
|
93
|
+
"password": "${{ env.USER_NO_PERMISSIONS_PASSWORD }}"
|
|
94
|
+
}')
|
|
95
|
+
echo "User data:"
|
|
96
|
+
echo "$user_data"
|
|
97
|
+
|
|
98
|
+
user_id=$(echo "$user_data" | jq '.user_id' -r)
|
|
99
|
+
|
|
100
|
+
# https://docassemble.org/docs/api.html#api_user_user_id_api_post
|
|
101
|
+
new_key=$(curl -X POST \
|
|
102
|
+
${{ env.SERVER_URL }}/api/user/"$user_id"/api \
|
|
103
|
+
-H 'Content-Type: application/json' \
|
|
104
|
+
-d '{
|
|
105
|
+
"key": "${{ env.KEY }}",
|
|
106
|
+
"name": "alkiln_key",
|
|
107
|
+
"method": "none"
|
|
108
|
+
}')
|
|
109
|
+
echo "User new key:"
|
|
110
|
+
echo "$new_key"
|
|
111
|
+
|
|
112
|
+
echo "USER_NO_PERMISSIONS_API_KEY=$new_key" >> "$GITHUB_ENV"
|
|
113
|
+
|
|
114
|
+
### Developer note: You can probably leave this out
|
|
115
|
+
# Optional debugging to explore things like docker issues
|
|
116
|
+
- name: Docker debug tmate session
|
|
117
|
+
#if: ${{ failure() && github.event.inputs.enable_tmate == 'true' }}
|
|
118
|
+
uses: mxschmitt/action-tmate@v3
|
|
78
119
|
|
|
79
120
|
#### Developer note: You can probably leave this out
|
|
80
|
-
- name:
|
|
121
|
+
- name: "Create other env vars for our own tests from server output"
|
|
81
122
|
run: |
|
|
82
123
|
echo "USER1_EMAIL=${{ steps.github_server.outputs.DA_ADMIN_EMAIL }}" >> $GITHUB_ENV
|
|
83
124
|
echo "USER1_PASSWORD=${{ steps.github_server.outputs.DA_ADMIN_PASSWORD }}" >> $GITHUB_ENV
|
|
@@ -106,12 +147,12 @@ jobs:
|
|
|
106
147
|
ALKILN_TAG_EXPRESSION: "${{ (github.event.inputs.tags && format('{0}', github.event.inputs.tags)) || '(not @error) and (not @temp_error)' }}"
|
|
107
148
|
with:
|
|
108
149
|
#### Developer note: Required inputs. See
|
|
109
|
-
#### https://suffolklitlab.org/
|
|
150
|
+
#### https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#sandbox-inputs
|
|
110
151
|
SERVER_URL: "${{ steps.github_server.outputs.SERVER_URL }}"
|
|
111
152
|
DOCASSEMBLE_DEVELOPER_API_KEY: "${{ steps.github_server.outputs.DOCASSEMBLE_DEVELOPER_API_KEY }}"
|
|
112
153
|
INSTALL_METHOD: "server"
|
|
113
154
|
#### Developer note: You can probably leave the rest out
|
|
114
|
-
#### To learn more, see https://suffolklitlab.org/
|
|
155
|
+
#### To learn more, see https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#optional-inputs
|
|
115
156
|
ALKILN_TAG_EXPRESSION: "${{ env.ALKILN_TAG_EXPRESSION }}"
|
|
116
157
|
ALKILN_VERSION: delete
|
|
117
158
|
|
|
@@ -43,6 +43,11 @@ jobs:
|
|
|
43
43
|
PLAYGROUND_ID: ${{ secrets.PLAYGROUND_ID }}
|
|
44
44
|
USER1_EMAIL: ${{ secrets.USER1_EMAIL }}
|
|
45
45
|
USER1_PASSWORD: ${{ secrets.USER1_PASSWORD }}
|
|
46
|
+
USER_NO_PERMISSIONS_EMAIL: ${{ secrets.USER_NO_PERMISSIONS_EMAIL }}
|
|
47
|
+
USER_NO_PERMISSIONS_PASSWORD: ${{ secrets.USER_NO_PERMISSIONS_PASSWORD }}
|
|
48
|
+
USER_NO_PERMISSIONS_API_KEY: ${{ secrets.USER_NO_PERMISSIONS_API_KEY }}
|
|
49
|
+
INVALID_API_KEY: invalidAPIkey
|
|
50
|
+
EMPTY_STRING: ""
|
|
46
51
|
SECRET_VAR1: secret-var1-value
|
|
47
52
|
SECRET_VAR2: secret-var2-value
|
|
48
53
|
SECRET_FOR_MISSING_FIELD: secret for missing field
|
|
@@ -64,10 +69,10 @@ jobs:
|
|
|
64
69
|
ALKILN_TAG_EXPRESSION: "${{ (github.event.inputs.tags && format('{0}', github.event.inputs.tags)) || '(not @error) and (not @temp_error)' }}"
|
|
65
70
|
with:
|
|
66
71
|
#### Developer note: Required ALKiln inputs. You can read more at
|
|
67
|
-
#### https://suffolklitlab.org/
|
|
72
|
+
#### https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#githubNyou-inputs
|
|
68
73
|
SERVER_URL: "${{ env.SERVER_URL }}"
|
|
69
74
|
DOCASSEMBLE_DEVELOPER_API_KEY: "${{ env.DOCASSEMBLE_DEVELOPER_API_KEY }}"
|
|
70
|
-
#### Developer note: See https://suffolklitlab.org/
|
|
75
|
+
#### Developer note: See https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#optional-inputs
|
|
71
76
|
#### You can probably leave this out
|
|
72
77
|
# Internal: docassemble changes sometimes break @a11y tests. That is
|
|
73
78
|
# a da problem, not ours. We will trigger these tests manually when we
|
package/CHANGELOG.md
CHANGED
|
@@ -51,11 +51,12 @@ Format:
|
|
|
51
51
|
|
|
52
52
|
### Fixed
|
|
53
53
|
|
|
54
|
-
- Now
|
|
54
|
+
- Now ALKiln deletes interviews upon interview completion for [signed in users](https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#sign-in) as long as the user has an API key. Also, the author must have used the ["start interview" Step](https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#start-interview) to get to the interview. Admins can give a regular user an API key with https://docassemble.org/docs/api.html#api_user_user_id_api_post. See [#831](https://github.com/SuffolkLITLab/ALKiln/issues/831).
|
|
55
55
|
|
|
56
56
|
### Internal
|
|
57
57
|
|
|
58
|
-
- Test deleting interviews upon interview completion for signed in users
|
|
58
|
+
- Test deleting interviews upon interview completion for signed in users.
|
|
59
|
+
- Switch to mostly using a lowest-access-level user account for actually running interviews.
|
|
59
60
|
- Added @temp_error to neutralize tests that are getting undesired errors right now, but which we anticipate being fixed soon. We want to ignore them for a short while. For example, an upstream change temporarily breaking some tests.
|
|
60
61
|
|
|
61
62
|
## [5.12.0] - 2024-06-06
|
|
@@ -31,6 +31,27 @@ da.get_dev_id = async function ( timeout ) {
|
|
|
31
31
|
}; // Ends da.get_dev_id()
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
da.get_api_key_info = async function ( timeout, { api_key = null, server_url = null }) {
|
|
35
|
+
/** Get information about an API key owned by the user of the given API key. */
|
|
36
|
+
let options = {
|
|
37
|
+
method: 'GET',
|
|
38
|
+
headers: {'X-API-Key': api_key},
|
|
39
|
+
url: `${ server_url }/api/user/api`,
|
|
40
|
+
params: {
|
|
41
|
+
api_key: api_key,
|
|
42
|
+
},
|
|
43
|
+
timeout: timeout,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
return await axios.request( options );
|
|
48
|
+
} catch (error) {
|
|
49
|
+
let response = error.response || { data: null }
|
|
50
|
+
throw {...error.toJSON(), data: response.data};
|
|
51
|
+
}
|
|
52
|
+
}; // Ends da.get_api_key_info()
|
|
53
|
+
|
|
54
|
+
|
|
34
55
|
// node -e 'require("./lib/docassemble/docassemble_api_REST.js").delete_project()'
|
|
35
56
|
da.delete_project = async function ( timeout ) {
|
|
36
57
|
/* Delete a project on the user's da server. */
|
|
@@ -177,6 +177,67 @@ da_i.get_dev_id = async function ( dev_id_options ) {
|
|
|
177
177
|
return dev_id;
|
|
178
178
|
}; // Ends da_i.get_dev_id();
|
|
179
179
|
|
|
180
|
+
da_i.get_api_key_access_status = async function ({ timeout = null, api_key = null }) {
|
|
181
|
+
/** Check if the API key has minimal authorization on the server.
|
|
182
|
+
* See https://docassemble.org/docs/api.html#api_user_api_get.
|
|
183
|
+
*
|
|
184
|
+
* @param options {obj} Options for getting authorization of the API key
|
|
185
|
+
* @param options.api_key {str | null} Required. The API key to test.
|
|
186
|
+
* @param options.timeout {int | null} Optional. Max MS
|
|
187
|
+
* to allow for server request.
|
|
188
|
+
*/
|
|
189
|
+
|
|
190
|
+
let auth_data = {
|
|
191
|
+
codes: [ 1 ],
|
|
192
|
+
has_auth: null,
|
|
193
|
+
messages: [`API key authorization is not yet determined.`],
|
|
194
|
+
error: null
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Skip this for tests run from ALKilnInThePlayground
|
|
198
|
+
if ( session_vars.get_origin() === 'playground' ) {
|
|
199
|
+
auth_data.codes.push( 2 );
|
|
200
|
+
auth_data.messages.push( `API keys are unnecessary for tests run in the Playground.` );
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if ( typeof api_key !== `string` ) {
|
|
204
|
+
auth_data.codes.push( 3 );
|
|
205
|
+
auth_data.messages.push( `The given API key is not a string. Type: ${ typeof api_key }`);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if ( auth_data.codes.length === 1 ) {
|
|
209
|
+
// Default timeouts
|
|
210
|
+
timeout = timeout || DEFAULT_MAX_REQUEST_MS;
|
|
211
|
+
try {
|
|
212
|
+
let response = await _da_REST.get_api_key_info( timeout, {
|
|
213
|
+
api_key,
|
|
214
|
+
server_url: session_vars.get_da_server_url(),
|
|
215
|
+
});
|
|
216
|
+
auth_data.has_auth = true;
|
|
217
|
+
auth_data.codes = [ 6 ];
|
|
218
|
+
auth_data.messages = [ `This API key has at least basic authorization on this server.` ];
|
|
219
|
+
|
|
220
|
+
} catch ( error ) {
|
|
221
|
+
auth_data.error = error;
|
|
222
|
+
if ( error.status === 403 ) {
|
|
223
|
+
auth_data.has_auth = false;
|
|
224
|
+
auth_data.codes = [ 4 ];
|
|
225
|
+
auth_data.messages = [ `This API is unverified on this server. It is probably missing or has been deleted.` ];
|
|
226
|
+
} else {
|
|
227
|
+
// Note on 404, non-existent key: 404 == 403 - Since we're using the
|
|
228
|
+
// key itself to get its own info, if it doesn't exist, we'll get 403
|
|
229
|
+
auth_data.codes = [ 5 ];
|
|
230
|
+
auth_data.messages = [ `This API key threw a non-403 error.` ];
|
|
231
|
+
} // ends error status
|
|
232
|
+
} // ends try
|
|
233
|
+
} // ends auth_data.codes only has the first code
|
|
234
|
+
|
|
235
|
+
log.info({ type: `da api info`, code: `ALK0202`,
|
|
236
|
+
pre: `API key authentication info`, data: auth_data });
|
|
237
|
+
|
|
238
|
+
return auth_data;
|
|
239
|
+
}; // Ends da_i.get_api_key_access_status()
|
|
240
|
+
|
|
180
241
|
// node -e 'require("./lib/docassemble/docassemble_api_interface.js").delete_project( "create1" )'
|
|
181
242
|
da_i.delete_project = async function ( delete_options ) {
|
|
182
243
|
/** Delete a project on the user's da server. Do we need to watch
|
|
@@ -231,7 +292,7 @@ da_i.quietly_delete_one_interview = async function ( timeout, { interview = {},
|
|
|
231
292
|
/** Try to delete an interview using all available API keys. Fail silently.
|
|
232
293
|
* Example failure: the test did not log in any users and the testing
|
|
233
294
|
* account's role prevents access to other user's interviews. */
|
|
234
|
-
|
|
295
|
+
|
|
235
296
|
let responses = [];
|
|
236
297
|
for ( let api_key of api_keys ) {
|
|
237
298
|
try {
|
|
@@ -263,8 +324,6 @@ da_i.get_interviews = async function ({ interviews = {}, api_keys = [], options
|
|
|
263
324
|
/** Return an object of interviews that exist on the server
|
|
264
325
|
* that match the given interviews. Keys are the session ids. */
|
|
265
326
|
|
|
266
|
-
api_keys = normalize_api_keys( api_keys );
|
|
267
|
-
|
|
268
327
|
let fetched_interviews = {};
|
|
269
328
|
if ( interviews ) {
|
|
270
329
|
for ( let id in interviews ) {
|
|
@@ -285,7 +344,6 @@ da_i.get_interview = async function ({ interview = {}, api_keys = [], options =
|
|
|
285
344
|
|
|
286
345
|
// Defaults
|
|
287
346
|
let { timeout } = options || { timeout: DEFAULT_MAX_REQUEST_MS };
|
|
288
|
-
api_keys = normalize_api_keys( api_keys );
|
|
289
347
|
|
|
290
348
|
if ( interview && interview.uid ) {
|
|
291
349
|
for ( let api_key of api_keys ) {
|
|
@@ -304,6 +362,7 @@ da_i.get_interview = async function ({ interview = {}, api_keys = [], options =
|
|
|
304
362
|
} else {
|
|
305
363
|
log.debug({ type: `da api info`, code: `ALK0194`, pre: `Status ${ response.status }. Cannot find ${ interview.uid }`});
|
|
306
364
|
}
|
|
365
|
+
|
|
307
366
|
} catch ( error ) {
|
|
308
367
|
error.interview = interview;
|
|
309
368
|
let msg = `${ error.status || `No error.status.` } ${ error.statusText || error.data || `No error.statusText.` } Ran into an error when getting the interview ${ interview.uid }. See https://docassemble.org/docs/api.html#interviews.`
|
|
@@ -317,11 +376,3 @@ da_i.get_interview = async function ({ interview = {}, api_keys = [], options =
|
|
|
317
376
|
return null;
|
|
318
377
|
|
|
319
378
|
}; // Ends da_i.get_interview()
|
|
320
|
-
|
|
321
|
-
let normalize_api_keys = function ( api_keys = [] ) {
|
|
322
|
-
/** Ensure the dev API key is in the api_keys list. */
|
|
323
|
-
let dev_key = session_vars.get_dev_api_key();
|
|
324
|
-
if ( !api_keys ) { api_keys = [ dev_key ]; }
|
|
325
|
-
if ( !api_keys.includes( dev_key ) ) { api_keys.unshift( dev_key ); }
|
|
326
|
-
return api_keys;
|
|
327
|
-
};
|
package/lib/scope.js
CHANGED
|
@@ -16,7 +16,7 @@ const time = require('./utils/time');
|
|
|
16
16
|
const log = require('./utils/log');
|
|
17
17
|
const { waitForTimeout } = require('./utils/time');
|
|
18
18
|
const files = require('./utils/files' );
|
|
19
|
-
const
|
|
19
|
+
const da_api = require('./docassemble/docassemble_api_interface');
|
|
20
20
|
const wrapPromiseWithTimeout = require('./cucumber_8_shim');
|
|
21
21
|
const reports = require(`./utils/reports`);
|
|
22
22
|
|
|
@@ -339,7 +339,7 @@ module.exports = {
|
|
|
339
339
|
// This code assumes a reasonable response time would be n seconds if the
|
|
340
340
|
// server is up and that a server reload/restart won't take less than n seconds.
|
|
341
341
|
// Also, it's non-blocking, so it doesn't slow down tests
|
|
342
|
-
let is_up = await
|
|
342
|
+
let is_up = await da_api.is_server_responding({ timeout: scope.server_check_interval_ms });
|
|
343
343
|
// Add status to the beginning of the list to make truncating easier
|
|
344
344
|
scope.server_statuses.unshift( is_up );
|
|
345
345
|
|
|
@@ -2996,10 +2996,20 @@ module.exports = {
|
|
|
2996
2996
|
// Save API key to clean up interviews later. Nice to have, not critical
|
|
2997
2997
|
if ( api_key_secret_name ) {
|
|
2998
2998
|
let api_key = process.env[ api_key_secret_name ];
|
|
2999
|
-
let api_key_msg = `The
|
|
2999
|
+
let api_key_msg = `The API key in the variable "${ api_key_secret_name }" is missing. Check for a typo in your test, workflow file, GitHub secret, or server config.`
|
|
3000
3000
|
if ( api_key === undefined ) {
|
|
3001
3001
|
reports.addToReport( scope, { type: `warning`, code: `ALK0199`, value: api_key_msg });
|
|
3002
|
+
} else if ( api_key === `` ) {
|
|
3003
|
+
reports.addToReport( scope, { type: `warning`, code: `ALK0200`,
|
|
3004
|
+
value: `ALKiln found the API key in the variable "${ api_key_secret_name }", but it was empty. It had no text in it. Edit the value of the GitHub secret or server config variable called "${ api_key_secret_name }".` });
|
|
3002
3005
|
} else {
|
|
3006
|
+
let access_info = await da_api.get_api_key_access_status({ api_key });
|
|
3007
|
+
if ( !access_info.has_auth ) {
|
|
3008
|
+
reports.addToReport( scope, { type: `warning`, code: `ALK0201`,
|
|
3009
|
+
value: `The server rejected the API key in the variable "${ api_key_secret_name }". Does it exist on this server? Was it deleted somehow? You can always make a new one.` });
|
|
3010
|
+
}
|
|
3011
|
+
// Even if it doesn't have access, give it a shot anyway.
|
|
3012
|
+
// Maybe we got something wrong.
|
|
3003
3013
|
scope.scenarios.get( scope.scenario_id ).api_keys.push( api_key );
|
|
3004
3014
|
}
|
|
3005
3015
|
}
|
package/lib/steps.js
CHANGED
|
@@ -140,7 +140,7 @@ Before(async (scenario) => {
|
|
|
140
140
|
scope.scenario_id = uuidv4();
|
|
141
141
|
scope.scenarios.set( scope.scenario_id, {} );
|
|
142
142
|
scope.scenarios.get( scope.scenario_id ).interviews = {};
|
|
143
|
-
scope.scenarios.get( scope.scenario_id ).api_keys = [
|
|
143
|
+
scope.scenarios.get( scope.scenario_id ).api_keys = [];
|
|
144
144
|
scope.expected_status = null;
|
|
145
145
|
scope.expected_in_report = null;
|
|
146
146
|
scope.expected_not_in_report = null;
|
|
@@ -286,14 +286,14 @@ Given(
|
|
|
286
286
|
{ timeout: -1 },
|
|
287
287
|
async ( email, password, api_key ) => {
|
|
288
288
|
/** Uses the names of environment variables (most often GitHub SECRETs) to
|
|
289
|
-
* log into an account on the user's server. Must be
|
|
289
|
+
* log into an account on the user's server. Must be secure.
|
|
290
290
|
*
|
|
291
291
|
* Variations:
|
|
292
|
-
* I sign into the server with the email "
|
|
293
|
-
* I sign on with the email "
|
|
294
|
-
* I log in with "
|
|
295
|
-
* I sign in with the email "
|
|
296
|
-
* I sign in with "
|
|
292
|
+
* I sign into the server with the email "USER2_EMAIL" and the password "USER2_PASSWORD"
|
|
293
|
+
* I sign on with the email "USER2_EMAIL" and the password "USER2_PASSWORD"
|
|
294
|
+
* I log in with "USER2_EMAIL" and "USER2_PASSWORD"
|
|
295
|
+
* I sign in with the email "USER2_EMAIL", the password "USER2_PASSWORD", and the API key "USER2_API_KEY"
|
|
296
|
+
* I sign in with "USER2_EMAIL", "USER2_PASSWORD", "USER2_API_KEY"
|
|
297
297
|
*/
|
|
298
298
|
// `page` timeout will deal with custom timeout
|
|
299
299
|
// Couldn't test the timeout for tapping the button because there's not
|
|
@@ -1205,11 +1205,11 @@ Then(/of two interviews, I delete one __internal__/i, async () => {
|
|
|
1205
1205
|
|
|
1206
1206
|
// Check that both interviews exist on the server. 1 √ 2 √
|
|
1207
1207
|
let api_keys = scope.scenarios.get( scope.scenario_id ).api_keys;
|
|
1208
|
-
let
|
|
1209
|
-
let
|
|
1208
|
+
let visible_interviews = await da_api.get_interviews({ interviews, api_keys });
|
|
1209
|
+
let visible_keys = Object.keys( visible_interviews );
|
|
1210
1210
|
expect(
|
|
1211
|
-
|
|
1212
|
-
`2 interviews should be on the server. Instead: "${
|
|
1211
|
+
visible_keys.length,
|
|
1212
|
+
`2 interviews should be on the server. Instead: "${ visible_keys.join(', ') }"`
|
|
1213
1213
|
).to.equal( 2 );
|
|
1214
1214
|
|
|
1215
1215
|
// Delete one. 1 x 2 √
|
|
@@ -1233,24 +1233,23 @@ Then(/of two interviews, I delete one __internal__/i, async () => {
|
|
|
1233
1233
|
// In After(), the other session should get deleted
|
|
1234
1234
|
});
|
|
1235
1235
|
|
|
1236
|
-
Then(/
|
|
1237
|
-
/** Test that
|
|
1238
|
-
|
|
1239
|
-
*/
|
|
1236
|
+
Then(/I fail to delete (\d) detected interview(?:s)? and get no error __internal__/i, async ( num ) => {
|
|
1237
|
+
/** Test that there is no error when ALKiln is unable to delete an interview. */
|
|
1238
|
+
num = parseInt( num );
|
|
1240
1239
|
// Make sure we started an interview
|
|
1241
1240
|
let interviews = scope.scenarios.get( scope.scenario_id ).interviews;
|
|
1242
1241
|
expect(
|
|
1243
1242
|
Object.keys( interviews ).length,
|
|
1244
|
-
`The test should have saved
|
|
1245
|
-
).to.equal(
|
|
1243
|
+
`The test should have saved ${ num } interview session(s)`
|
|
1244
|
+
).to.equal( num );
|
|
1246
1245
|
|
|
1247
1246
|
// There should be no error about an unauthorized user
|
|
1248
1247
|
let api_keys = scope.scenarios.get( scope.scenario_id ).api_keys;
|
|
1249
|
-
let
|
|
1250
|
-
let
|
|
1248
|
+
let visible_interviews = await da_api.get_interviews({ interviews, api_keys });
|
|
1249
|
+
let visible_keys = Object.keys( visible_interviews );
|
|
1251
1250
|
expect(
|
|
1252
|
-
|
|
1253
|
-
`
|
|
1251
|
+
visible_keys.length,
|
|
1252
|
+
`User should detect 0 interviews on the server. Instead: "${ visible_keys.join(', ') }"`
|
|
1254
1253
|
).to.equal( 0 );
|
|
1255
1254
|
|
|
1256
1255
|
// Deleting with an anonymous user should fail silently
|
|
@@ -1475,14 +1474,15 @@ After(async function(scenario) {
|
|
|
1475
1474
|
let interviews = scope.scenarios.get( scope.scenario_id ).interviews;
|
|
1476
1475
|
let api_keys = scope.scenarios.get( scope.scenario_id ).api_keys;
|
|
1477
1476
|
await da_api.quietly_try_to_delete_interviews({ interviews, api_keys });
|
|
1478
|
-
let
|
|
1479
|
-
let
|
|
1477
|
+
let visible_interviews = await da_api.get_interviews({ interviews, api_keys });
|
|
1478
|
+
let visible_keys = Object.keys( visible_interviews );
|
|
1480
1479
|
// Deleting interviews is nice, but not non-critical. Don't bother the
|
|
1481
1480
|
// user with it. Don't want to cover up a more meaningful failure (like
|
|
1482
1481
|
// going to the wrong file). If it becomes a problem we can track it down later.
|
|
1483
|
-
if (
|
|
1482
|
+
if ( visible_keys.length > 0 ) {
|
|
1483
|
+
// Can an API key ever see an interview that it can't delete?
|
|
1484
1484
|
log.debug({ type: `internal warning`, code: `ALK0197`,
|
|
1485
|
-
pre:
|
|
1485
|
+
pre: `The API key can see ${ visible_keys.length } interviews that were not deleted: ${ visible_keys.join( ', ' ) }`
|
|
1486
1486
|
});
|
|
1487
1487
|
}
|
|
1488
1488
|
} catch ( error ) {
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@ fi
|
|
|
16
16
|
# The grepped files will include the list of all the codes that have been
|
|
17
17
|
# removed and are no longer used. Syntax used works with GitHub cli ([[:digit:]])
|
|
18
18
|
# https://stackoverflow.com/a/6901221
|
|
19
|
-
lines=$(grep -roh --exclude="tests/log_codes/check_codes.sh" --exclude="debug_log.txt" --exclude="cucumber-report.txt" --exclude-dir="node_modules" --exclude-dir='alkiln-*' --exclude-dir='_alkiln*' 'ALK[[:digit:]][[:digit:]][[:digit:]][[:digit:]]' "$directory")
|
|
19
|
+
lines=$(grep -roh --exclude="tests/log_codes/check_codes.sh" --exclude="debug_log.txt" --exclude="cucumber-report.txt" --exclude-dir="./docassemble" --exclude-dir="node_modules" --exclude-dir='alkiln-*' --exclude-dir='_alkiln*' 'ALK[[:digit:]][[:digit:]][[:digit:]][[:digit:]]' "$directory")
|
|
20
20
|
sorted=$(echo "$lines" | sort -n)
|
|
21
21
|
|
|
22
22
|
|