Skip to content

Commit 26d3fc0

Browse files
authored
Merge pull request #3665 from kbase/develop
Merge to main for 5.4.2. release
2 parents 419a1d7 + 22db152 commit 26d3fc0

21 files changed

+4800
-4073
lines changed

.github/dependabot.yml

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,33 @@
11
version: 2
22
updates:
3-
- package-ecosystem: pip
3+
- package-ecosystem: "pip"
44
directory: "/src"
55
schedule:
6-
interval: monthly
7-
time: '11:00'
6+
interval: "monthly"
87
groups:
9-
python-dependencies:
8+
pip:
109
patterns:
1110
- "*"
1211
open-pull-requests-limit: 20
1312
ignore:
1413
- dependency-name: "notebook"
15-
versions: '>= 7.0.0'
16-
- package-ecosystem: npm
14+
versions: ">= 7.0.0"
15+
- package-ecosystem: "npm"
1716
directory: "/"
1817
schedule:
19-
interval: monthly
20-
time: '11:00'
18+
interval: "monthly"
2119
groups:
22-
npm-dependencies:
20+
npm:
2321
patterns:
24-
"*"
22+
- "*"
2523
open-pull-requests-limit: 20
26-
- package-ecosystem: docker
24+
- package-ecosystem: "docker"
2725
directory: "/"
2826
schedule:
29-
interval: monthly
30-
time: '11:00'
27+
interval: "monthly"
3128
open-pull-requests-limit: 20
32-
- package-ecosystem: github-actions
29+
- package-ecosystem: "github-actions"
3330
directory: "/.github"
3431
schedule:
35-
interval: monthly
36-
time: '11:00'
32+
interval: "monthly"
3733
open-pull-requests-limit: 20

RELEASE_NOTES.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,86 @@ The Narrative Interface allows users to craft KBase Narratives using a combinati
44

55
This is built on the Jupyter Notebook v6.5.6 and IPython 8.26.0 (more notes will follow).
66

7+
## Version 5.4.2
8+
- UIP-52 - repair integration tests, get WebDriverIO up to date
9+
- PTV-1913 - fix potential authentication issues affecting report viewing and downloads in narratives
10+
11+
### Dependency Changes
12+
- Python dependency updates
13+
- coverage 7.5.3 -> 7.6.1
14+
- pytest 8.2.2 -> 8.3.2
15+
- pytest-recording 0.13.1 -> 0.13.2
16+
- ruff 0.5.5 -> 0.6.3
17+
18+
- certifi 2027.7.4 -> 2024.8.30
19+
- cryptography 42.0.8 -> 43.0.0
20+
- idna 3.7 -> 3.8
21+
- jsonschema 4.16.0 -> 4.23.0
22+
- markdown 3.4.1 -> 3.7
23+
- markupsafe 2.1.4 -> 2.1.5
24+
- pycurl 7.45.1 -> 7.45.3
25+
- pyopenssl 24.1.0 -> 24.2.1
26+
- setuptools 71.1.0 -> 74.0.0
27+
- terminado 0.18.0 -> 0.18.1
28+
- bokeh 3.5.1 -> 3.5.2
29+
- ete3 3.1.2 -> 3.1.3
30+
- numpy 2.0.1 -> 2.1.0
31+
- plotly 5.23.0 -> 5.24.0
32+
- scipy 1.14.0 -> 1.14.1
33+
- sympy 1.13.1 -> 1.13.2
34+
35+
- ipython 8.26.0 -> 8.27.0
36+
- ipywidgets 7.7.1 -> 8.1.5
37+
- notebook 6.5.6 -> 6.5.7
38+
- pymongo 4.7.3 -> 4.8.0
39+
- pyyaml 6.0.1 -> 6.0.2
40+
- scikit-learn 1.5.0 -> 1.5.1
41+
42+
- Javascript Dependency Changes
43+
- wdio-chromedriver-service -- Deprecated and removed, functionality is now built-in to WebdriverIO
44+
45+
- @babel/traverse 7.24.7 -> 7.25.6
46+
- @eslint/js 9.6.0 -> 9.9.1
47+
- @wdio/browserstack-service 8.38.2 -> 9.0.9
48+
- @wdio/cli 8.38.2 -> 9.0.9
49+
- @wdio/local-runner 8.38.2 -> 9.0.9
50+
- @wdio/mocha-framwork 8.39.0 -> 9.0.8
51+
- @wdio/spec-reporter 8.38.2 -> 9.0.8
52+
- autoprefixer 10.4.19 -> 10.4.20
53+
- axios 1.7.2 -> 1.7.7
54+
- chromedriver 128.0.0 -> 128.0.1
55+
- cssnano 7.0.2 -> 7.0.6
56+
- eslint 9.4.0 -> 9.9.1
57+
- expect-webdriverio 3.6.0 -> 5.0.2
58+
- glob 10.4.1 -> 11.0.0
59+
- globals 15.6.0 -> 15.9.0
60+
- grunt-cli 1.4.3 -> 1.5.0
61+
- grunt-stylelint 0.20.0 -> 0.20.1
62+
- husky 9.0.11 -> 9.1.5
63+
- jasmine-core 5.1.2 -> 5.2.0
64+
- jquery-migrate 1.4.1 -> 3.5.2
65+
- karma 6.4.3 -> 6.4.4
66+
- lint-staged 15.2.6 -> 15.2.10
67+
- postcss 8.4.39 -> 8.4.45
68+
- prettier 3.3.2 -> 3.3.3
69+
- puppeteer 23.2.1 -> 23.3.0
70+
- requirejs 2.3.6 -> 2.3.7
71+
- sass 1.77.5 -> 1.78.0
72+
- selenium-standalone 9.5.0 -> 10.0.0
73+
- selenium-webdriver 4.22.0 -> 4.24.0
74+
- stylelint 16.6.1 -> 16.9.0
75+
- stylelint-config-recommended 14.0.0 -> 14.0.1
76+
- stylelint-config-sass-guidelines 11.1.0 -> 12.0.0
77+
- stylelint-config-standard 36.0.0 -> 36.0.1
78+
- terser 5.31.1 -> 5.31.6
79+
- webdriverio 8.38.2 -> 9.0.9
80+
81+
- dompurify 2.5.5 -> 3.1.6
82+
- follow-redirects 1.15.6 -> 1.15.9
83+
- jquery-ui 1.13.2 -> 1.14.0
84+
- plotly.js-dist-min 2.33.0 -> 2.35.0
85+
- underscore 1.13.6 -> 1.13.7
86+
787
## Version 5.4.1
888
- UIP-51 fix issue where JSON and STAGING download apps aren't getting properly instantiated with object inputs.
989

