@deephaven/auth-plugins 0.43.0 → 0.44.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/dist/AuthHandlerTypes.js +3 -0
- package/dist/AuthHandlerTypes.js.map +1 -0
- package/dist/AuthPlugin.js +19 -0
- package/dist/AuthPlugin.js.map +1 -0
- package/dist/AuthPluginAnonymous.js +32 -0
- package/dist/AuthPluginAnonymous.js.map +1 -0
- package/dist/AuthPluginBase.js +71 -0
- package/dist/AuthPluginBase.js.map +1 -0
- package/dist/AuthPluginParent.js +52 -0
- package/dist/AuthPluginParent.js.map +1 -0
- package/dist/AuthPluginPsk.js +209 -0
- package/dist/AuthPluginPsk.js.map +1 -0
- package/dist/AuthenticationError.js +12 -0
- package/dist/AuthenticationError.js.map +1 -0
- package/dist/Login.css +74 -0
- package/dist/Login.css.map +1 -0
- package/dist/Login.js +23 -0
- package/dist/Login.js.map +1 -0
- package/dist/LoginForm.css +57 -0
- package/dist/LoginForm.css.map +1 -0
- package/dist/LoginForm.js +48 -0
- package/dist/LoginForm.js.map +1 -0
- package/dist/UserContexts.js +5 -0
- package/dist/UserContexts.js.map +1 -0
- package/dist/UserUtils.js +70 -0
- package/dist/UserUtils.js.map +1 -0
- package/dist/declarations.d.js +2 -0
- package/dist/declarations.d.js.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/package.json +10 -10
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthHandlerTypes.js","names":["AUTH_HANDLER_TYPE_ANONYMOUS","AUTH_HANDLER_TYPE_PSK"],"sources":["../src/AuthHandlerTypes.ts"],"sourcesContent":["export const AUTH_HANDLER_TYPE_ANONYMOUS =\n 'io.deephaven.auth.AnonymousAuthenticationHandler';\n\nexport const AUTH_HANDLER_TYPE_PSK =\n 'io.deephaven.authentication.psk.PskAuthenticationHandler';\n"],"mappings":"AAAA,OAAO,IAAMA,2BAA2B,GACtC,kDAAkD;AAEpD,OAAO,IAAMC,qBAAqB,GAChC,0DAA0D"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map from auth config keys to their values
|
|
3
|
+
* E.g. Map { AuthHandlers → "io.deephaven.auth.AnonymousAuthenticationHandler" }
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Props for the auth plugin component to render
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Whether the auth plugin is available given the current configuration
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export function isAuthPlugin(plugin) {
|
|
15
|
+
if (plugin == null) return false;
|
|
16
|
+
var authPlugin = plugin;
|
|
17
|
+
return authPlugin.Component !== undefined && typeof authPlugin.isAvailable === 'function';
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=AuthPlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthPlugin.js","names":["isAuthPlugin","plugin","authPlugin","Component","undefined","isAvailable"],"sources":["../src/AuthPlugin.ts"],"sourcesContent":["import React from 'react';\n\n/**\n * Map from auth config keys to their values\n * E.g. Map { AuthHandlers → \"io.deephaven.auth.AnonymousAuthenticationHandler\" }\n */\nexport type AuthConfigMap = Map<string, string>;\n\n/**\n * Props for the auth plugin component to render\n */\nexport type AuthPluginProps = {\n /** Map from config keys to their values */\n authConfigValues: AuthConfigMap;\n\n /**\n * The children to render after authentication is completed.\n */\n children: React.ReactNode;\n};\n\nexport type AuthPluginComponent = React.FunctionComponent<AuthPluginProps>;\n\n/**\n * Whether the auth plugin is available given the current configuration\n */\nexport type AuthPluginIsAvailableFunction = (\n authHandlers: string[],\n authConfig: AuthConfigMap\n) => boolean;\n\nexport type AuthPlugin = {\n Component: AuthPluginComponent;\n isAvailable: AuthPluginIsAvailableFunction;\n};\n\nexport function isAuthPlugin(plugin?: unknown): plugin is AuthPlugin {\n if (plugin == null) return false;\n const authPlugin = plugin as AuthPlugin;\n return (\n authPlugin.Component !== undefined &&\n typeof authPlugin.isAvailable === 'function'\n );\n}\n"],"mappings":"AAEA;AACA;AACA;AACA;;AAGA;AACA;AACA;;AAaA;AACA;AACA;;AAWA,OAAO,SAASA,YAAY,CAACC,MAAgB,EAAwB;EACnE,IAAIA,MAAM,IAAI,IAAI,EAAE,OAAO,KAAK;EAChC,IAAMC,UAAU,GAAGD,MAAoB;EACvC,OACEC,UAAU,CAACC,SAAS,KAAKC,SAAS,IAClC,OAAOF,UAAU,CAACG,WAAW,KAAK,UAAU;AAEhD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
|
+
import { useApi } from '@deephaven/jsapi-bootstrap';
|
|
3
|
+
import { AUTH_HANDLER_TYPE_ANONYMOUS } from "./AuthHandlerTypes.js";
|
|
4
|
+
import AuthPluginBase from "./AuthPluginBase.js";
|
|
5
|
+
import { UserPermissionsOverrideContext } from "./UserContexts.js";
|
|
6
|
+
var permissionsOverrides = {
|
|
7
|
+
canLogout: false
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* AuthPlugin that tries to login anonymously. Fails if anonymous login fails
|
|
12
|
+
*/
|
|
13
|
+
function Component(_ref) {
|
|
14
|
+
var {
|
|
15
|
+
children
|
|
16
|
+
} = _ref;
|
|
17
|
+
var dh = useApi();
|
|
18
|
+
var getLoginOptions = useCallback(() => ({
|
|
19
|
+
type: dh.CoreClient.LOGIN_TYPE_ANONYMOUS
|
|
20
|
+
}), [dh]);
|
|
21
|
+
return /*#__PURE__*/React.createElement(AuthPluginBase, {
|
|
22
|
+
getLoginOptions: getLoginOptions
|
|
23
|
+
}, /*#__PURE__*/React.createElement(UserPermissionsOverrideContext.Provider, {
|
|
24
|
+
value: permissionsOverrides
|
|
25
|
+
}, children));
|
|
26
|
+
}
|
|
27
|
+
var AuthPluginAnonymous = {
|
|
28
|
+
Component,
|
|
29
|
+
isAvailable: authHandlers => authHandlers.includes(AUTH_HANDLER_TYPE_ANONYMOUS)
|
|
30
|
+
};
|
|
31
|
+
export default AuthPluginAnonymous;
|
|
32
|
+
//# sourceMappingURL=AuthPluginAnonymous.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthPluginAnonymous.js","names":["React","useCallback","useApi","AUTH_HANDLER_TYPE_ANONYMOUS","AuthPluginBase","UserPermissionsOverrideContext","permissionsOverrides","canLogout","Component","children","dh","getLoginOptions","type","CoreClient","LOGIN_TYPE_ANONYMOUS","AuthPluginAnonymous","isAvailable","authHandlers","includes"],"sources":["../src/AuthPluginAnonymous.tsx"],"sourcesContent":["import React, { useCallback } from 'react';\nimport { useApi } from '@deephaven/jsapi-bootstrap';\nimport { AUTH_HANDLER_TYPE_ANONYMOUS } from './AuthHandlerTypes';\nimport { AuthPlugin, AuthPluginProps } from './AuthPlugin';\nimport AuthPluginBase from './AuthPluginBase';\nimport {\n UserPermissionsOverride,\n UserPermissionsOverrideContext,\n} from './UserContexts';\n\nconst permissionsOverrides: UserPermissionsOverride = { canLogout: false };\n\n/**\n * AuthPlugin that tries to login anonymously. Fails if anonymous login fails\n */\nfunction Component({ children }: AuthPluginProps): JSX.Element {\n const dh = useApi();\n\n const getLoginOptions = useCallback(\n () => ({ type: dh.CoreClient.LOGIN_TYPE_ANONYMOUS }),\n [dh]\n );\n\n return (\n <AuthPluginBase getLoginOptions={getLoginOptions}>\n <UserPermissionsOverrideContext.Provider value={permissionsOverrides}>\n {children}\n </UserPermissionsOverrideContext.Provider>\n </AuthPluginBase>\n );\n}\n\nconst AuthPluginAnonymous: AuthPlugin = {\n Component,\n isAvailable: authHandlers =>\n authHandlers.includes(AUTH_HANDLER_TYPE_ANONYMOUS),\n};\n\nexport default AuthPluginAnonymous;\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,WAAW,QAAQ,OAAO;AAC1C,SAASC,MAAM,QAAQ,4BAA4B;AAAC,SAC3CC,2BAA2B;AAAA,OAE7BC,cAAc;AAAA,SAGnBC,8BAA8B;AAGhC,IAAMC,oBAA6C,GAAG;EAAEC,SAAS,EAAE;AAAM,CAAC;;AAE1E;AACA;AACA;AACA,SAASC,SAAS,OAA6C;EAAA,IAA5C;IAAEC;EAA0B,CAAC;EAC9C,IAAMC,EAAE,GAAGR,MAAM,EAAE;EAEnB,IAAMS,eAAe,GAAGV,WAAW,CACjC,OAAO;IAAEW,IAAI,EAAEF,EAAE,CAACG,UAAU,CAACC;EAAqB,CAAC,CAAC,EACpD,CAACJ,EAAE,CAAC,CACL;EAED,oBACE,oBAAC,cAAc;IAAC,eAAe,EAAEC;EAAgB,gBAC/C,oBAAC,8BAA8B,CAAC,QAAQ;IAAC,KAAK,EAAEL;EAAqB,GAClEG,QAAQ,CAC+B,CAC3B;AAErB;AAEA,IAAMM,mBAA+B,GAAG;EACtCP,SAAS;EACTQ,WAAW,EAAEC,YAAY,IACvBA,YAAY,CAACC,QAAQ,CAACf,2BAA2B;AACrD,CAAC;AAED,eAAeY,mBAAmB"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
2
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
3
|
+
import React, { useEffect, useState } from 'react';
|
|
4
|
+
import { LoadingOverlay } from '@deephaven/components';
|
|
5
|
+
import { useClient } from '@deephaven/jsapi-bootstrap';
|
|
6
|
+
import Log from '@deephaven/log';
|
|
7
|
+
import { CanceledPromiseError, getErrorMessage } from '@deephaven/utils';
|
|
8
|
+
import AuthenticationError from "./AuthenticationError.js";
|
|
9
|
+
var log = Log.module('AuthPluginBase');
|
|
10
|
+
/**
|
|
11
|
+
* Base AuthPlugin that gets passed a function for retrieving the login options, and then attempting to login with them.
|
|
12
|
+
* @param getLoginOptions Function that returns a promise for the login options
|
|
13
|
+
*/
|
|
14
|
+
function AuthPluginBase(_ref) {
|
|
15
|
+
var {
|
|
16
|
+
children,
|
|
17
|
+
getLoginOptions
|
|
18
|
+
} = _ref;
|
|
19
|
+
var client = useClient();
|
|
20
|
+
var [error, setError] = useState();
|
|
21
|
+
var [isLoggedIn, setIsLoggedIn] = useState(false);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
var isCanceled = false;
|
|
24
|
+
function verifyNotCanceled() {
|
|
25
|
+
if (isCanceled) {
|
|
26
|
+
throw new CanceledPromiseError('Login canceled.');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function login() {
|
|
30
|
+
return _login.apply(this, arguments);
|
|
31
|
+
}
|
|
32
|
+
function _login() {
|
|
33
|
+
_login = _asyncToGenerator(function* () {
|
|
34
|
+
try {
|
|
35
|
+
var loginOptions = yield getLoginOptions();
|
|
36
|
+
verifyNotCanceled();
|
|
37
|
+
log.info('Logging in...');
|
|
38
|
+
yield client.login(loginOptions);
|
|
39
|
+
verifyNotCanceled();
|
|
40
|
+
setIsLoggedIn(true);
|
|
41
|
+
} catch (e) {
|
|
42
|
+
if (!isCanceled) {
|
|
43
|
+
var _getErrorMessage;
|
|
44
|
+
log.error('Unable to login:', e);
|
|
45
|
+
var message = (_getErrorMessage = getErrorMessage(e)) !== null && _getErrorMessage !== void 0 ? _getErrorMessage : 'Unable to login. Verify credentials.';
|
|
46
|
+
setError(new AuthenticationError(message));
|
|
47
|
+
setIsLoggedIn(false);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return _login.apply(this, arguments);
|
|
52
|
+
}
|
|
53
|
+
login();
|
|
54
|
+
return () => {
|
|
55
|
+
isCanceled = true;
|
|
56
|
+
};
|
|
57
|
+
}, [client, getLoginOptions]);
|
|
58
|
+
if (!isLoggedIn) {
|
|
59
|
+
return /*#__PURE__*/React.createElement(LoadingOverlay, {
|
|
60
|
+
"data-testid": "auth-base-loading",
|
|
61
|
+
isLoading: error == null,
|
|
62
|
+
isLoaded: false,
|
|
63
|
+
errorMessage: getErrorMessage(error)
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// eslint-disable-next-line react/jsx-no-useless-fragment
|
|
68
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
69
|
+
}
|
|
70
|
+
export default AuthPluginBase;
|
|
71
|
+
//# sourceMappingURL=AuthPluginBase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthPluginBase.js","names":["React","useEffect","useState","LoadingOverlay","useClient","Log","CanceledPromiseError","getErrorMessage","AuthenticationError","log","module","AuthPluginBase","children","getLoginOptions","client","error","setError","isLoggedIn","setIsLoggedIn","isCanceled","verifyNotCanceled","login","loginOptions","info","e","message"],"sources":["../src/AuthPluginBase.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react';\nimport { LoadingOverlay } from '@deephaven/components';\nimport { useClient } from '@deephaven/jsapi-bootstrap';\nimport Log from '@deephaven/log';\nimport type { LoginOptions } from '@deephaven/jsapi-types';\nimport { CanceledPromiseError, getErrorMessage } from '@deephaven/utils';\nimport AuthenticationError from './AuthenticationError';\n\nconst log = Log.module('AuthPluginBase');\n\nexport type AuthPluginBaseProps = {\n /**\n * The children to render after authentication is completed.\n */\n children: React.ReactNode;\n\n /**\n * Retrieve the login options for logging in to the client\n * @returns A promise for the login options\n */\n getLoginOptions: () => LoginOptions | Promise<LoginOptions>;\n};\n\n/**\n * Base AuthPlugin that gets passed a function for retrieving the login options, and then attempting to login with them.\n * @param getLoginOptions Function that returns a promise for the login options\n */\nfunction AuthPluginBase({\n children,\n getLoginOptions,\n}: AuthPluginBaseProps): JSX.Element {\n const client = useClient();\n const [error, setError] = useState<unknown>();\n const [isLoggedIn, setIsLoggedIn] = useState(false);\n\n useEffect(() => {\n let isCanceled = false;\n function verifyNotCanceled() {\n if (isCanceled) {\n throw new CanceledPromiseError('Login canceled.');\n }\n }\n async function login() {\n try {\n const loginOptions = await getLoginOptions();\n verifyNotCanceled();\n\n log.info('Logging in...');\n await client.login(loginOptions);\n verifyNotCanceled();\n\n setIsLoggedIn(true);\n } catch (e) {\n if (!isCanceled) {\n log.error('Unable to login:', e);\n const message =\n getErrorMessage(e) ?? 'Unable to login. Verify credentials.';\n setError(new AuthenticationError(message));\n setIsLoggedIn(false);\n }\n }\n }\n login();\n return () => {\n isCanceled = true;\n };\n }, [client, getLoginOptions]);\n\n if (!isLoggedIn) {\n return (\n <LoadingOverlay\n data-testid=\"auth-base-loading\"\n isLoading={error == null}\n isLoaded={false}\n errorMessage={getErrorMessage(error)}\n />\n );\n }\n\n // eslint-disable-next-line react/jsx-no-useless-fragment\n return <>{children}</>;\n}\n\nexport default AuthPluginBase;\n"],"mappings":";;AAAA,OAAOA,KAAK,IAAIC,SAAS,EAAEC,QAAQ,QAAQ,OAAO;AAClD,SAASC,cAAc,QAAQ,uBAAuB;AACtD,SAASC,SAAS,QAAQ,4BAA4B;AACtD,OAAOC,GAAG,MAAM,gBAAgB;AAEhC,SAASC,oBAAoB,EAAEC,eAAe,QAAQ,kBAAkB;AAAC,OAClEC,mBAAmB;AAE1B,IAAMC,GAAG,GAAGJ,GAAG,CAACK,MAAM,CAAC,gBAAgB,CAAC;AAexC;AACA;AACA;AACA;AACA,SAASC,cAAc,OAGc;EAAA,IAHb;IACtBC,QAAQ;IACRC;EACmB,CAAC;EACpB,IAAMC,MAAM,GAAGV,SAAS,EAAE;EAC1B,IAAM,CAACW,KAAK,EAAEC,QAAQ,CAAC,GAAGd,QAAQ,EAAW;EAC7C,IAAM,CAACe,UAAU,EAAEC,aAAa,CAAC,GAAGhB,QAAQ,CAAC,KAAK,CAAC;EAEnDD,SAAS,CAAC,MAAM;IACd,IAAIkB,UAAU,GAAG,KAAK;IACtB,SAASC,iBAAiB,GAAG;MAC3B,IAAID,UAAU,EAAE;QACd,MAAM,IAAIb,oBAAoB,CAAC,iBAAiB,CAAC;MACnD;IACF;IAAC,SACce,KAAK;MAAA;IAAA;IAAA;MAAA,2BAApB,aAAuB;QACrB,IAAI;UACF,IAAMC,YAAY,SAAST,eAAe,EAAE;UAC5CO,iBAAiB,EAAE;UAEnBX,GAAG,CAACc,IAAI,CAAC,eAAe,CAAC;UACzB,MAAMT,MAAM,CAACO,KAAK,CAACC,YAAY,CAAC;UAChCF,iBAAiB,EAAE;UAEnBF,aAAa,CAAC,IAAI,CAAC;QACrB,CAAC,CAAC,OAAOM,CAAC,EAAE;UACV,IAAI,CAACL,UAAU,EAAE;YAAA;YACfV,GAAG,CAACM,KAAK,CAAC,kBAAkB,EAAES,CAAC,CAAC;YAChC,IAAMC,OAAO,uBACXlB,eAAe,CAACiB,CAAC,CAAC,+DAAI,sCAAsC;YAC9DR,QAAQ,CAAC,IAAIR,mBAAmB,CAACiB,OAAO,CAAC,CAAC;YAC1CP,aAAa,CAAC,KAAK,CAAC;UACtB;QACF;MACF,CAAC;MAAA;IAAA;IACDG,KAAK,EAAE;IACP,OAAO,MAAM;MACXF,UAAU,GAAG,IAAI;IACnB,CAAC;EACH,CAAC,EAAE,CAACL,MAAM,EAAED,eAAe,CAAC,CAAC;EAE7B,IAAI,CAACI,UAAU,EAAE;IACf,oBACE,oBAAC,cAAc;MACb,eAAY,mBAAmB;MAC/B,SAAS,EAAEF,KAAK,IAAI,IAAK;MACzB,QAAQ,EAAE,KAAM;MAChB,YAAY,EAAER,eAAe,CAACQ,KAAK;IAAE,EACrC;EAEN;;EAEA;EACA,oBAAO,0CAAGH,QAAQ,CAAI;AACxB;AAEA,eAAeD,cAAc"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
2
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { getWindowParent, LOGIN_OPTIONS_REQUEST, requestParentResponse } from '@deephaven/jsapi-utils';
|
|
5
|
+
import Log from '@deephaven/log';
|
|
6
|
+
import AuthPluginBase from "./AuthPluginBase.js";
|
|
7
|
+
import { UserPermissionsOverrideContext } from "./UserContexts.js";
|
|
8
|
+
var log = Log.module('AuthPluginParent');
|
|
9
|
+
var permissionsOverrides = {
|
|
10
|
+
canLogout: false
|
|
11
|
+
};
|
|
12
|
+
function isLoginOptions(options) {
|
|
13
|
+
return options != null && typeof options.type === 'string';
|
|
14
|
+
}
|
|
15
|
+
function getLoginOptions() {
|
|
16
|
+
return _getLoginOptions.apply(this, arguments);
|
|
17
|
+
}
|
|
18
|
+
function _getLoginOptions() {
|
|
19
|
+
_getLoginOptions = _asyncToGenerator(function* () {
|
|
20
|
+
log.info('Logging in by delegating to parent window...');
|
|
21
|
+
var response = yield requestParentResponse(LOGIN_OPTIONS_REQUEST);
|
|
22
|
+
if (!isLoginOptions(response)) {
|
|
23
|
+
throw new Error("Unexpected login options response: ".concat(response));
|
|
24
|
+
}
|
|
25
|
+
return response;
|
|
26
|
+
});
|
|
27
|
+
return _getLoginOptions.apply(this, arguments);
|
|
28
|
+
}
|
|
29
|
+
function getWindowAuthProvider() {
|
|
30
|
+
var _URLSearchParams$get;
|
|
31
|
+
return (_URLSearchParams$get = new URLSearchParams(window.location.search).get('authProvider')) !== null && _URLSearchParams$get !== void 0 ? _URLSearchParams$get : '';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* AuthPlugin that tries to delegate to the parent window for authentication. Fails if there is no parent window.
|
|
36
|
+
*/
|
|
37
|
+
function Component(_ref) {
|
|
38
|
+
var {
|
|
39
|
+
children
|
|
40
|
+
} = _ref;
|
|
41
|
+
return /*#__PURE__*/React.createElement(AuthPluginBase, {
|
|
42
|
+
getLoginOptions: getLoginOptions
|
|
43
|
+
}, /*#__PURE__*/React.createElement(UserPermissionsOverrideContext.Provider, {
|
|
44
|
+
value: permissionsOverrides
|
|
45
|
+
}, children));
|
|
46
|
+
}
|
|
47
|
+
var AuthPluginParent = {
|
|
48
|
+
Component,
|
|
49
|
+
isAvailable: () => getWindowParent() != null && getWindowAuthProvider() === 'parent'
|
|
50
|
+
};
|
|
51
|
+
export default AuthPluginParent;
|
|
52
|
+
//# sourceMappingURL=AuthPluginParent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthPluginParent.js","names":["React","getWindowParent","LOGIN_OPTIONS_REQUEST","requestParentResponse","Log","AuthPluginBase","UserPermissionsOverrideContext","log","module","permissionsOverrides","canLogout","isLoginOptions","options","type","getLoginOptions","info","response","Error","getWindowAuthProvider","URLSearchParams","window","location","search","get","Component","children","AuthPluginParent","isAvailable"],"sources":["../src/AuthPluginParent.tsx"],"sourcesContent":["import React from 'react';\nimport type { LoginOptions } from '@deephaven/jsapi-types';\nimport {\n getWindowParent,\n LOGIN_OPTIONS_REQUEST,\n requestParentResponse,\n} from '@deephaven/jsapi-utils';\nimport Log from '@deephaven/log';\nimport { AuthPlugin, AuthPluginProps } from './AuthPlugin';\nimport AuthPluginBase from './AuthPluginBase';\nimport {\n UserPermissionsOverride,\n UserPermissionsOverrideContext,\n} from './UserContexts';\n\nconst log = Log.module('AuthPluginParent');\n\nconst permissionsOverrides: UserPermissionsOverride = { canLogout: false };\n\nfunction isLoginOptions(options: unknown): options is LoginOptions {\n return options != null && typeof (options as LoginOptions).type === 'string';\n}\n\nasync function getLoginOptions(): Promise<LoginOptions> {\n log.info('Logging in by delegating to parent window...');\n const response = await requestParentResponse(LOGIN_OPTIONS_REQUEST);\n if (!isLoginOptions(response)) {\n throw new Error(`Unexpected login options response: ${response}`);\n }\n return response;\n}\n\nfunction getWindowAuthProvider(): string {\n return new URLSearchParams(window.location.search).get('authProvider') ?? '';\n}\n\n/**\n * AuthPlugin that tries to delegate to the parent window for authentication. Fails if there is no parent window.\n */\nfunction Component({ children }: AuthPluginProps): JSX.Element {\n return (\n <AuthPluginBase getLoginOptions={getLoginOptions}>\n <UserPermissionsOverrideContext.Provider value={permissionsOverrides}>\n {children}\n </UserPermissionsOverrideContext.Provider>\n </AuthPluginBase>\n );\n}\n\nconst AuthPluginParent: AuthPlugin = {\n Component,\n isAvailable: () =>\n getWindowParent() != null && getWindowAuthProvider() === 'parent',\n};\n\nexport default AuthPluginParent;\n"],"mappings":";;AAAA,OAAOA,KAAK,MAAM,OAAO;AAEzB,SACEC,eAAe,EACfC,qBAAqB,EACrBC,qBAAqB,QAChB,wBAAwB;AAC/B,OAAOC,GAAG,MAAM,gBAAgB;AAAC,OAE1BC,cAAc;AAAA,SAGnBC,8BAA8B;AAGhC,IAAMC,GAAG,GAAGH,GAAG,CAACI,MAAM,CAAC,kBAAkB,CAAC;AAE1C,IAAMC,oBAA6C,GAAG;EAAEC,SAAS,EAAE;AAAM,CAAC;AAE1E,SAASC,cAAc,CAACC,OAAgB,EAA2B;EACjE,OAAOA,OAAO,IAAI,IAAI,IAAI,OAAQA,OAAO,CAAkBC,IAAI,KAAK,QAAQ;AAC9E;AAAC,SAEcC,eAAe;EAAA;AAAA;AAAA;EAAA,qCAA9B,aAAwD;IACtDP,GAAG,CAACQ,IAAI,CAAC,8CAA8C,CAAC;IACxD,IAAMC,QAAQ,SAASb,qBAAqB,CAACD,qBAAqB,CAAC;IACnE,IAAI,CAACS,cAAc,CAACK,QAAQ,CAAC,EAAE;MAC7B,MAAM,IAAIC,KAAK,8CAAuCD,QAAQ,EAAG;IACnE;IACA,OAAOA,QAAQ;EACjB,CAAC;EAAA;AAAA;AAED,SAASE,qBAAqB,GAAW;EAAA;EACvC,+BAAO,IAAIC,eAAe,CAACC,MAAM,CAACC,QAAQ,CAACC,MAAM,CAAC,CAACC,GAAG,CAAC,cAAc,CAAC,uEAAI,EAAE;AAC9E;;AAEA;AACA;AACA;AACA,SAASC,SAAS,OAA6C;EAAA,IAA5C;IAAEC;EAA0B,CAAC;EAC9C,oBACE,oBAAC,cAAc;IAAC,eAAe,EAAEX;EAAgB,gBAC/C,oBAAC,8BAA8B,CAAC,QAAQ;IAAC,KAAK,EAAEL;EAAqB,GAClEgB,QAAQ,CAC+B,CAC3B;AAErB;AAEA,IAAMC,gBAA4B,GAAG;EACnCF,SAAS;EACTG,WAAW,EAAE,MACX1B,eAAe,EAAE,IAAI,IAAI,IAAIiB,qBAAqB,EAAE,KAAK;AAC7D,CAAC;AAED,eAAeQ,gBAAgB"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
2
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
3
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
+
import { CSSTransition } from 'react-transition-group';
|
|
5
|
+
import { LoadingOverlay, ThemeExport } from '@deephaven/components';
|
|
6
|
+
import { useClient } from '@deephaven/jsapi-bootstrap';
|
|
7
|
+
import { useBroadcastLoginListener } from '@deephaven/jsapi-components';
|
|
8
|
+
import Log from '@deephaven/log';
|
|
9
|
+
import { getErrorMessage } from '@deephaven/utils';
|
|
10
|
+
import Cookies from 'js-cookie';
|
|
11
|
+
import LoginForm from "./LoginForm.js";
|
|
12
|
+
import Login from "./Login.js";
|
|
13
|
+
import AuthenticationError from "./AuthenticationError.js";
|
|
14
|
+
var AUTH_TYPE = 'io.deephaven.authentication.psk.PskAuthenticationHandler';
|
|
15
|
+
var PSK_QUERY_PARAM_KEY = 'psk';
|
|
16
|
+
var PSK_TOKEN_KEY = 'io.deephaven.web.client.auth.psk.token';
|
|
17
|
+
var log = Log.module('AuthPluginPsk');
|
|
18
|
+
function getWindowToken() {
|
|
19
|
+
return new URLSearchParams(window.location.search).get(PSK_QUERY_PARAM_KEY);
|
|
20
|
+
}
|
|
21
|
+
function clearWindowToken() {
|
|
22
|
+
log.debug2('clearWindowToken');
|
|
23
|
+
var url = new URL(window.location.href);
|
|
24
|
+
url.searchParams.delete(PSK_QUERY_PARAM_KEY);
|
|
25
|
+
window.history.replaceState(null, '', url.href);
|
|
26
|
+
}
|
|
27
|
+
function readCookieToken() {
|
|
28
|
+
var _Cookies$get;
|
|
29
|
+
return (_Cookies$get = Cookies.get(PSK_TOKEN_KEY)) !== null && _Cookies$get !== void 0 ? _Cookies$get : null;
|
|
30
|
+
}
|
|
31
|
+
function storeCookieToken(token) {
|
|
32
|
+
log.debug2('Storing token in cookie', token);
|
|
33
|
+
if (token != null) {
|
|
34
|
+
Cookies.set(PSK_TOKEN_KEY, token, {
|
|
35
|
+
secure: true,
|
|
36
|
+
sameSite: 'strict'
|
|
37
|
+
});
|
|
38
|
+
} else {
|
|
39
|
+
Cookies.remove(PSK_TOKEN_KEY);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* AuthPlugin that tries to login using a pre-shared key.
|
|
44
|
+
* Add the `psk=<token>` parameter to your URL string to set the token.
|
|
45
|
+
*/
|
|
46
|
+
function Component(_ref) {
|
|
47
|
+
var {
|
|
48
|
+
children,
|
|
49
|
+
logoPath
|
|
50
|
+
} = _ref;
|
|
51
|
+
var client = useClient();
|
|
52
|
+
var inputField = useRef(null);
|
|
53
|
+
var loginPromise = useRef(null);
|
|
54
|
+
var [error, setError] = useState();
|
|
55
|
+
var [isInputRequired, setIsInputRequired] = useState(false);
|
|
56
|
+
var [isLoggedIn, setIsLoggedIn] = useState(false);
|
|
57
|
+
var [isLoggingIn, setIsLoggingIn] = useState(false);
|
|
58
|
+
var [token, setToken] = useState('');
|
|
59
|
+
var login = useCallback(
|
|
60
|
+
/*#__PURE__*/
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-inferrable-types
|
|
62
|
+
function () {
|
|
63
|
+
var _ref2 = _asyncToGenerator(function* (loginToken) {
|
|
64
|
+
var showError = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
65
|
+
log.info('Logging in...');
|
|
66
|
+
setIsLoggingIn(true);
|
|
67
|
+
var newLoginPromise = null;
|
|
68
|
+
try {
|
|
69
|
+
newLoginPromise = client.login({
|
|
70
|
+
type: AUTH_TYPE,
|
|
71
|
+
token: loginToken
|
|
72
|
+
});
|
|
73
|
+
loginPromise.current = newLoginPromise;
|
|
74
|
+
yield newLoginPromise;
|
|
75
|
+
log.info('Logged in successfully');
|
|
76
|
+
if (loginPromise.current !== newLoginPromise) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
storeCookieToken(loginToken);
|
|
80
|
+
setIsLoggedIn(true);
|
|
81
|
+
} catch (e) {
|
|
82
|
+
if (loginPromise.current !== newLoginPromise) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
setIsInputRequired(true);
|
|
86
|
+
if (showError) {
|
|
87
|
+
var _getErrorMessage;
|
|
88
|
+
log.error('Unable to login', e);
|
|
89
|
+
var message = (_getErrorMessage = getErrorMessage(e)) !== null && _getErrorMessage !== void 0 ? _getErrorMessage : 'Unable to login: Verify credentials.';
|
|
90
|
+
setError(new AuthenticationError(message));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
setIsLoggingIn(false);
|
|
94
|
+
});
|
|
95
|
+
return function (_x) {
|
|
96
|
+
return _ref2.apply(this, arguments);
|
|
97
|
+
};
|
|
98
|
+
}(), [client]);
|
|
99
|
+
var cancelLogin = useCallback(() => {
|
|
100
|
+
loginPromise.current = null;
|
|
101
|
+
setIsLoggingIn(false);
|
|
102
|
+
}, []);
|
|
103
|
+
var onLogin = useCallback( /*#__PURE__*/_asyncToGenerator(function* () {
|
|
104
|
+
log.debug('onLogin');
|
|
105
|
+
|
|
106
|
+
// User logged in successfully in another tab, we should be able to read the token from the cookie and login
|
|
107
|
+
var newToken = readCookieToken();
|
|
108
|
+
if (isLoggedIn || isLoggingIn || newToken == null) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
login(newToken, false);
|
|
112
|
+
}), [isLoggedIn, isLoggingIn, login]);
|
|
113
|
+
var onLogout = useCallback(() => {
|
|
114
|
+
storeCookieToken(null);
|
|
115
|
+
}, []);
|
|
116
|
+
useBroadcastLoginListener(onLogin, onLogout);
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
var isCanceled = false;
|
|
119
|
+
function initialLogin() {
|
|
120
|
+
return _initialLogin.apply(this, arguments);
|
|
121
|
+
}
|
|
122
|
+
function _initialLogin() {
|
|
123
|
+
_initialLogin = _asyncToGenerator(function* () {
|
|
124
|
+
var _getWindowToken;
|
|
125
|
+
var initialToken = (_getWindowToken = getWindowToken()) !== null && _getWindowToken !== void 0 ? _getWindowToken : readCookieToken();
|
|
126
|
+
clearWindowToken();
|
|
127
|
+
if (initialToken == null) {
|
|
128
|
+
setIsInputRequired(true);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
setIsLoggingIn(true);
|
|
132
|
+
try {
|
|
133
|
+
yield client.login({
|
|
134
|
+
type: AUTH_TYPE,
|
|
135
|
+
token: initialToken
|
|
136
|
+
});
|
|
137
|
+
if (!isCanceled) {
|
|
138
|
+
storeCookieToken(initialToken);
|
|
139
|
+
setIsLoggedIn(true);
|
|
140
|
+
setIsLoggingIn(false);
|
|
141
|
+
}
|
|
142
|
+
} catch (e) {
|
|
143
|
+
if (!isCanceled) {
|
|
144
|
+
setIsInputRequired(true);
|
|
145
|
+
setIsLoggingIn(false);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
return _initialLogin.apply(this, arguments);
|
|
150
|
+
}
|
|
151
|
+
initialLogin();
|
|
152
|
+
return () => {
|
|
153
|
+
isCanceled = true;
|
|
154
|
+
};
|
|
155
|
+
}, [client]);
|
|
156
|
+
var handleSubmit = useCallback(() => {
|
|
157
|
+
if (!isLoggingIn) {
|
|
158
|
+
login(token);
|
|
159
|
+
} else {
|
|
160
|
+
cancelLogin();
|
|
161
|
+
}
|
|
162
|
+
}, [cancelLogin, isLoggingIn, login, token]);
|
|
163
|
+
useEffect(function autoFocusInput() {
|
|
164
|
+
var _inputField$current;
|
|
165
|
+
(_inputField$current = inputField.current) === null || _inputField$current === void 0 ? void 0 : _inputField$current.focus();
|
|
166
|
+
}, [inputField, isInputRequired]);
|
|
167
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, isLoggedIn && children, isInputRequired && /*#__PURE__*/React.createElement(CSSTransition, {
|
|
168
|
+
in: !isLoggedIn,
|
|
169
|
+
timeout: ThemeExport.transitionMs,
|
|
170
|
+
classNames: "fade",
|
|
171
|
+
mountOnEnter: true,
|
|
172
|
+
unmountOnExit: true
|
|
173
|
+
}, /*#__PURE__*/React.createElement(Login, {
|
|
174
|
+
logoPath: logoPath
|
|
175
|
+
}, /*#__PURE__*/React.createElement(LoginForm, {
|
|
176
|
+
errorMessage: getErrorMessage(error),
|
|
177
|
+
isLoggingIn: isLoggingIn,
|
|
178
|
+
onSubmit: handleSubmit
|
|
179
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
180
|
+
className: "form-group"
|
|
181
|
+
}, /*#__PURE__*/React.createElement("label", {
|
|
182
|
+
htmlFor: "auth-psk-token-input"
|
|
183
|
+
}, "Token"), /*#__PURE__*/React.createElement("input", {
|
|
184
|
+
id: "auth-psk-token-input",
|
|
185
|
+
name: "token",
|
|
186
|
+
className: "input-token form-control",
|
|
187
|
+
type: "text",
|
|
188
|
+
autoComplete: "username",
|
|
189
|
+
autoCapitalize: "none",
|
|
190
|
+
autoCorrect: "off",
|
|
191
|
+
spellCheck: "false",
|
|
192
|
+
ref: inputField,
|
|
193
|
+
value: token,
|
|
194
|
+
onChange: event => {
|
|
195
|
+
setError(undefined);
|
|
196
|
+
setToken(event.target.value);
|
|
197
|
+
}
|
|
198
|
+
}))))), /*#__PURE__*/React.createElement(LoadingOverlay, {
|
|
199
|
+
"data-testid": "auth-psk-loading",
|
|
200
|
+
isLoaded: isLoggedIn || isInputRequired,
|
|
201
|
+
isLoading: !isLoggedIn && !isInputRequired
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
204
|
+
var AuthPluginPsk = {
|
|
205
|
+
Component,
|
|
206
|
+
isAvailable: authHandlers => authHandlers.includes(AUTH_TYPE)
|
|
207
|
+
};
|
|
208
|
+
export default AuthPluginPsk;
|
|
209
|
+
//# sourceMappingURL=AuthPluginPsk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthPluginPsk.js","names":["React","useCallback","useEffect","useRef","useState","CSSTransition","LoadingOverlay","ThemeExport","useClient","useBroadcastLoginListener","Log","getErrorMessage","Cookies","LoginForm","Login","AuthenticationError","AUTH_TYPE","PSK_QUERY_PARAM_KEY","PSK_TOKEN_KEY","log","module","getWindowToken","URLSearchParams","window","location","search","get","clearWindowToken","debug2","url","URL","href","searchParams","delete","history","replaceState","readCookieToken","storeCookieToken","token","set","secure","sameSite","remove","Component","children","logoPath","client","inputField","loginPromise","error","setError","isInputRequired","setIsInputRequired","isLoggedIn","setIsLoggedIn","isLoggingIn","setIsLoggingIn","setToken","login","loginToken","showError","info","newLoginPromise","type","current","e","message","cancelLogin","onLogin","debug","newToken","onLogout","isCanceled","initialLogin","initialToken","handleSubmit","autoFocusInput","focus","transitionMs","event","undefined","target","value","AuthPluginPsk","isAvailable","authHandlers","includes"],"sources":["../src/AuthPluginPsk.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { CSSTransition } from 'react-transition-group';\nimport { LoadingOverlay, ThemeExport } from '@deephaven/components';\nimport { useClient } from '@deephaven/jsapi-bootstrap';\nimport { useBroadcastLoginListener } from '@deephaven/jsapi-components';\nimport Log from '@deephaven/log';\nimport { getErrorMessage } from '@deephaven/utils';\nimport Cookies from 'js-cookie';\nimport { AuthPlugin, AuthPluginProps } from './AuthPlugin';\nimport LoginForm from './LoginForm';\nimport Login from './Login';\nimport AuthenticationError from './AuthenticationError';\n\nconst AUTH_TYPE = 'io.deephaven.authentication.psk.PskAuthenticationHandler';\n\nconst PSK_QUERY_PARAM_KEY = 'psk';\n\nconst PSK_TOKEN_KEY = 'io.deephaven.web.client.auth.psk.token';\n\nconst log = Log.module('AuthPluginPsk');\n\nfunction getWindowToken(): string | null {\n return new URLSearchParams(window.location.search).get(PSK_QUERY_PARAM_KEY);\n}\n\nfunction clearWindowToken() {\n log.debug2('clearWindowToken');\n const url = new URL(window.location.href);\n url.searchParams.delete(PSK_QUERY_PARAM_KEY);\n\n window.history.replaceState(null, '', url.href);\n}\n\nfunction readCookieToken(): string | null {\n return Cookies.get(PSK_TOKEN_KEY) ?? null;\n}\n\nfunction storeCookieToken(token: string | null): void {\n log.debug2('Storing token in cookie', token);\n if (token != null) {\n Cookies.set(PSK_TOKEN_KEY, token, { secure: true, sameSite: 'strict' });\n } else {\n Cookies.remove(PSK_TOKEN_KEY);\n }\n}\n\nexport type AuthPluginPskProps = AuthPluginProps & {\n /** Custom path to a logo to display on the login screen */\n logoPath?: string;\n};\n\n/**\n * AuthPlugin that tries to login using a pre-shared key.\n * Add the `psk=<token>` parameter to your URL string to set the token.\n */\nfunction Component({ children, logoPath }: AuthPluginPskProps): JSX.Element {\n const client = useClient();\n const inputField = useRef<HTMLInputElement>(null);\n const loginPromise = useRef<Promise<void> | null>(null);\n const [error, setError] = useState<unknown>();\n const [isInputRequired, setIsInputRequired] = useState(false);\n const [isLoggedIn, setIsLoggedIn] = useState(false);\n const [isLoggingIn, setIsLoggingIn] = useState(false);\n const [token, setToken] = useState('');\n\n const login = useCallback(\n // eslint-disable-next-line @typescript-eslint/no-inferrable-types\n async (loginToken: string, showError: boolean = true) => {\n log.info('Logging in...');\n setIsLoggingIn(true);\n let newLoginPromise: Promise<void> | null = null;\n try {\n newLoginPromise = client.login({ type: AUTH_TYPE, token: loginToken });\n loginPromise.current = newLoginPromise;\n await newLoginPromise;\n\n log.info('Logged in successfully');\n if (loginPromise.current !== newLoginPromise) {\n return;\n }\n storeCookieToken(loginToken);\n setIsLoggedIn(true);\n } catch (e) {\n if (loginPromise.current !== newLoginPromise) {\n return;\n }\n setIsInputRequired(true);\n if (showError) {\n log.error('Unable to login', e);\n const message =\n getErrorMessage(e) ?? 'Unable to login: Verify credentials.';\n setError(new AuthenticationError(message));\n }\n }\n setIsLoggingIn(false);\n },\n [client]\n );\n\n const cancelLogin = useCallback(() => {\n loginPromise.current = null;\n setIsLoggingIn(false);\n }, []);\n\n const onLogin = useCallback(async () => {\n log.debug('onLogin');\n\n // User logged in successfully in another tab, we should be able to read the token from the cookie and login\n const newToken = readCookieToken();\n if (isLoggedIn || isLoggingIn || newToken == null) {\n return;\n }\n\n login(newToken, false);\n }, [isLoggedIn, isLoggingIn, login]);\n const onLogout = useCallback(() => {\n storeCookieToken(null);\n }, []);\n useBroadcastLoginListener(onLogin, onLogout);\n\n useEffect(() => {\n let isCanceled = false;\n async function initialLogin() {\n const initialToken = getWindowToken() ?? readCookieToken();\n clearWindowToken();\n\n if (initialToken == null) {\n setIsInputRequired(true);\n return;\n }\n\n setIsLoggingIn(true);\n try {\n await client.login({ type: AUTH_TYPE, token: initialToken });\n if (!isCanceled) {\n storeCookieToken(initialToken);\n setIsLoggedIn(true);\n setIsLoggingIn(false);\n }\n } catch (e) {\n if (!isCanceled) {\n setIsInputRequired(true);\n setIsLoggingIn(false);\n }\n }\n }\n initialLogin();\n return () => {\n isCanceled = true;\n };\n }, [client]);\n\n const handleSubmit = useCallback(() => {\n if (!isLoggingIn) {\n login(token);\n } else {\n cancelLogin();\n }\n }, [cancelLogin, isLoggingIn, login, token]);\n\n useEffect(\n function autoFocusInput() {\n inputField.current?.focus();\n },\n [inputField, isInputRequired]\n );\n\n return (\n <>\n {isLoggedIn && children}\n {isInputRequired && (\n <CSSTransition\n in={!isLoggedIn}\n timeout={ThemeExport.transitionMs}\n classNames=\"fade\"\n mountOnEnter\n unmountOnExit\n >\n <Login logoPath={logoPath}>\n <LoginForm\n errorMessage={getErrorMessage(error)}\n isLoggingIn={isLoggingIn}\n onSubmit={handleSubmit}\n >\n <div className=\"form-group\">\n <label htmlFor=\"auth-psk-token-input\">Token</label>\n <input\n id=\"auth-psk-token-input\"\n name=\"token\"\n className=\"input-token form-control\"\n type=\"text\"\n autoComplete=\"username\"\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n spellCheck=\"false\"\n ref={inputField}\n value={token}\n onChange={event => {\n setError(undefined);\n setToken(event.target.value);\n }}\n />\n </div>\n </LoginForm>\n </Login>\n </CSSTransition>\n )}\n <LoadingOverlay\n data-testid=\"auth-psk-loading\"\n isLoaded={isLoggedIn || isInputRequired}\n isLoading={!isLoggedIn && !isInputRequired}\n />\n </>\n );\n}\n\nconst AuthPluginPsk: AuthPlugin = {\n Component,\n isAvailable: authHandlers => authHandlers.includes(AUTH_TYPE),\n};\n\nexport default AuthPluginPsk;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
2
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
3
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
4
|
+
export class AuthenticationError extends Error {
|
|
5
|
+
constructor() {
|
|
6
|
+
super(...arguments);
|
|
7
|
+
_defineProperty(this, "name", 'AuthenticationError');
|
|
8
|
+
_defineProperty(this, "isAuthenticationError", true);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export default AuthenticationError;
|
|
12
|
+
//# sourceMappingURL=AuthenticationError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthenticationError.js","names":["AuthenticationError","Error"],"sources":["../src/AuthenticationError.ts"],"sourcesContent":["export class AuthenticationError extends Error {\n name = 'AuthenticationError';\n\n isAuthenticationError = true;\n}\n\nexport default AuthenticationError;\n"],"mappings":";;;AAAA,OAAO,MAAMA,mBAAmB,SAASC,KAAK,CAAC;EAAA;IAAA;IAAA,8BACtC,qBAAqB;IAAA,+CAEJ,IAAI;EAAA;AAC9B;AAEA,eAAeD,mBAAmB"}
|
package/dist/Login.css
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/* stylelint-disable scss/at-import-no-partial-leading-underscore */
|
|
2
|
+
.login-container {
|
|
3
|
+
position: absolute;
|
|
4
|
+
height: 100%;
|
|
5
|
+
width: 100%;
|
|
6
|
+
top: 0;
|
|
7
|
+
left: 0;
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
}
|
|
12
|
+
.login-container .login-box {
|
|
13
|
+
position: relative;
|
|
14
|
+
display: flex;
|
|
15
|
+
width: 605px;
|
|
16
|
+
box-shadow: 0 0.1rem 1rem rgba(26, 23, 26, 0.45);
|
|
17
|
+
opacity: 0;
|
|
18
|
+
animation: 0.3s ease-out 0s 1 forwards animateLoginBox;
|
|
19
|
+
}
|
|
20
|
+
.login-container .login-box .logo {
|
|
21
|
+
background-color: #fcfcfa;
|
|
22
|
+
border-radius: 4px 0 0 4px;
|
|
23
|
+
display: flex;
|
|
24
|
+
justify-content: center;
|
|
25
|
+
align-items: center;
|
|
26
|
+
min-height: 310px;
|
|
27
|
+
min-width: 302.5px;
|
|
28
|
+
pointer-events: none;
|
|
29
|
+
user-select: none;
|
|
30
|
+
}
|
|
31
|
+
.login-container .login-box .logo img {
|
|
32
|
+
max-width: 225px;
|
|
33
|
+
}
|
|
34
|
+
.login-container .login-box .footer {
|
|
35
|
+
padding: 1rem 0;
|
|
36
|
+
position: absolute;
|
|
37
|
+
width: 100%;
|
|
38
|
+
bottom: 0;
|
|
39
|
+
margin: 0;
|
|
40
|
+
transform: translateY(100%);
|
|
41
|
+
text-align: center;
|
|
42
|
+
color: #c0bfbf;
|
|
43
|
+
font-size: 12px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@keyframes animateLoginBox {
|
|
47
|
+
0% {
|
|
48
|
+
opacity: 0;
|
|
49
|
+
}
|
|
50
|
+
100% {
|
|
51
|
+
opacity: 1;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
@media (max-width: 767.98px) {
|
|
55
|
+
.login-container .login-box {
|
|
56
|
+
flex-direction: column;
|
|
57
|
+
margin: 3rem;
|
|
58
|
+
}
|
|
59
|
+
.login-container .login-box .logo {
|
|
60
|
+
width: 100%;
|
|
61
|
+
min-height: 165px;
|
|
62
|
+
border-radius: 4px 4px 0 0;
|
|
63
|
+
}
|
|
64
|
+
.login-container .login-box .logo img {
|
|
65
|
+
width: 80%;
|
|
66
|
+
max-width: 350px;
|
|
67
|
+
}
|
|
68
|
+
.login-container .login-box .form {
|
|
69
|
+
max-width: 100%;
|
|
70
|
+
border-radius: 0 0 4px 4px;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/*# sourceMappingURL=Login.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sourceRoot":"","sources":["../../../node_modules/@deephaven/components/scss/custom.scss","../src/Login.scss","../../../node_modules/@deephaven/components/scss/bootstrap_overrides.scss","../../../node_modules/bootstrap/scss/mixins/_breakpoints.scss","../../../node_modules/@deephaven/components/scss/new_variables.scss"],"names":[],"mappings":"AAAA;ACQA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA,OAnBc;EAoBd,YCoGS;EDnGT;EACA;;AAEA;EACE,kBCTK;EDUL;EACA;EACA;EACA;EACA,YA7BiB;EA8BjB;EACA;EACA;;AAEA;EACE;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OC9BK;ED+BL;;;AAKN;EACE;IACE;;EAEF;IACE;;;AEYA;EFNA;IACE;IACA,QG/DK;;EHgEL;IACE;IACA;IACA;;EACA;IACE;IACA;;EAGJ;IACE;IACA","file":"Login.css","sourcesContent":["/* stylelint-disable scss/at-import-no-partial-leading-underscore */\n// Consumers should be able to resolve bootstrap/ to node_modules/bootstrap\n\n//Make bootstrap functions available for use in overrides\n@import 'bootstrap/scss/_functions.scss';\n@import './bootstrap_overrides.scss';\n\n//_variable imports come after bootstrap default overrides,\n// makes all other variables and mixins from bootstrap available\n/// with just importing customer.scss\n@import 'bootstrap/scss/_variables.scss';\n@import 'bootstrap/scss/_mixins.scss';\n\n//New variables come after imports\n@import './new_variables.scss';\n","@import '@deephaven/components/scss/custom.scss';\n\n$login-box-width: 605px;\n$login-box-min-height: 310px;\n$logo-background-color: $gray-100;\n$footer-color: $gray-300;\n$login-box-animation-scale: 0.8;\n\n.login-container {\n position: absolute;\n height: 100%;\n width: 100%;\n top: 0;\n left: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n\n .login-box {\n position: relative;\n display: flex;\n width: $login-box-width;\n box-shadow: $box-shadow;\n opacity: 0;\n animation: $transition-long ease-out 0s 1 forwards animateLoginBox;\n\n .logo {\n background-color: $logo-background-color;\n border-radius: $border-radius 0 0 $border-radius;\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: $login-box-min-height;\n min-width: $login-box-width * 0.5;\n pointer-events: none;\n user-select: none;\n\n img {\n max-width: 225px;\n }\n }\n\n .footer {\n padding: $spacer-3 0;\n position: absolute;\n width: 100%;\n bottom: 0;\n margin: 0;\n transform: translateY(100%);\n text-align: center;\n color: $footer-color;\n font-size: 12px;\n }\n }\n}\n\n@keyframes animateLoginBox {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n\n@include media-breakpoint-down(sm) {\n .login-container {\n .login-box {\n flex-direction: column;\n margin: $spacer-5;\n .logo {\n width: 100%;\n min-height: 165px;\n border-radius: $border-radius $border-radius 0 0;\n img {\n width: 80%;\n max-width: 350px;\n }\n }\n .form {\n max-width: 100%;\n border-radius: 0 0 $border-radius $border-radius;\n }\n }\n }\n}\n","// Styling overrides for bootstrap\n\n// Override / set color variables\n$red: #f95d84;\n$orange: #f37e3f;\n$yellow: #fcd65b;\n$green: #9edc6f;\n$blue: #76d9e4;\n$purple: #aa9af4;\n\n//Define some UI colors\n$interfacegray: #2d2a2e;\n$interfaceblue: #4878ea;\n$interfacewhite: #f0f0ee; //same as gray-200\n$interfaceblack: #1a171a;\n\n//Define our Gray scale\n$white: $interfacewhite;\n$gray-100: #fcfcfa;\n$gray-200: $interfacewhite;\n$gray-300: #c0bfbf;\n$gray-400: #929192;\n$gray-500: #5b5a5c;\n$gray-600: #555356;\n$gray-700: #403e41;\n$gray-800: #373438;\n$gray-850: #322f33;\n$gray-900: #211f22;\n$black: $interfaceblack;\n$content-bg: $interfacegray;\n$background: $interfaceblack;\n$foreground: $interfacewhite;\n\n//Load colors into map\n$colors: ();\n$colors: map-merge(\n (\n 'red': $red,\n 'orange': $orange,\n 'yellow': $yellow,\n 'green': $green,\n 'blue': $blue,\n 'purple': $purple,\n 'white': $white,\n 'black': $black,\n ),\n $colors\n);\n\n//Set default colors\n$body-bg: $black;\n$body-color: $interfacewhite;\n\n// Set brand colors\n$primary: $interfaceblue;\n$primary-hover: darken($primary, 8%);\n$primary-dark: mix($primary, $content-bg, 25%);\n$primary-light: scale-color($primary, $lightness: -25%);\n$secondary: $gray-500;\n$secondary-hover: darken($secondary, 8%);\n$success: $green;\n$info: $yellow;\n$warning: $orange;\n$danger: $red;\n$danger-hover: darken($danger, 8%);\n$light: $gray-100;\n$mid: $gray-400; //Added a mid color, useful for input styling\n$dark: $gray-800;\n$green-dark: scale-color($green, $lightness: -45%, $saturation: -10%);\n\n$theme-colors: () !default;\n$theme-colors: map-merge(\n (\n 'primary': $primary,\n 'primary-hover': $primary-hover,\n 'primary-light': $primary-light,\n 'primary-dark': $primary-dark,\n 'secondary': $secondary,\n 'success': $success,\n 'info': $info,\n 'warning': $warning,\n 'danger': $danger,\n 'light': $light,\n 'dark': $dark,\n 'mid': $mid,\n 'content-bg': $interfacegray,\n 'background': $interfaceblack,\n 'foreground': $interfacewhite,\n ),\n $theme-colors\n);\n\n$component-active-bg: $primary;\n$theme-color-interval: 9%;\n$yiq-contrasted-threshold: 180;\n\n// Override fonts\n$font-family-sans-serif: 'Fira Sans', -apple-system, blinkmacsystemfont,\n 'Segoe UI', 'Roboto', 'Helvetica Neue', arial, sans-serif; //fira sans then native system ui fallbacks\n$font-family-monospace: 'Fira Mono', menlo, monaco, consolas, 'Liberation Mono',\n 'Courier New', monospace;\n$font-family-base: $font-family-sans-serif;\n\n$headings-font-weight: 400;\n\n//Text overides\n$text-muted: $gray-400;\n\n//Style Selection highlight color\n//so browsers add alpha to your color by default, ignoring opacity 1\n//by setting rgba with 0.99 it tricks browser into thinking there is alpha applied\n$text-select-color: $primary-hover;\n$text-select-color-editor: lighten(\n $gray-700,\n 15%\n); //we lighten it abit to account for that 0.01 loss, and because it needs some anyways.\n\n//Grid variables, same value as default just making easily accessible\n$grid-gutter-width: 30px;\n\n//Visual Overrides\n$border-radius: 4px;\n$box-shadow: 0 0.1rem 1rem rgba($black, 45%); //because our UI is so dark, we need darker default shadows\n$box-shadow-900: 0 0.1rem 1rem rgba(0, 0, 0, 45%); //darkest shadow for $black popups over $black UI\n\n//Override Btn\n$btn-border-radius: 4rem;\n$btn-padding-x: 1.5rem;\n$btn-transition: color 0.12s ease-in-out, background-color 0.12s ease-in-out,\n border-color 0.12s ease-in-out, box-shadow 0.12s ease-in-out; //default 0.15 is too long\n$btn-border-width: 2px;\n\n//Override Inputs\n$input-bg: $gray-600;\n$input-disabled-bg: $gray-800;\n$input-color: $foreground;\n$input-border-color: $gray-400;\n$input-placeholder-color: $gray-400;\n$input-focus-border-color: rgba($primary, 85%);\n\n$input-btn-focus-width: 0.2rem;\n$input-btn-focus-color: rgba($component-active-bg, 35%);\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color;\n\n//checkbox\n$custom-control-indicator-bg: $gray-600;\n$custom-control-indicator-bg-size: 75% 75%;\n$custom-control-indicator-disabled-bg: $gray-800;\n$custom-control-indicator-checked-disabled-bg: $gray-800;\n$custom-control-label-disabled-color: $gray-400;\n\n//Custom Select\n$custom-select-indicator-color: $gray-400;\n$custom-select-bg-size: 16px 16px;\n//dhSort icon encoded\n$custom-select-indicator: str-replace(\n url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='#{$custom-select-indicator-color}' d='M4 7l-.4-.8 4-3.7h.8l4 3.7-.4.8H4zm0 2l-.4.8 4 3.7h.8l4-3.7L12 9H4z'/%3E%3C/svg%3E\"),\n '#',\n '%23'\n);\n$custom-select-focus-box-shadow: $input-btn-focus-box-shadow;\n$custom-select-disabled-color: darken($gray-400, 5%);\n$custom-select-disabled-bg: $gray-800;\n\n//modal\n$modal-content-bg: $gray-200;\n$modal-content-border-width: 0;\n$modal-md: 550px;\n\n// Toast notification\n$toast-bg: $primary-dark;\n$toast-color: $foreground;\n$toast-error-bg: mix($danger, $content-bg, 15%);\n$toast-error-color: $foreground;\n\n//tooltips\n$tooltip-bg: $gray-700;\n$tooltip-color: $foreground;\n$tooltip-box-shadow: 0 0.1rem 1.5rem 0.1rem rgba($black, 80%);\n\n//drowdowns\n$dropdown-bg: $gray-600;\n$dropdown-link-color: $foreground;\n$dropdown-link-hover-color: $foreground;\n$dropdown-link-hover-bg: $primary;\n$dropdown-divider-bg: $gray-700;\n\n//context menus\n$contextmenu-bg: $gray-600;\n$contextmenu-color: $foreground;\n$contextmenu-disabled-color: $text-muted;\n$contextmenu-keyboard-selected-bg: rgba($primary, 50%);\n$contextmenu-selected-bg: $primary;\n$contextmenu-selected-color: $foreground;\n\n//links\n$link-color: $gray-400;\n$link-hover-color: $foreground;\n\n//progress-bar\n$progress-bg: $gray-600;\n$progress-border-radius: 1rem;\n\n// Set global options\n$enable-shadows: false;\n$enable-gradients: false;\n$enable-print-styles: false; //I don't think anyone should expect to \"print\" this app.\n\n// Transition times\n$transition: 0.15s;\n$transition-mid: 0.2s;\n$transition-long: 0.3s;\n$transition-slow: 0.6s;\n\n//form-validation icon, uses vsWarning icon encoded here as svg\n$form-feedback-icon-invalid-color: theme-color('danger');\n$form-feedback-icon-invalid: str-replace(\n url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cg fill='none'%3E%3Cg fill='#{$form-feedback-icon-invalid-color}'%3E%3Cpath d='M7.56 1h.88l6.54 12.26-.44.74H1.44L1 13.26 7.56 1zM8 2.28 2.28 13H13.7L8 2.28zM8.625 12v-1h-1.25v1h1.25zm-1.25-2V6h1.25v4h-1.25z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E \"),\n '#',\n '%23'\n);\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n != null and $n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","//Set of spacer variables from the spacer map\n$spacer-0: map-get($spacers, 0); //0\n$spacer-1: map-get($spacers, 1);\n$spacer-2: map-get($spacers, 2);\n$spacer-3: map-get($spacers, 3);\n$spacer-4: map-get($spacers, 4);\n$spacer-5: map-get($spacers, 5);\n\n//Marching Ants for golden layout dropzone and drag and drop\n//top bottom, left right.\n//create 4 background images that are 50% color 1, 50% color 2 using graidents, two veritical, two horizontal\n//size them to ant-size and thickness\n//position those images along the egdes and make top/bottom repeat-x and left/right repeat-y\n//then offest each of those background positions by ant-size in animation to make them march.\n$ant-size: 8px;\n$ant-thickness: 1px;\n\n@mixin ants-base($color-1: black, $color-2: white) {\n background-image: linear-gradient(to right, $color-2 50%, $color-1 50%),\n linear-gradient(to right, $color-2 50%, $color-1 50%),\n linear-gradient(to bottom, $color-2 50%, $color-1 50%),\n linear-gradient(to bottom, $color-2 50%, $color-1 50%);\n background-size: $ant-size $ant-thickness, $ant-size $ant-thickness,\n $ant-thickness $ant-size, $ant-thickness $ant-size;\n background-position: 0 top, 0 bottom, left 0, right 0;\n background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;\n animation: march 0.5s;\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n}\n\n@mixin drag-stack($pseudo-element) {\n &::#{$pseudo-element} {\n content: ' ';\n background: $primary;\n box-shadow: $box-shadow;\n border-radius: $border-radius;\n position: absolute;\n height: 100%;\n width: 100%;\n @content;\n }\n}\n\n$focus-bg-transparency: 0.12;\n$hover-bg-transparency: 0.14;\n$active-bg-transparency: 0.28;\n$exception-transparency: 0.13;\n"]}
|
package/dist/Login.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { RandomAreaPlotAnimation } from '@deephaven/components';
|
|
3
|
+
import "./Login.css";
|
|
4
|
+
export function Login(_ref) {
|
|
5
|
+
var {
|
|
6
|
+
children,
|
|
7
|
+
logoPath = './logo.png'
|
|
8
|
+
} = _ref;
|
|
9
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
10
|
+
className: "login-container"
|
|
11
|
+
}, /*#__PURE__*/React.createElement(RandomAreaPlotAnimation, null), /*#__PURE__*/React.createElement("div", {
|
|
12
|
+
className: "login-box"
|
|
13
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
14
|
+
className: "logo"
|
|
15
|
+
}, /*#__PURE__*/React.createElement("img", {
|
|
16
|
+
src: logoPath,
|
|
17
|
+
alt: "Deephaven Data Labs"
|
|
18
|
+
})), children, /*#__PURE__*/React.createElement("p", {
|
|
19
|
+
className: "footer"
|
|
20
|
+
}, "\xA9 2016-", new Date().getFullYear(), " Deephaven Data Labs LLC. Patent Pending.")));
|
|
21
|
+
}
|
|
22
|
+
export default Login;
|
|
23
|
+
//# sourceMappingURL=Login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Login.js","names":["React","RandomAreaPlotAnimation","Login","children","logoPath","Date","getFullYear"],"sources":["../src/Login.tsx"],"sourcesContent":["import React from 'react';\nimport { RandomAreaPlotAnimation } from '@deephaven/components';\nimport './Login.scss';\n\ninterface LoginProps {\n /** What to show in the login input part of the login form. */\n children: React.ReactNode;\n\n /** Path to the custom logo, relative to document base */\n logoPath?: string;\n}\n\nexport function Login({ children, logoPath = './logo.png' }: LoginProps) {\n return (\n <div className=\"login-container\">\n <RandomAreaPlotAnimation />\n <div className=\"login-box\">\n <div className=\"logo\">\n <img src={logoPath} alt=\"Deephaven Data Labs\" />\n </div>\n {children}\n <p className=\"footer\">\n © 2016-{new Date().getFullYear()} Deephaven Data Labs LLC. Patent\n Pending.\n </p>\n </div>\n </div>\n );\n}\n\nexport default Login;\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,uBAAuB,QAAQ,uBAAuB;AAAC;AAWhE,OAAO,SAASC,KAAK,OAAoD;EAAA,IAAnD;IAAEC,QAAQ;IAAEC,QAAQ,GAAG;EAAyB,CAAC;EACrE,oBACE;IAAK,SAAS,EAAC;EAAiB,gBAC9B,oBAAC,uBAAuB,OAAG,eAC3B;IAAK,SAAS,EAAC;EAAW,gBACxB;IAAK,SAAS,EAAC;EAAM,gBACnB;IAAK,GAAG,EAAEA,QAAS;IAAC,GAAG,EAAC;EAAqB,EAAG,CAC5C,EACLD,QAAQ,eACT;IAAG,SAAS,EAAC;EAAQ,GAAC,YACb,EAAC,IAAIE,IAAI,EAAE,CAACC,WAAW,EAAE,EAAC,2CAEnC,CAAI,CACA,CACF;AAEV;AAEA,eAAeJ,KAAK"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/* stylelint-disable scss/at-import-no-partial-leading-underscore */
|
|
2
|
+
.login-form {
|
|
3
|
+
max-width: 302.5px;
|
|
4
|
+
min-height: 310px;
|
|
5
|
+
background: #403e41;
|
|
6
|
+
border-radius: 0 4px 4px 0;
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-grow: 1;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
align-items: center;
|
|
11
|
+
justify-content: space-between;
|
|
12
|
+
padding: 1rem 0;
|
|
13
|
+
}
|
|
14
|
+
.login-form fieldset {
|
|
15
|
+
padding: 0;
|
|
16
|
+
margin: 0;
|
|
17
|
+
}
|
|
18
|
+
.login-form .flex-wrapper {
|
|
19
|
+
width: 85%;
|
|
20
|
+
}
|
|
21
|
+
.login-form .flex-spacer {
|
|
22
|
+
display: flex;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
align-items: center;
|
|
25
|
+
flex-grow: 1;
|
|
26
|
+
width: 85%;
|
|
27
|
+
}
|
|
28
|
+
.login-form .flex-spacer:empty {
|
|
29
|
+
content: "";
|
|
30
|
+
}
|
|
31
|
+
.login-form .status-message {
|
|
32
|
+
color: #929192;
|
|
33
|
+
}
|
|
34
|
+
.login-form .error-message {
|
|
35
|
+
color: #f95d84;
|
|
36
|
+
width: 100%;
|
|
37
|
+
word-break: break-word;
|
|
38
|
+
margin-top: 0.25rem;
|
|
39
|
+
margin-bottom: 0.25rem;
|
|
40
|
+
}
|
|
41
|
+
.login-form .btn-primary {
|
|
42
|
+
min-width: 118px;
|
|
43
|
+
}
|
|
44
|
+
@keyframes fade-in {
|
|
45
|
+
from {
|
|
46
|
+
opacity: 0;
|
|
47
|
+
}
|
|
48
|
+
to {
|
|
49
|
+
opacity: 1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
.login-form .is-initializing {
|
|
53
|
+
opacity: 0;
|
|
54
|
+
animation: fade-in 0.15s 1s forwards;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/*# sourceMappingURL=LoginForm.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sourceRoot":"","sources":["../../../node_modules/@deephaven/components/scss/custom.scss","../src/LoginForm.scss","../../../node_modules/@deephaven/components/scss/bootstrap_overrides.scss","../../../node_modules/@deephaven/components/scss/new_variables.scss"],"names":[],"mappings":"AAAA;ACKA;EACE;EACA,YAJqB;EAKrB,YCgBS;EDfT;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAGF;EACE,OClBO;;ADqBT;EACE,OCxCE;EDyCF;EACA;EACA,YE5CO;EF6CP,eE7CO;;AFgDT;EACE;;AAGF;EACE;IACE;;EAEF;IACE;;;AAIJ;EACE;EACA","file":"LoginForm.css","sourcesContent":["/* stylelint-disable scss/at-import-no-partial-leading-underscore */\n// Consumers should be able to resolve bootstrap/ to node_modules/bootstrap\n\n//Make bootstrap functions available for use in overrides\n@import 'bootstrap/scss/_functions.scss';\n@import './bootstrap_overrides.scss';\n\n//_variable imports come after bootstrap default overrides,\n// makes all other variables and mixins from bootstrap available\n/// with just importing customer.scss\n@import 'bootstrap/scss/_variables.scss';\n@import 'bootstrap/scss/_mixins.scss';\n\n//New variables come after imports\n@import './new_variables.scss';\n","@import '@deephaven/components/scss/custom.scss';\n\n$login-box-width: 605px;\n$login-box-min-height: 310px;\n\n.login-form {\n max-width: $login-box-width * 0.5;\n min-height: $login-box-min-height;\n background: $gray-700;\n border-radius: 0 $border-radius $border-radius 0;\n display: flex;\n flex-grow: 1;\n flex-direction: column;\n align-items: center;\n justify-content: space-between;\n padding: $spacer 0;\n\n fieldset {\n padding: 0;\n margin: 0;\n }\n\n .flex-wrapper {\n width: 85%;\n }\n\n .flex-spacer {\n display: flex;\n justify-content: center;\n align-items: center;\n flex-grow: 1;\n width: 85%;\n }\n\n .flex-spacer:empty {\n content: ''; // just to make a empty div to have height\n }\n\n .status-message {\n color: $gray-400;\n }\n\n .error-message {\n color: $danger;\n width: 100%;\n word-break: break-word;\n margin-top: $spacer-1;\n margin-bottom: $spacer-1;\n }\n\n .btn-primary {\n min-width: 118px;\n }\n\n @keyframes fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n .is-initializing {\n opacity: 0;\n animation: fade-in $transition 1s forwards;\n }\n}\n","// Styling overrides for bootstrap\n\n// Override / set color variables\n$red: #f95d84;\n$orange: #f37e3f;\n$yellow: #fcd65b;\n$green: #9edc6f;\n$blue: #76d9e4;\n$purple: #aa9af4;\n\n//Define some UI colors\n$interfacegray: #2d2a2e;\n$interfaceblue: #4878ea;\n$interfacewhite: #f0f0ee; //same as gray-200\n$interfaceblack: #1a171a;\n\n//Define our Gray scale\n$white: $interfacewhite;\n$gray-100: #fcfcfa;\n$gray-200: $interfacewhite;\n$gray-300: #c0bfbf;\n$gray-400: #929192;\n$gray-500: #5b5a5c;\n$gray-600: #555356;\n$gray-700: #403e41;\n$gray-800: #373438;\n$gray-850: #322f33;\n$gray-900: #211f22;\n$black: $interfaceblack;\n$content-bg: $interfacegray;\n$background: $interfaceblack;\n$foreground: $interfacewhite;\n\n//Load colors into map\n$colors: ();\n$colors: map-merge(\n (\n 'red': $red,\n 'orange': $orange,\n 'yellow': $yellow,\n 'green': $green,\n 'blue': $blue,\n 'purple': $purple,\n 'white': $white,\n 'black': $black,\n ),\n $colors\n);\n\n//Set default colors\n$body-bg: $black;\n$body-color: $interfacewhite;\n\n// Set brand colors\n$primary: $interfaceblue;\n$primary-hover: darken($primary, 8%);\n$primary-dark: mix($primary, $content-bg, 25%);\n$primary-light: scale-color($primary, $lightness: -25%);\n$secondary: $gray-500;\n$secondary-hover: darken($secondary, 8%);\n$success: $green;\n$info: $yellow;\n$warning: $orange;\n$danger: $red;\n$danger-hover: darken($danger, 8%);\n$light: $gray-100;\n$mid: $gray-400; //Added a mid color, useful for input styling\n$dark: $gray-800;\n$green-dark: scale-color($green, $lightness: -45%, $saturation: -10%);\n\n$theme-colors: () !default;\n$theme-colors: map-merge(\n (\n 'primary': $primary,\n 'primary-hover': $primary-hover,\n 'primary-light': $primary-light,\n 'primary-dark': $primary-dark,\n 'secondary': $secondary,\n 'success': $success,\n 'info': $info,\n 'warning': $warning,\n 'danger': $danger,\n 'light': $light,\n 'dark': $dark,\n 'mid': $mid,\n 'content-bg': $interfacegray,\n 'background': $interfaceblack,\n 'foreground': $interfacewhite,\n ),\n $theme-colors\n);\n\n$component-active-bg: $primary;\n$theme-color-interval: 9%;\n$yiq-contrasted-threshold: 180;\n\n// Override fonts\n$font-family-sans-serif: 'Fira Sans', -apple-system, blinkmacsystemfont,\n 'Segoe UI', 'Roboto', 'Helvetica Neue', arial, sans-serif; //fira sans then native system ui fallbacks\n$font-family-monospace: 'Fira Mono', menlo, monaco, consolas, 'Liberation Mono',\n 'Courier New', monospace;\n$font-family-base: $font-family-sans-serif;\n\n$headings-font-weight: 400;\n\n//Text overides\n$text-muted: $gray-400;\n\n//Style Selection highlight color\n//so browsers add alpha to your color by default, ignoring opacity 1\n//by setting rgba with 0.99 it tricks browser into thinking there is alpha applied\n$text-select-color: $primary-hover;\n$text-select-color-editor: lighten(\n $gray-700,\n 15%\n); //we lighten it abit to account for that 0.01 loss, and because it needs some anyways.\n\n//Grid variables, same value as default just making easily accessible\n$grid-gutter-width: 30px;\n\n//Visual Overrides\n$border-radius: 4px;\n$box-shadow: 0 0.1rem 1rem rgba($black, 45%); //because our UI is so dark, we need darker default shadows\n$box-shadow-900: 0 0.1rem 1rem rgba(0, 0, 0, 45%); //darkest shadow for $black popups over $black UI\n\n//Override Btn\n$btn-border-radius: 4rem;\n$btn-padding-x: 1.5rem;\n$btn-transition: color 0.12s ease-in-out, background-color 0.12s ease-in-out,\n border-color 0.12s ease-in-out, box-shadow 0.12s ease-in-out; //default 0.15 is too long\n$btn-border-width: 2px;\n\n//Override Inputs\n$input-bg: $gray-600;\n$input-disabled-bg: $gray-800;\n$input-color: $foreground;\n$input-border-color: $gray-400;\n$input-placeholder-color: $gray-400;\n$input-focus-border-color: rgba($primary, 85%);\n\n$input-btn-focus-width: 0.2rem;\n$input-btn-focus-color: rgba($component-active-bg, 35%);\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color;\n\n//checkbox\n$custom-control-indicator-bg: $gray-600;\n$custom-control-indicator-bg-size: 75% 75%;\n$custom-control-indicator-disabled-bg: $gray-800;\n$custom-control-indicator-checked-disabled-bg: $gray-800;\n$custom-control-label-disabled-color: $gray-400;\n\n//Custom Select\n$custom-select-indicator-color: $gray-400;\n$custom-select-bg-size: 16px 16px;\n//dhSort icon encoded\n$custom-select-indicator: str-replace(\n url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='#{$custom-select-indicator-color}' d='M4 7l-.4-.8 4-3.7h.8l4 3.7-.4.8H4zm0 2l-.4.8 4 3.7h.8l4-3.7L12 9H4z'/%3E%3C/svg%3E\"),\n '#',\n '%23'\n);\n$custom-select-focus-box-shadow: $input-btn-focus-box-shadow;\n$custom-select-disabled-color: darken($gray-400, 5%);\n$custom-select-disabled-bg: $gray-800;\n\n//modal\n$modal-content-bg: $gray-200;\n$modal-content-border-width: 0;\n$modal-md: 550px;\n\n// Toast notification\n$toast-bg: $primary-dark;\n$toast-color: $foreground;\n$toast-error-bg: mix($danger, $content-bg, 15%);\n$toast-error-color: $foreground;\n\n//tooltips\n$tooltip-bg: $gray-700;\n$tooltip-color: $foreground;\n$tooltip-box-shadow: 0 0.1rem 1.5rem 0.1rem rgba($black, 80%);\n\n//drowdowns\n$dropdown-bg: $gray-600;\n$dropdown-link-color: $foreground;\n$dropdown-link-hover-color: $foreground;\n$dropdown-link-hover-bg: $primary;\n$dropdown-divider-bg: $gray-700;\n\n//context menus\n$contextmenu-bg: $gray-600;\n$contextmenu-color: $foreground;\n$contextmenu-disabled-color: $text-muted;\n$contextmenu-keyboard-selected-bg: rgba($primary, 50%);\n$contextmenu-selected-bg: $primary;\n$contextmenu-selected-color: $foreground;\n\n//links\n$link-color: $gray-400;\n$link-hover-color: $foreground;\n\n//progress-bar\n$progress-bg: $gray-600;\n$progress-border-radius: 1rem;\n\n// Set global options\n$enable-shadows: false;\n$enable-gradients: false;\n$enable-print-styles: false; //I don't think anyone should expect to \"print\" this app.\n\n// Transition times\n$transition: 0.15s;\n$transition-mid: 0.2s;\n$transition-long: 0.3s;\n$transition-slow: 0.6s;\n\n//form-validation icon, uses vsWarning icon encoded here as svg\n$form-feedback-icon-invalid-color: theme-color('danger');\n$form-feedback-icon-invalid: str-replace(\n url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cg fill='none'%3E%3Cg fill='#{$form-feedback-icon-invalid-color}'%3E%3Cpath d='M7.56 1h.88l6.54 12.26-.44.74H1.44L1 13.26 7.56 1zM8 2.28 2.28 13H13.7L8 2.28zM8.625 12v-1h-1.25v1h1.25zm-1.25-2V6h1.25v4h-1.25z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E \"),\n '#',\n '%23'\n);\n","//Set of spacer variables from the spacer map\n$spacer-0: map-get($spacers, 0); //0\n$spacer-1: map-get($spacers, 1);\n$spacer-2: map-get($spacers, 2);\n$spacer-3: map-get($spacers, 3);\n$spacer-4: map-get($spacers, 4);\n$spacer-5: map-get($spacers, 5);\n\n//Marching Ants for golden layout dropzone and drag and drop\n//top bottom, left right.\n//create 4 background images that are 50% color 1, 50% color 2 using graidents, two veritical, two horizontal\n//size them to ant-size and thickness\n//position those images along the egdes and make top/bottom repeat-x and left/right repeat-y\n//then offest each of those background positions by ant-size in animation to make them march.\n$ant-size: 8px;\n$ant-thickness: 1px;\n\n@mixin ants-base($color-1: black, $color-2: white) {\n background-image: linear-gradient(to right, $color-2 50%, $color-1 50%),\n linear-gradient(to right, $color-2 50%, $color-1 50%),\n linear-gradient(to bottom, $color-2 50%, $color-1 50%),\n linear-gradient(to bottom, $color-2 50%, $color-1 50%);\n background-size: $ant-size $ant-thickness, $ant-size $ant-thickness,\n $ant-thickness $ant-size, $ant-thickness $ant-size;\n background-position: 0 top, 0 bottom, left 0, right 0;\n background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;\n animation: march 0.5s;\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n}\n\n@mixin drag-stack($pseudo-element) {\n &::#{$pseudo-element} {\n content: ' ';\n background: $primary;\n box-shadow: $box-shadow;\n border-radius: $border-radius;\n position: absolute;\n height: 100%;\n width: 100%;\n @content;\n }\n}\n\n$focus-bg-transparency: 0.12;\n$hover-bg-transparency: 0.14;\n$active-bg-transparency: 0.28;\n$exception-transparency: 0.13;\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { LoadingSpinner } from '@deephaven/components';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import "./LoginForm.css";
|
|
5
|
+
export function LoginForm(_ref) {
|
|
6
|
+
var {
|
|
7
|
+
children,
|
|
8
|
+
errorMessage,
|
|
9
|
+
isLoggingIn = false,
|
|
10
|
+
onSubmit: _onSubmit
|
|
11
|
+
} = _ref;
|
|
12
|
+
return /*#__PURE__*/React.createElement("form", {
|
|
13
|
+
className: "login-form",
|
|
14
|
+
onSubmit: event => {
|
|
15
|
+
event.preventDefault();
|
|
16
|
+
event.stopPropagation();
|
|
17
|
+
_onSubmit === null || _onSubmit === void 0 ? void 0 : _onSubmit(event);
|
|
18
|
+
}
|
|
19
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
20
|
+
className: "flex-spacer"
|
|
21
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
22
|
+
className: "flex-wrapper"
|
|
23
|
+
}, /*#__PURE__*/React.createElement("fieldset", {
|
|
24
|
+
disabled: isLoggingIn,
|
|
25
|
+
className: "container-fluid"
|
|
26
|
+
}, children), /*#__PURE__*/React.createElement("div", {
|
|
27
|
+
className: "form-group d-flex justify-content-end align-items-center mb-0"
|
|
28
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
29
|
+
type: "submit",
|
|
30
|
+
className: classNames('btn btn-primary', {
|
|
31
|
+
'btn-spinner': isLoggingIn
|
|
32
|
+
}, {
|
|
33
|
+
'btn-cancelable': isLoggingIn
|
|
34
|
+
}),
|
|
35
|
+
"data-testid": "btn-login"
|
|
36
|
+
}, isLoggingIn && /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(LoadingSpinner, null), /*#__PURE__*/React.createElement("span", {
|
|
37
|
+
className: "btn-normal-content"
|
|
38
|
+
}, "Logging in"), /*#__PURE__*/React.createElement("span", {
|
|
39
|
+
className: "btn-hover-content"
|
|
40
|
+
}, "Cancel")), !isLoggingIn && 'Login'))), /*#__PURE__*/React.createElement("div", {
|
|
41
|
+
className: "flex-spacer"
|
|
42
|
+
}, errorMessage != null && /*#__PURE__*/React.createElement("p", {
|
|
43
|
+
className: "error-message mb-0",
|
|
44
|
+
role: "alert"
|
|
45
|
+
}, "".concat(errorMessage))));
|
|
46
|
+
}
|
|
47
|
+
export default LoginForm;
|
|
48
|
+
//# sourceMappingURL=LoginForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LoginForm.js","names":["LoadingSpinner","classNames","React","LoginForm","children","errorMessage","isLoggingIn","onSubmit","event","preventDefault","stopPropagation"],"sources":["../src/LoginForm.tsx"],"sourcesContent":["import { LoadingSpinner } from '@deephaven/components';\nimport classNames from 'classnames';\nimport React, { FormEventHandler } from 'react';\nimport './LoginForm.scss';\n\nexport interface LoginFormProps {\n /** What to display inside the form */\n children: React.ReactNode;\n\n /** Error message to display */\n errorMessage?: string;\n\n /** Whether currently logging in */\n isLoggingIn?: boolean;\n\n /** Triggered when the form is submitting */\n onSubmit?: FormEventHandler;\n}\n\nexport function LoginForm({\n children,\n errorMessage,\n isLoggingIn = false,\n onSubmit,\n}: LoginFormProps) {\n return (\n <form\n className=\"login-form\"\n onSubmit={event => {\n event.preventDefault();\n event.stopPropagation();\n onSubmit?.(event);\n }}\n >\n <div className=\"flex-spacer\" />\n <div className=\"flex-wrapper\">\n <fieldset disabled={isLoggingIn} className=\"container-fluid\">\n {children}\n </fieldset>\n <div className=\"form-group d-flex justify-content-end align-items-center mb-0\">\n <button\n type=\"submit\"\n className={classNames(\n 'btn btn-primary',\n { 'btn-spinner': isLoggingIn },\n { 'btn-cancelable': isLoggingIn }\n )}\n data-testid=\"btn-login\"\n >\n {isLoggingIn && (\n <span>\n <LoadingSpinner />\n <span className=\"btn-normal-content\">Logging in</span>\n <span className=\"btn-hover-content\">Cancel</span>\n </span>\n )}\n {!isLoggingIn && 'Login'}\n </button>\n </div>\n </div>\n <div className=\"flex-spacer\">\n {errorMessage != null && (\n <p className=\"error-message mb-0\" role=\"alert\">{`${errorMessage}`}</p>\n )}\n </div>\n </form>\n );\n}\n\nexport default LoginForm;\n"],"mappings":"AAAA,SAASA,cAAc,QAAQ,uBAAuB;AACtD,OAAOC,UAAU,MAAM,YAAY;AACnC,OAAOC,KAAK,MAA4B,OAAO;AAAC;AAiBhD,OAAO,SAASC,SAAS,OAKN;EAAA,IALO;IACxBC,QAAQ;IACRC,YAAY;IACZC,WAAW,GAAG,KAAK;IACnBC,QAAQ,EAARA;EACc,CAAC;EACf,oBACE;IACE,SAAS,EAAC,YAAY;IACtB,QAAQ,EAAEC,KAAK,IAAI;MACjBA,KAAK,CAACC,cAAc,EAAE;MACtBD,KAAK,CAACE,eAAe,EAAE;MACvBH,SAAQ,aAARA,SAAQ,uBAARA,SAAQ,CAAGC,KAAK,CAAC;IACnB;EAAE,gBAEF;IAAK,SAAS,EAAC;EAAa,EAAG,eAC/B;IAAK,SAAS,EAAC;EAAc,gBAC3B;IAAU,QAAQ,EAAEF,WAAY;IAAC,SAAS,EAAC;EAAiB,GACzDF,QAAQ,CACA,eACX;IAAK,SAAS,EAAC;EAA+D,gBAC5E;IACE,IAAI,EAAC,QAAQ;IACb,SAAS,EAAEH,UAAU,CACnB,iBAAiB,EACjB;MAAE,aAAa,EAAEK;IAAY,CAAC,EAC9B;MAAE,gBAAgB,EAAEA;IAAY,CAAC,CACjC;IACF,eAAY;EAAW,GAEtBA,WAAW,iBACV,+CACE,oBAAC,cAAc,OAAG,eAClB;IAAM,SAAS,EAAC;EAAoB,GAAC,YAAU,CAAO,eACtD;IAAM,SAAS,EAAC;EAAmB,GAAC,QAAM,CAAO,CAEpD,EACA,CAACA,WAAW,IAAI,OAAO,CACjB,CACL,CACF,eACN;IAAK,SAAS,EAAC;EAAa,GACzBD,YAAY,IAAI,IAAI,iBACnB;IAAG,SAAS,EAAC,oBAAoB;IAAC,IAAI,EAAC;EAAO,aAAKA,YAAY,EAChE,CACG,CACD;AAEX;AAEA,eAAeF,SAAS"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { createContext } from 'react';
|
|
2
|
+
export var UserOverrideContext = /*#__PURE__*/createContext({});
|
|
3
|
+
export var UserPermissionsOverrideContext = /*#__PURE__*/createContext({});
|
|
4
|
+
export var UserContext = /*#__PURE__*/createContext(null);
|
|
5
|
+
//# sourceMappingURL=UserContexts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserContexts.js","names":["createContext","UserOverrideContext","UserPermissionsOverrideContext","UserContext"],"sources":["../src/UserContexts.ts"],"sourcesContent":["import { createContext } from 'react';\nimport { User, UserPermissions } from '@deephaven/redux';\n\nexport type UserOverride = Partial<Omit<User, 'permissions'>>;\n\nexport type UserPermissionsOverride = Partial<UserPermissions>;\n\nexport const UserOverrideContext = createContext<UserOverride>({});\n\nexport const UserPermissionsOverrideContext = createContext<UserPermissionsOverride>(\n {}\n);\n\nexport const UserContext = createContext<User | null>(null);\n"],"mappings":"AAAA,SAASA,aAAa,QAAQ,OAAO;AAOrC,OAAO,IAAMC,mBAAmB,gBAAGD,aAAa,CAAe,CAAC,CAAC,CAAC;AAElE,OAAO,IAAME,8BAA8B,gBAAGF,aAAa,CACzD,CAAC,CAAC,CACH;AAED,OAAO,IAAMG,WAAW,gBAAGH,aAAa,CAAc,IAAI,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
2
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
3
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
4
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
5
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
6
|
+
import Log from '@deephaven/log';
|
|
7
|
+
var log = Log.module('UserUtils');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Retrieve a value from the AppInit config
|
|
11
|
+
* @param serverConfig Server config map
|
|
12
|
+
* @param key The AppInit key to retrieve
|
|
13
|
+
* @returns The value for the AppInit key
|
|
14
|
+
*/
|
|
15
|
+
export function getAppInitValue(serverConfig, key) {
|
|
16
|
+
return serverConfig.get("internal.webClient.appInit.".concat(key));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Retrieve a user object provided the server config and overrides
|
|
21
|
+
* @param serverConfig Server config map
|
|
22
|
+
* @param overrides Override values for the user
|
|
23
|
+
* @param permissionsOverrides Override specific permissions for the user
|
|
24
|
+
* @returns The user object
|
|
25
|
+
*/
|
|
26
|
+
export function getUserFromConfig(serverConfig) {
|
|
27
|
+
var _getValue, _getValue2, _getValue$split, _getValue3;
|
|
28
|
+
var overrides = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
29
|
+
var permissionsOverrides = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
30
|
+
function getValue(key) {
|
|
31
|
+
return getAppInitValue(serverConfig, key);
|
|
32
|
+
}
|
|
33
|
+
function getBooleanValue(key, defaultValue) {
|
|
34
|
+
var value = getValue(key);
|
|
35
|
+
if (value === 'true') {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
if (value === 'false') {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
if (value !== undefined) {
|
|
42
|
+
log.warn("Unexpected value for ".concat(key, ": ").concat(value));
|
|
43
|
+
}
|
|
44
|
+
return defaultValue;
|
|
45
|
+
}
|
|
46
|
+
var name = (_getValue = getValue('name')) !== null && _getValue !== void 0 ? _getValue : '';
|
|
47
|
+
var operateAs = (_getValue2 = getValue('operateAs')) !== null && _getValue2 !== void 0 ? _getValue2 : name;
|
|
48
|
+
var groups = (_getValue$split = (_getValue3 = getValue('groups')) === null || _getValue3 === void 0 ? void 0 : _getValue3.split(',')) !== null && _getValue$split !== void 0 ? _getValue$split : [];
|
|
49
|
+
var canCopy = getBooleanValue('canCopy', true);
|
|
50
|
+
var canDownloadCsv = getBooleanValue('canDownloadCsv', true);
|
|
51
|
+
var canUsePanels = getBooleanValue('canUsePanels', true);
|
|
52
|
+
var canLogout = getBooleanValue('canLogout', true);
|
|
53
|
+
return _objectSpread(_objectSpread({
|
|
54
|
+
name,
|
|
55
|
+
operateAs,
|
|
56
|
+
groups
|
|
57
|
+
}, overrides), {}, {
|
|
58
|
+
permissions: _objectSpread({
|
|
59
|
+
canUsePanels,
|
|
60
|
+
canCopy,
|
|
61
|
+
canDownloadCsv,
|
|
62
|
+
canLogout
|
|
63
|
+
}, permissionsOverrides)
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
export default {
|
|
67
|
+
getAppInitValue,
|
|
68
|
+
getUser: getUserFromConfig
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=UserUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserUtils.js","names":["Log","log","module","getAppInitValue","serverConfig","key","get","getUserFromConfig","overrides","permissionsOverrides","getValue","getBooleanValue","defaultValue","value","undefined","warn","name","operateAs","groups","split","canCopy","canDownloadCsv","canUsePanels","canLogout","permissions","getUser"],"sources":["../src/UserUtils.ts"],"sourcesContent":["import { User, UserPermissions } from '@deephaven/redux';\nimport Log from '@deephaven/log';\n\nconst log = Log.module('UserUtils');\n\n/**\n * Retrieve a value from the AppInit config\n * @param serverConfig Server config map\n * @param key The AppInit key to retrieve\n * @returns The value for the AppInit key\n */\nexport function getAppInitValue(\n serverConfig: Map<string, string>,\n key: string\n): string | undefined {\n return serverConfig.get(`internal.webClient.appInit.${key}`);\n}\n\n/**\n * Retrieve a user object provided the server config and overrides\n * @param serverConfig Server config map\n * @param overrides Override values for the user\n * @param permissionsOverrides Override specific permissions for the user\n * @returns The user object\n */\nexport function getUserFromConfig(\n serverConfig: Map<string, string>,\n overrides: Partial<Omit<User, 'permissions'>> = {},\n permissionsOverrides: Partial<UserPermissions> = {}\n): User {\n function getValue(key: string): string | undefined {\n return getAppInitValue(serverConfig, key);\n }\n function getBooleanValue(key: string, defaultValue: boolean): boolean {\n const value = getValue(key);\n if (value === 'true') {\n return true;\n }\n if (value === 'false') {\n return false;\n }\n if (value !== undefined) {\n log.warn(`Unexpected value for ${key}: ${value}`);\n }\n return defaultValue;\n }\n const name = getValue('name') ?? '';\n const operateAs = getValue('operateAs') ?? name;\n const groups = getValue('groups')?.split(',') ?? [];\n const canCopy = getBooleanValue('canCopy', true);\n const canDownloadCsv = getBooleanValue('canDownloadCsv', true);\n const canUsePanels = getBooleanValue('canUsePanels', true);\n const canLogout = getBooleanValue('canLogout', true);\n\n return {\n name,\n operateAs,\n groups,\n ...overrides,\n permissions: {\n canUsePanels,\n canCopy,\n canDownloadCsv,\n canLogout,\n ...permissionsOverrides,\n },\n };\n}\n\nexport default { getAppInitValue, getUser: getUserFromConfig };\n"],"mappings":";;;;;AACA,OAAOA,GAAG,MAAM,gBAAgB;AAEhC,IAAMC,GAAG,GAAGD,GAAG,CAACE,MAAM,CAAC,WAAW,CAAC;;AAEnC;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,eAAe,CAC7BC,YAAiC,EACjCC,GAAW,EACS;EACpB,OAAOD,YAAY,CAACE,GAAG,sCAA+BD,GAAG,EAAG;AAC9D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASE,iBAAiB,CAC/BH,YAAiC,EAG3B;EAAA;EAAA,IAFNI,SAA6C,uEAAG,CAAC,CAAC;EAAA,IAClDC,oBAA8C,uEAAG,CAAC,CAAC;EAEnD,SAASC,QAAQ,CAACL,GAAW,EAAsB;IACjD,OAAOF,eAAe,CAACC,YAAY,EAAEC,GAAG,CAAC;EAC3C;EACA,SAASM,eAAe,CAACN,GAAW,EAAEO,YAAqB,EAAW;IACpE,IAAMC,KAAK,GAAGH,QAAQ,CAACL,GAAG,CAAC;IAC3B,IAAIQ,KAAK,KAAK,MAAM,EAAE;MACpB,OAAO,IAAI;IACb;IACA,IAAIA,KAAK,KAAK,OAAO,EAAE;MACrB,OAAO,KAAK;IACd;IACA,IAAIA,KAAK,KAAKC,SAAS,EAAE;MACvBb,GAAG,CAACc,IAAI,gCAAyBV,GAAG,eAAKQ,KAAK,EAAG;IACnD;IACA,OAAOD,YAAY;EACrB;EACA,IAAMI,IAAI,gBAAGN,QAAQ,CAAC,MAAM,CAAC,iDAAI,EAAE;EACnC,IAAMO,SAAS,iBAAGP,QAAQ,CAAC,WAAW,CAAC,mDAAIM,IAAI;EAC/C,IAAME,MAAM,oCAAGR,QAAQ,CAAC,QAAQ,CAAC,+CAAlB,WAAoBS,KAAK,CAAC,GAAG,CAAC,6DAAI,EAAE;EACnD,IAAMC,OAAO,GAAGT,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC;EAChD,IAAMU,cAAc,GAAGV,eAAe,CAAC,gBAAgB,EAAE,IAAI,CAAC;EAC9D,IAAMW,YAAY,GAAGX,eAAe,CAAC,cAAc,EAAE,IAAI,CAAC;EAC1D,IAAMY,SAAS,GAAGZ,eAAe,CAAC,WAAW,EAAE,IAAI,CAAC;EAEpD;IACEK,IAAI;IACJC,SAAS;IACTC;EAAM,GACHV,SAAS;IACZgB,WAAW;MACTF,YAAY;MACZF,OAAO;MACPC,cAAc;MACdE;IAAS,GACNd,oBAAoB;EACxB;AAEL;AAEA,eAAe;EAAEN,eAAe;EAAEsB,OAAO,EAAElB;AAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"declarations.d.js","names":[],"sources":["../src/declarations.d.ts"],"sourcesContent":["declare module '*.png';\n"],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from "./AuthPlugin.js";
|
|
2
|
+
export * from "./AuthHandlerTypes.js";
|
|
3
|
+
export { default as AuthPluginAnonymous } from "./AuthPluginAnonymous.js";
|
|
4
|
+
export { default as AuthPluginBase } from "./AuthPluginBase.js";
|
|
5
|
+
export { default as AuthPluginParent } from "./AuthPluginParent.js";
|
|
6
|
+
export { default as AuthPluginPsk } from "./AuthPluginPsk.js";
|
|
7
|
+
export * from "./Login.js";
|
|
8
|
+
export * from "./LoginForm.js";
|
|
9
|
+
export * from "./UserUtils.js";
|
|
10
|
+
export * from "./UserContexts.js";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["default","AuthPluginAnonymous","AuthPluginBase","AuthPluginParent","AuthPluginPsk"],"sources":["../src/index.ts"],"sourcesContent":["export * from './AuthPlugin';\nexport * from './AuthHandlerTypes';\nexport { default as AuthPluginAnonymous } from './AuthPluginAnonymous';\nexport { default as AuthPluginBase } from './AuthPluginBase';\nexport { default as AuthPluginParent } from './AuthPluginParent';\nexport { default as AuthPluginPsk } from './AuthPluginPsk';\nexport * from './Login';\nexport * from './LoginForm';\nexport * from './UserUtils';\nexport * from './UserContexts';\n"],"mappings":";;SAESA,OAAO,IAAIC,mBAAmB;AAAA,SAC9BD,OAAO,IAAIE,cAAc;AAAA,SACzBF,OAAO,IAAIG,gBAAgB;AAAA,SAC3BH,OAAO,IAAII,aAAa;AAAA;AAAA;AAAA;AAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deephaven/auth-plugins",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.44.0",
|
|
4
4
|
"description": "Deephaven Auth Plugins",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Deephaven",
|
|
@@ -33,14 +33,14 @@
|
|
|
33
33
|
"build:sass": "sass --embed-sources --load-path=../../node_modules ./src:./dist"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@deephaven/components": "^0.
|
|
37
|
-
"@deephaven/jsapi-bootstrap": "^0.
|
|
38
|
-
"@deephaven/jsapi-components": "^0.
|
|
39
|
-
"@deephaven/jsapi-types": "^0.
|
|
40
|
-
"@deephaven/jsapi-utils": "^0.
|
|
41
|
-
"@deephaven/log": "^0.
|
|
42
|
-
"@deephaven/redux": "^0.
|
|
43
|
-
"@deephaven/utils": "^0.
|
|
36
|
+
"@deephaven/components": "^0.44.0",
|
|
37
|
+
"@deephaven/jsapi-bootstrap": "^0.44.0",
|
|
38
|
+
"@deephaven/jsapi-components": "^0.44.0",
|
|
39
|
+
"@deephaven/jsapi-types": "^0.44.0",
|
|
40
|
+
"@deephaven/jsapi-utils": "^0.44.0",
|
|
41
|
+
"@deephaven/log": "^0.44.0",
|
|
42
|
+
"@deephaven/redux": "^0.44.0",
|
|
43
|
+
"@deephaven/utils": "^0.44.0",
|
|
44
44
|
"classnames": "^2.3.1",
|
|
45
45
|
"js-cookie": "^3.0.5",
|
|
46
46
|
"react-transition-group": "^4.4.2"
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"publishConfig": {
|
|
60
60
|
"access": "public"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "ba13c9139b3b7a5f5d64d79069f1de9d4727eeb6"
|
|
63
63
|
}
|