Skip to content

Commit

Permalink
Address inaccurate calculation of session expiration time (jupyter-se…
Browse files Browse the repository at this point in the history
…rver#408)

* fix bug to compute login time correctly

* Bump to 0.21.2

* address code review
  • Loading branch information
Zsailer authored and GitHub Enterprise committed Jun 10, 2022
1 parent 6309798 commit 376e054
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 29 deletions.
2 changes: 1 addition & 1 deletion data_studio_jupyter_extensions/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.21.1" # pragma: no cover
__version__ = "0.21.2" # pragma: no cover
26 changes: 11 additions & 15 deletions data_studio_jupyter_extensions/auth/login.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import time
import uuid

import tornado
Expand Down Expand Up @@ -52,22 +51,19 @@ def post(self):
self, self.datastudio_secure_cookie_name.lower(), data_studio_jwt
)
cookie_options = self.settings.get("cookie_options", {})
cookie_expiry_days = cookie_options["expires_days"]
if hasattr(self.authenticator, "get_expiration"):
exp = self.authenticator.get_expiration(data_studio_jwt)
exp_sec = exp - time.time()
cookie_expiry_days = exp_sec / 60 / 60 / 24
# Expiration date from epoch (converted from seconds to milliseconds)
exp = self.authenticator.get_expiration(data_studio_jwt) * 1000

# This sets an insecure cookie. This is required to track if session expired through javascript.
# No secure information should be set
self.set_cookie(
self.datastudio_cookie_name,
str(cookie_expiry_days),
domain=self.request.host_name,
expires_days=cookie_expiry_days,
httponly=False,
path=self.base_url,
)
# This sets an insecure cookie. This is required to track if session expired through javascript.
# No secure information should be set
self.set_cookie(
self.datastudio_cookie_name,
str(exp),
domain=self.request.host_name,
httponly=False,
path=self.base_url,
)
# Configure the notebook service to use the JWT.
if not self.nbservice_client.local_mode:
self.nbservice_client.request_token = data_studio_jwt
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ testpaths = [
]

[tool.tbump.version]
current = "0.21.1"
current = "0.21.2"
regex = '''
(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)
((?P<channel>a|b|rc|.dev)(?P<release>\d+))?
Expand Down
49 changes: 39 additions & 10 deletions src/sessionexp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
JupyterFrontEndPlugin
} from '@jupyterlab/application';

import { showDialog } from '@jupyterlab/apputils';
import { showDialog, Dialog } from '@jupyterlab/apputils';

import { DocumentWidget } from '@jupyterlab/docregistry';

Expand All @@ -17,7 +17,16 @@ import { PageConfig, URLExt } from '@jupyterlab/coreutils';
* A session expiration body
*/
export const SessionExpBody = () => {
return <>{'Session is expiring, click OK to refresh login'}</>;
return (
<div>
<p>
Your session is about to expire. We saved your notebooks, so your work
won't be lost.
</p>
<br></br>
<p>Please re-login to continue using Data Studio Notebooks.</p>
</div>
);
};

function readCookie(name: string) {
Expand Down Expand Up @@ -56,6 +65,7 @@ export const SessionExpPlugin: JupyterFrontEndPlugin<void> = {

// Get the expiration from the login cookie.
let obj = readCookie(loginCookie);

let expires: number;
if (!obj) {
console.log(`Login cookie ${loginCookie} not found`);
Expand All @@ -64,13 +74,26 @@ export const SessionExpPlugin: JupyterFrontEndPlugin<void> = {
expires = parseFloat(obj);
}

// Set the callback time to "sessionWarningMinutes" before expiration, all times are in msec.
let callbackTime =
expires * 24 * 60 * 60 * 1000 - sessionWarningMinutes * 60 * 1000;
// Time since Epoch (in milliseconds).
let currentTime = Date.now();
let secondsUntilExpiration = expires - currentTime;
let twentyMinutesAsMilliseconds = sessionWarningMinutes * 60 * 1000;
let reloginTimeout = secondsUntilExpiration - twentyMinutesAsMilliseconds;
let reloginMinutes = reloginTimeout / 1000 / 60;
let reloginSeconds = ((reloginTimeout / 1000 / 60) % 1) * 60;

// Write a human-readable statement about the expiration time to the console.
console.log(
'This Data Studio Notebooks Session expires in: ' +
Math.trunc(reloginMinutes) +
' minutes and ' +
Math.round(reloginSeconds) +
' seconds'
);

callbackTime = Math.max(callbackTime, 1000);
reloginTimeout = Math.max(reloginTimeout, 1000);
if (PageConfig.getOption('sessionWarningOverride') === 'true') {
callbackTime = 0;
reloginTimeout = 0;
}

setTimeout(async () => {
Expand All @@ -87,8 +110,14 @@ export const SessionExpPlugin: JupyterFrontEndPlugin<void> = {

// Prompt the user to login.
const result = await showDialog({
title: 'Session Expiring',
body: SessionExpBody()
title: 'Session is expiring.',
body: SessionExpBody(),
buttons: [
Dialog.okButton({
label: 'Re-login',
displayType: 'default'
})
]
});
if (!result.button.accept) {
return;
Expand All @@ -99,6 +128,6 @@ export const SessionExpPlugin: JupyterFrontEndPlugin<void> = {
await fetch(URLExt.join(baseUrl, 'logout'));
const url = URLExt.join(baseUrl, 'login');
window.location.replace(url);
}, callbackTime);
}, reloginTimeout);
}
};
2 changes: 1 addition & 1 deletion src/status.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { ISessionContext, ReactWidget } from '@jupyterlab/apputils';
import { EventListener } from './eventlistener';

// This is managed by tbump config in pyproject.toml
const VERSION = '0.21.1';
const VERSION = '0.21.2';

// Define the error states
// https://github.pie.apple.com/pie-data-studio/notebook-service/blob/761d63604966db5918d2e491c0f89cce454b7f67/app/com/apple/datastudio/model/ResourceState.scala#L20
Expand Down
2 changes: 1 addition & 1 deletion version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.21.1
0.21.2

0 comments on commit 376e054

Please sign in to comment.