eslint.config.mjs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ export default [{
4141
},
4242

4343
rules: {
44-
strict: ["error", "function"],
45-
4644
"no-console": ["error", {
4745
allow: ["warn", "error"],
4846
}],

kbase-extension/static/kbase/custom/custom.js

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,6 @@ define([
135135
NarrativeRuntime,
136136
html
137137
) => {
138-
'use strict';
139-
140138
// Handlebars global configuration. Since these changes affect all usage of handlebars
141139
// in this app, they should be performed just once.
142140
Handlebars.registerHelper('numeral', (value, format, defaultValue, options) => {
@@ -145,19 +143,8 @@ define([
145143
options = defaultValue;
146144
defaultValue = undefined;
147145
}
148-
let missing = false;
149-
if (typeof value === 'string') {
150-
if (value.trim().length === 0) {
151-
missing = true;
152-
}
153-
} else if (typeof value !== 'number') {
154-
missing = true;
155-
}
156146
const numeralValue = numeral(value);
157-
if (isNaN(numeralValue)) {
158-
missing = true;
159-
}
160-
if (missing) {
147+
if (numeralValue.value() === null) {
161148
return defaultValue || 'n/a';
162149
}
163150
try {

kbase-extension/static/kbase/js/api/auth.js

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ define(['bluebird', 'jquery', 'narrativeConfig'], (Promise, $, Config) => {
2424
},
2525
};
2626

27-
const TOKEN_AGE = 14; // days
27+
const DEFAULT_TOKEN_LIFE = 14 * 24 * 60 * 60 * 1000; // millis
2828

2929
/**
3030
* Meant for managing auth or session cookies (mainly auth cookies as set by
@@ -33,10 +33,10 @@ define(['bluebird', 'jquery', 'narrativeConfig'], (Promise, $, Config) => {
3333
* If it's missing name or value, does nothing.
3434
* Default expiration time is 14 days.
3535
* domain, expires, and max-age are optional
36-
* expires is expected to be in days
37-
* auto set fields are:
36+
* expires is expected to be the timestamp (ms since epoch) it will expire
37+
* default fields are:
3838
* - path = '/'
39-
* - expires = TOKEN_AGE (default 14) days
39+
* - expires = now + 14 days
4040
* @param {object} cookie
4141
* - has the cookie keys: name, value, path, expires, max-age, domain
4242
* - adds secure=true, samesite=Lax for KBase use.
@@ -50,7 +50,7 @@ define(['bluebird', 'jquery', 'narrativeConfig'], (Promise, $, Config) => {
5050
const name = encodeURIComponent(cookie.name);
5151
const value = encodeURIComponent(cookie.value || '');
5252
const props = {
53-
expires: TOKEN_AGE, // gets translated to GMT string
53+
expires: Date.now() + DEFAULT_TOKEN_LIFE, // gets translated to GMT string
5454
path: '/',
5555
samesite: 'Lax',
5656
};
@@ -66,14 +66,8 @@ define(['bluebird', 'jquery', 'narrativeConfig'], (Promise, $, Config) => {
6666
if (cookie.domain) {
6767
props.domain = cookie.domain;
6868
}
69-
props['max-age'] = 86400 * props.expires;
70-
if (props.expires === 0) {
71-
props.expires = new Date(0).toUTCString();
72-
} else {
73-
props.expires = new Date(
74-
new Date().getTime() + 86400000 * props.expires
75-
).toUTCString();
76-
}
69+
props['max-age'] = parseInt((props.expires - Date.now()) / 1000);
70+
props.expires = new Date(props.expires).toUTCString();
7771

7872
const fields = Object.keys(props).map((key) => {
7973
return `${key}=${props[key]}`;
@@ -85,7 +79,7 @@ define(['bluebird', 'jquery', 'narrativeConfig'], (Promise, $, Config) => {
8579

8680
const propStr = fields.join(';');
8781

88-
const newCookie = `${name}=${value}; ${propStr}`;
82+
const newCookie = `${name}=${value};${propStr}`;
8983
document.cookie = newCookie;
9084
}
9185

@@ -161,22 +155,34 @@ define(['bluebird', 'jquery', 'narrativeConfig'], (Promise, $, Config) => {
161155
return getCookie(cookieConfig.auth.name);
162156
}
163157

164-
/* Sets the given auth token into the browser's cookie.
165-
* Does nothing if the token is null.
158+
/**
159+
* Returns a Promise that ets the given auth token into the
160+
* browser's cookie, as configured. The cookie has the
161+
* same lifespan as the token.
162+
* If the token is null or expired, this does nothing.
163+
* If there's an error in looking up the token, this throws
164+
* an error.
165+
* @param {string} token
166+
* @returns
166167
*/
167-
function setAuthToken(token) {
168+
async function setAuthToken(token) {
169+
const tokenInfo = await getTokenInfo(token);
170+
// if it's expired, don't set (actually should've thrown
171+
// here, and get caught by the caller, but check anyway)
172+
if (tokenInfo.expires - Date.now() <= 0) {
173+
return;
174+
}
168175
const deployEnv = Config.get('environment');
169176

170177
function setToken(config) {
171178
// Honor cookie host whitelist if present.
172-
if (config.enableIn) {
173-
if (config.enableIn.indexOf(deployEnv) === -1) {
174-
return;
175-
}
179+
if (config.enableIn && !config.enableIn.includes(deployEnv)) {
180+
return;
176181
}
177182
const cookieField = {
178183
name: config.name,
179184
value: token,
185+
expires: tokenInfo.expires,
180186
};
181187
if (config.domain) {
182188
cookieField.domain = config.domain;

kbase-extension/static/kbase/js/narrativeLogin.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ define([
1515
'util/bootstrapDialog',
1616
], ($, Promise, kbapi, JupyterUtils, Config, Auth, UserMenu, BootstrapDialog) => {
1717
'use strict';
18+
1819
const baseUrl = JupyterUtils.get_body_data('baseUrl');
1920
const authClient = Auth.make({ url: Config.url('auth') });
2021
let sessionInfo = null;
@@ -98,10 +99,8 @@ define([
9899
function showNotLoggedInDialog() {
99100
const message = `
100101
<p>You are logged out (or your session has expired).</p>
101-
<p>You will be redirected to the sign in page after closing this, or ${
102-
AUTO_LOGOUT_DELAY / 1000
103-
} seconds,
104-
whichever comes first.</p>
102+
<p>You will be redirected to the sign in page after closing this, or
103+
${AUTO_LOGOUT_DELAY / 1000} seconds, whichever comes first.</p>
105104
`;
106105
const dialog = new BootstrapDialog({
107106
title: 'Logged Out',
@@ -304,10 +303,14 @@ define([
304303
*/
305304
clearTokenCheckTimers();
306305
const sessionToken = authClient.getAuthToken();
307-
return Promise.all([
308-
authClient.getTokenInfo(sessionToken),
309-
authClient.getUserProfile(sessionToken),
310-
])
306+
return authClient
307+
.setAuthToken(sessionToken)
308+
.then(() =>
309+
Promise.all([
310+
authClient.getTokenInfo(sessionToken),
311+
authClient.getUserProfile(sessionToken),
312+
])
313+
)
311314
.then(([tokenInfo, accountInfo]) => {
312315
sessionInfo = tokenInfo;
313316
this.sessionInfo = tokenInfo;

0 commit comments

Comments
 (0)