@jbrowse/plugin-authentication 4.3.0 → 5.0.0-beta.10
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/esm/DropboxOAuthModel/DropboxIcon.d.ts +1 -1
- package/esm/DropboxOAuthModel/configSchema.d.ts +154 -48
- package/esm/DropboxOAuthModel/configSchema.js +32 -2
- package/esm/DropboxOAuthModel/index.js +2 -2
- package/esm/DropboxOAuthModel/model.d.ts +301 -127
- package/esm/DropboxOAuthModel/model.js +46 -21
- package/esm/DropboxOAuthModel/util.d.ts +1 -1
- package/esm/DropboxOAuthModel/util.js +9 -12
- package/esm/ExternalTokenModel/ExternalTokenEntryForm.d.ts +1 -1
- package/esm/ExternalTokenModel/ExternalTokenEntryForm.js +11 -15
- package/esm/ExternalTokenModel/configSchema.d.ts +80 -19
- package/esm/ExternalTokenModel/configSchema.js +22 -1
- package/esm/ExternalTokenModel/index.js +2 -2
- package/esm/ExternalTokenModel/model.d.ts +49 -63
- package/esm/ExternalTokenModel/model.js +11 -54
- package/esm/GoogleDriveOAuthModel/GoogleDriveFilehandle.d.ts +2 -9
- package/esm/GoogleDriveOAuthModel/GoogleDriveFilehandle.js +27 -6
- package/esm/GoogleDriveOAuthModel/GoogleDriveIcon.d.ts +1 -1
- package/esm/GoogleDriveOAuthModel/configSchema.d.ts +152 -47
- package/esm/GoogleDriveOAuthModel/configSchema.js +32 -3
- package/esm/GoogleDriveOAuthModel/index.js +2 -2
- package/esm/GoogleDriveOAuthModel/model.d.ts +296 -128
- package/esm/GoogleDriveOAuthModel/model.js +45 -22
- package/esm/GoogleDriveOAuthModel/util.d.ts +1 -1
- package/esm/GoogleDriveOAuthModel/util.js +2 -11
- package/esm/HTTPBasicModel/HTTPBasicLoginForm.d.ts +1 -1
- package/esm/HTTPBasicModel/HTTPBasicLoginForm.js +17 -22
- package/esm/HTTPBasicModel/configSchema.d.ts +78 -21
- package/esm/HTTPBasicModel/configSchema.js +26 -1
- package/esm/HTTPBasicModel/index.js +2 -2
- package/esm/HTTPBasicModel/model.d.ts +57 -68
- package/esm/HTTPBasicModel/model.js +21 -51
- package/esm/OAuthModel/OAuthLoginPrompt.d.ts +4 -0
- package/esm/OAuthModel/OAuthLoginPrompt.js +12 -0
- package/esm/OAuthModel/configSchema.d.ts +81 -38
- package/esm/OAuthModel/configSchema.js +30 -1
- package/esm/OAuthModel/index.js +2 -2
- package/esm/OAuthModel/model.d.ts +231 -77
- package/esm/OAuthModel/model.js +361 -217
- package/esm/OAuthModel/util.d.ts +46 -7
- package/esm/OAuthModel/util.js +159 -16
- package/esm/index.d.ts +0 -1020
- package/esm/index.js +24 -57
- package/esm/lazyLoginForms.d.ts +18 -0
- package/esm/lazyLoginForms.js +25 -0
- package/esm/tokenEntryModelFactory.d.ts +135 -0
- package/esm/tokenEntryModelFactory.js +85 -0
- package/esm/util.d.ts +10 -0
- package/esm/util.js +24 -2
- package/package.json +10 -13
|
@@ -1,35 +1,59 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { ConfigurationReference } from '@jbrowse/core/configuration';
|
|
3
3
|
import { types } from '@jbrowse/mobx-state-tree';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import
|
|
4
|
+
import { configSchema as OAuthConfigSchema } from '../OAuthModel/index.js';
|
|
5
|
+
import baseModel from '../OAuthModel/model.js';
|
|
6
|
+
import { GoogleDriveFile } from './GoogleDriveFilehandle.js';
|
|
7
|
+
import GoogleDriveIcon from './GoogleDriveIcon.js';
|
|
8
|
+
import { getDescriptiveErrorMessage } from './util.js';
|
|
9
9
|
function getUri(str) {
|
|
10
|
-
const urlId =
|
|
11
|
-
|
|
10
|
+
const urlId = /\/d\/([-\w]{25,})/.exec(str);
|
|
11
|
+
if (!urlId) {
|
|
12
|
+
throw new Error(`Could not extract Google Drive file ID from URL: ${str}`);
|
|
13
|
+
}
|
|
14
|
+
return `https://www.googleapis.com/drive/v3/files/${urlId[1]}`;
|
|
12
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* #stateModel GoogleDriveOAuthInternetAccount
|
|
18
|
+
*/
|
|
13
19
|
export default function stateModelFactory(configSchema) {
|
|
14
20
|
return baseModel(OAuthConfigSchema)
|
|
15
21
|
.named('GoogleDriveOAuthInternetAccount')
|
|
16
22
|
.props({
|
|
23
|
+
/**
|
|
24
|
+
* #property
|
|
25
|
+
*/
|
|
17
26
|
type: types.literal('GoogleDriveOAuthInternetAccount'),
|
|
27
|
+
/**
|
|
28
|
+
* #property
|
|
29
|
+
*/
|
|
18
30
|
configuration: ConfigurationReference(configSchema),
|
|
19
31
|
})
|
|
20
32
|
.views(() => ({
|
|
33
|
+
/**
|
|
34
|
+
* #getter
|
|
35
|
+
* The FileSelector icon for Google drive
|
|
36
|
+
*/
|
|
21
37
|
get toggleContents() {
|
|
22
38
|
return _jsx(GoogleDriveIcon, {});
|
|
23
39
|
},
|
|
40
|
+
/**
|
|
41
|
+
* #getter
|
|
42
|
+
*/
|
|
24
43
|
get selectorLabel() {
|
|
25
44
|
return 'Enter Google Drive share link';
|
|
26
45
|
},
|
|
27
46
|
}))
|
|
28
47
|
.actions(self => ({
|
|
48
|
+
/**
|
|
49
|
+
* #method
|
|
50
|
+
*/
|
|
29
51
|
getFetcher(location) {
|
|
30
52
|
return async (input, init) => {
|
|
31
53
|
const driveUrl = new URL(getUri(String(input)));
|
|
32
54
|
const searchParams = new URLSearchParams();
|
|
55
|
+
// metadataOnly: private flag used by GoogleDriveFile constructor to
|
|
56
|
+
// pre-fetch just the file size for stat() without downloading content
|
|
33
57
|
if (init?.metadataOnly) {
|
|
34
58
|
searchParams.append('fields', 'size');
|
|
35
59
|
}
|
|
@@ -37,30 +61,29 @@ export default function stateModelFactory(configSchema) {
|
|
|
37
61
|
searchParams.append('alt', 'media');
|
|
38
62
|
}
|
|
39
63
|
driveUrl.search = searchParams.toString();
|
|
40
|
-
const
|
|
41
|
-
const response = await fetch(driveUrl, self.addAuthHeaderToInit({ ...init, method: 'GET', credentials: 'same-origin' }, authToken));
|
|
64
|
+
const response = await self.fetchWithToken(location, authToken => fetch(driveUrl, self.addAuthHeaderToInit({ ...init, method: 'GET', credentials: 'same-origin' }, authToken)));
|
|
42
65
|
if (!response.ok) {
|
|
43
66
|
throw new Error(await getDescriptiveErrorMessage(response));
|
|
44
67
|
}
|
|
45
68
|
return response;
|
|
46
69
|
};
|
|
47
70
|
},
|
|
71
|
+
/**
|
|
72
|
+
* #action
|
|
73
|
+
*/
|
|
74
|
+
async validateToken(token, location) {
|
|
75
|
+
const uri = getUri(location.uri);
|
|
76
|
+
return self.validateTokenWithProbe(token, authToken => fetch(uri, { headers: { Authorization: `Bearer ${authToken}` } }), getDescriptiveErrorMessage);
|
|
77
|
+
},
|
|
78
|
+
}))
|
|
79
|
+
.actions(self => ({
|
|
80
|
+
/**
|
|
81
|
+
* #method
|
|
82
|
+
*/
|
|
48
83
|
openLocation(location) {
|
|
49
84
|
return new GoogleDriveFile(location.uri, {
|
|
50
|
-
fetch:
|
|
51
|
-
});
|
|
52
|
-
},
|
|
53
|
-
async validateToken(token, location) {
|
|
54
|
-
const response = await fetch(getUri(location.uri), {
|
|
55
|
-
headers: {
|
|
56
|
-
Authorization: `Bearer ${token}`,
|
|
57
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
|
58
|
-
},
|
|
85
|
+
fetch: self.getFetcher(location),
|
|
59
86
|
});
|
|
60
|
-
if (!response.ok) {
|
|
61
|
-
throw new Error(await getDescriptiveErrorMessage(response, 'Token could not be validated'));
|
|
62
|
-
}
|
|
63
|
-
return token;
|
|
64
87
|
},
|
|
65
88
|
}));
|
|
66
89
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare
|
|
1
|
+
export declare const getDescriptiveErrorMessage: (response: Response, reason?: string) => Promise<string>;
|
|
@@ -1,11 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export
|
|
3
|
-
let errorMessage = '';
|
|
4
|
-
try {
|
|
5
|
-
const err = JSON.parse(await response.text());
|
|
6
|
-
errorMessage = err.error.message;
|
|
7
|
-
}
|
|
8
|
-
catch (error) {
|
|
9
|
-
}
|
|
10
|
-
return getResponseError({ response, reason, statusText: errorMessage });
|
|
11
|
-
}
|
|
1
|
+
import { descriptiveErrorMessage } from '../util.js';
|
|
2
|
+
export const getDescriptiveErrorMessage = descriptiveErrorMessage(err => err.error.message);
|
|
@@ -1,29 +1,24 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { SubmitDialog } from '@jbrowse/core/ui';
|
|
4
|
+
import { TextField } from '@mui/material';
|
|
5
5
|
export function HTTPBasicLoginForm({ internetAccountId, handleClose, }) {
|
|
6
6
|
const [username, setUsername] = useState('');
|
|
7
7
|
const [password, setPassword] = useState('');
|
|
8
|
-
return (_jsx(
|
|
8
|
+
return (_jsx(SubmitDialog, { open: true, maxWidth: "xl", "data-testid": "login-httpbasic", title: `Log in for ${internetAccountId}`,
|
|
9
|
+
// an incomplete submit used to close as if cancelled, which the account
|
|
10
|
+
// reports as "User cancelled entry" — a failed login the user never made
|
|
11
|
+
submitDisabled: !username || !password, onCancel: () => {
|
|
9
12
|
handleClose();
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
htmlInput: { 'data-testid': 'login-httpbasic-username' },
|
|
22
|
-
} }), _jsx(TextField, { required: true, label: "Password", type: "password", autoComplete: "current-password", variant: "outlined", onChange: event => {
|
|
23
|
-
setPassword(event.target.value);
|
|
24
|
-
}, margin: "dense", slotProps: {
|
|
25
|
-
htmlInput: { 'data-testid': 'login-httpbasic-password' },
|
|
26
|
-
} })] }), _jsxs(DialogActions, { children: [_jsx(Button, { variant: "contained", color: "primary", type: "submit", children: "Submit" }), _jsx(Button, { variant: "contained", color: "secondary", type: "submit", onClick: () => {
|
|
27
|
-
handleClose();
|
|
28
|
-
}, children: "Cancel" })] })] }) }));
|
|
13
|
+
}, onSubmit: () => {
|
|
14
|
+
handleClose(btoa(`${username}:${password}`));
|
|
15
|
+
}, children: _jsxs("div", { style: { display: 'flex', flexDirection: 'column' }, children: [_jsx(TextField, { required: true, label: "Username", variant: "outlined", onChange: event => {
|
|
16
|
+
setUsername(event.target.value);
|
|
17
|
+
}, margin: "dense", slotProps: {
|
|
18
|
+
htmlInput: { 'data-testid': 'login-httpbasic-username' },
|
|
19
|
+
} }), _jsx(TextField, { required: true, label: "Password", type: "password", autoComplete: "current-password", variant: "outlined", onChange: event => {
|
|
20
|
+
setPassword(event.target.value);
|
|
21
|
+
}, margin: "dense", slotProps: {
|
|
22
|
+
htmlInput: { 'data-testid': 'login-httpbasic-password' },
|
|
23
|
+
} })] }) }));
|
|
29
24
|
}
|
|
@@ -1,42 +1,99 @@
|
|
|
1
1
|
import type { Instance } from '@jbrowse/mobx-state-tree';
|
|
2
|
+
/**
|
|
3
|
+
* #config HTTPBasicInternetAccount
|
|
4
|
+
*
|
|
5
|
+
* #example
|
|
6
|
+
* An entry in the config's `internetAccounts`. JBrowse prompts for the username
|
|
7
|
+
* and password the first time a file under one of `domains` is opened, and
|
|
8
|
+
* sends them as an `Authorization: Basic …` header from then on.
|
|
9
|
+
* ```js
|
|
10
|
+
* {
|
|
11
|
+
* type: 'HTTPBasicInternetAccount',
|
|
12
|
+
* internetAccountId: 'myLabServer',
|
|
13
|
+
* name: 'My lab server',
|
|
14
|
+
* description: 'Sequencing data behind the lab htaccess',
|
|
15
|
+
* domains: ['data.mylab.org'],
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
2
19
|
declare const HTTPBasicConfigSchema: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
20
|
+
authHeader: {
|
|
21
|
+
type: "string";
|
|
22
|
+
} & {
|
|
23
|
+
defaultValue: string;
|
|
24
|
+
};
|
|
25
|
+
description: {
|
|
26
|
+
type: "string";
|
|
27
|
+
} & {
|
|
28
|
+
defaultValue: string;
|
|
29
|
+
};
|
|
30
|
+
domains: {
|
|
31
|
+
type: "stringArray";
|
|
32
|
+
} & {
|
|
33
|
+
defaultValue: unknown;
|
|
34
|
+
};
|
|
35
|
+
internetAccountId: {
|
|
36
|
+
type: "string";
|
|
37
|
+
} & {
|
|
38
|
+
defaultValue: string;
|
|
39
|
+
};
|
|
40
|
+
name: {
|
|
41
|
+
type: "string";
|
|
42
|
+
} & {
|
|
43
|
+
defaultValue: string;
|
|
44
|
+
};
|
|
3
45
|
tokenType: {
|
|
4
|
-
|
|
5
|
-
|
|
46
|
+
type: "string";
|
|
47
|
+
} & {
|
|
48
|
+
defaultValue: string;
|
|
49
|
+
};
|
|
50
|
+
type: {
|
|
51
|
+
type: "string";
|
|
52
|
+
} & {
|
|
6
53
|
defaultValue: string;
|
|
7
54
|
};
|
|
8
55
|
validateWithHEAD: {
|
|
9
|
-
|
|
10
|
-
|
|
56
|
+
type: "boolean";
|
|
57
|
+
} & {
|
|
11
58
|
defaultValue: boolean;
|
|
12
59
|
};
|
|
13
60
|
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
14
|
-
name: {
|
|
15
|
-
|
|
16
|
-
|
|
61
|
+
readonly name: {
|
|
62
|
+
type: "string";
|
|
63
|
+
} & {
|
|
17
64
|
defaultValue: string;
|
|
18
65
|
};
|
|
19
|
-
description: {
|
|
20
|
-
|
|
21
|
-
|
|
66
|
+
readonly description: {
|
|
67
|
+
type: "string";
|
|
68
|
+
} & {
|
|
22
69
|
defaultValue: string;
|
|
23
70
|
};
|
|
24
|
-
authHeader: {
|
|
25
|
-
|
|
26
|
-
|
|
71
|
+
readonly authHeader: {
|
|
72
|
+
type: "string";
|
|
73
|
+
} & {
|
|
27
74
|
defaultValue: string;
|
|
28
75
|
};
|
|
29
|
-
tokenType: {
|
|
30
|
-
|
|
31
|
-
|
|
76
|
+
readonly tokenType: {
|
|
77
|
+
type: "string";
|
|
78
|
+
} & {
|
|
32
79
|
defaultValue: string;
|
|
33
80
|
};
|
|
34
|
-
domains: {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
defaultValue:
|
|
81
|
+
readonly domains: {
|
|
82
|
+
type: "stringArray";
|
|
83
|
+
} & {
|
|
84
|
+
defaultValue: unknown;
|
|
85
|
+
};
|
|
86
|
+
type: {
|
|
87
|
+
type: "string";
|
|
88
|
+
} & {
|
|
89
|
+
defaultValue: string;
|
|
90
|
+
};
|
|
91
|
+
internetAccountId: {
|
|
92
|
+
type: "string";
|
|
93
|
+
} & {
|
|
94
|
+
defaultValue: string;
|
|
38
95
|
};
|
|
39
|
-
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "internetAccountId">>, undefined>>;
|
|
96
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "internetAccountId", true, import("@jbrowse/core/configuration").ConfigurationSchemaRequirement<Partial<Record<string, string[]>>, string>, any>>, undefined, true, import("@jbrowse/core/configuration").ConfigurationSchemaRequirement<Partial<Record<string, string[]>>, string>, any>>;
|
|
40
97
|
export type HTTPBasicInternetAccountConfigModel = typeof HTTPBasicConfigSchema;
|
|
41
98
|
export type HTTPBasicInternetAccountConfig = Instance<HTTPBasicInternetAccountConfigModel>;
|
|
42
99
|
export default HTTPBasicConfigSchema;
|
|
@@ -1,18 +1,43 @@
|
|
|
1
1
|
import { ConfigurationSchema } from '@jbrowse/core/configuration';
|
|
2
2
|
import { BaseInternetAccountConfig } from '@jbrowse/core/pluggableElementTypes/models';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* #config HTTPBasicInternetAccount
|
|
5
|
+
*
|
|
6
|
+
* #example
|
|
7
|
+
* An entry in the config's `internetAccounts`. JBrowse prompts for the username
|
|
8
|
+
* and password the first time a file under one of `domains` is opened, and
|
|
9
|
+
* sends them as an `Authorization: Basic …` header from then on.
|
|
10
|
+
* ```js
|
|
11
|
+
* {
|
|
12
|
+
* type: 'HTTPBasicInternetAccount',
|
|
13
|
+
* internetAccountId: 'myLabServer',
|
|
14
|
+
* name: 'My lab server',
|
|
15
|
+
* description: 'Sequencing data behind the lab htaccess',
|
|
16
|
+
* domains: ['data.mylab.org'],
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
4
20
|
const HTTPBasicConfigSchema = ConfigurationSchema('HTTPBasicInternetAccount', {
|
|
21
|
+
/**
|
|
22
|
+
* #slot
|
|
23
|
+
*/
|
|
5
24
|
tokenType: {
|
|
6
25
|
description: 'a custom name for a token to include in the header',
|
|
7
26
|
type: 'string',
|
|
8
27
|
defaultValue: 'Basic',
|
|
9
28
|
},
|
|
29
|
+
/**
|
|
30
|
+
* #slot
|
|
31
|
+
*/
|
|
10
32
|
validateWithHEAD: {
|
|
11
33
|
description: 'validate the token with a HEAD request before using it',
|
|
12
34
|
type: 'boolean',
|
|
13
35
|
defaultValue: true,
|
|
14
36
|
},
|
|
15
37
|
}, {
|
|
38
|
+
/**
|
|
39
|
+
* #baseConfiguration
|
|
40
|
+
*/
|
|
16
41
|
baseConfiguration: BaseInternetAccountConfig,
|
|
17
42
|
explicitlyTyped: true,
|
|
18
43
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { default as configSchema } from
|
|
2
|
-
export { default as modelFactory } from
|
|
1
|
+
export { default as configSchema } from './configSchema.js';
|
|
2
|
+
export { default as modelFactory } from './model.js';
|
|
@@ -1,76 +1,55 @@
|
|
|
1
1
|
import type { HTTPBasicInternetAccountConfigModel } from './configSchema.ts';
|
|
2
|
-
import type { UriLocation } from '@jbrowse/core/util/types';
|
|
3
2
|
import type { Instance } from '@jbrowse/mobx-state-tree';
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* #stateModel HTTPBasicInternetAccount
|
|
5
|
+
* Internet account that authenticates requests with an HTTP Basic
|
|
6
|
+
* username/password the user enters through a dialog, optionally validated with
|
|
7
|
+
* a HEAD request. See [TokenEntryInternetAccount](../tokenentryinternetaccount)
|
|
8
|
+
* for the shared behavior.
|
|
9
|
+
*/
|
|
10
|
+
declare const stateModelFactory: (configSchema: HTTPBasicInternetAccountConfigModel) => import("@jbrowse/mobx-state-tree").IModelType<Omit<{
|
|
5
11
|
id: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
6
12
|
type: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
|
|
7
|
-
configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
8
|
-
name: {
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
configuration: import("@jbrowse/core/configuration/configurationSchema").IConfigurationReference<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
14
|
+
readonly name: {
|
|
15
|
+
type: "string";
|
|
16
|
+
} & {
|
|
11
17
|
defaultValue: string;
|
|
12
18
|
};
|
|
13
|
-
description: {
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
readonly description: {
|
|
20
|
+
type: "string";
|
|
21
|
+
} & {
|
|
16
22
|
defaultValue: string;
|
|
17
23
|
};
|
|
18
|
-
authHeader: {
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
readonly authHeader: {
|
|
25
|
+
type: "string";
|
|
26
|
+
} & {
|
|
21
27
|
defaultValue: string;
|
|
22
28
|
};
|
|
23
|
-
tokenType: {
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
readonly tokenType: {
|
|
30
|
+
type: "string";
|
|
31
|
+
} & {
|
|
26
32
|
defaultValue: string;
|
|
27
33
|
};
|
|
28
|
-
domains: {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
defaultValue:
|
|
34
|
+
readonly domains: {
|
|
35
|
+
type: "stringArray";
|
|
36
|
+
} & {
|
|
37
|
+
defaultValue: unknown;
|
|
32
38
|
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
37
|
-
tokenType: {
|
|
38
|
-
description: string;
|
|
39
|
-
type: string;
|
|
40
|
-
defaultValue: string;
|
|
41
|
-
};
|
|
42
|
-
validateWithHEAD: {
|
|
43
|
-
description: string;
|
|
44
|
-
type: string;
|
|
45
|
-
defaultValue: boolean;
|
|
46
|
-
};
|
|
47
|
-
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
48
|
-
name: {
|
|
49
|
-
description: string;
|
|
50
|
-
type: string;
|
|
51
|
-
defaultValue: string;
|
|
52
|
-
};
|
|
53
|
-
description: {
|
|
54
|
-
description: string;
|
|
55
|
-
type: string;
|
|
56
|
-
defaultValue: string;
|
|
57
|
-
};
|
|
58
|
-
authHeader: {
|
|
59
|
-
description: string;
|
|
60
|
-
type: string;
|
|
39
|
+
type: {
|
|
40
|
+
type: "string";
|
|
41
|
+
} & {
|
|
61
42
|
defaultValue: string;
|
|
62
43
|
};
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
44
|
+
internetAccountId: {
|
|
45
|
+
type: "string";
|
|
46
|
+
} & {
|
|
66
47
|
defaultValue: string;
|
|
67
48
|
};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
};
|
|
73
|
-
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "internetAccountId">>, undefined>>;
|
|
49
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "internetAccountId", true, import("@jbrowse/core/configuration").ConfigurationSchemaRequirement<Partial<Record<string, string[]>>, string>, any>>>;
|
|
50
|
+
}, "configuration" | "type"> & {
|
|
51
|
+
type: import("@jbrowse/mobx-state-tree").ILiteralType<"HTTPBasicInternetAccount">;
|
|
52
|
+
configuration: import("@jbrowse/core/configuration/configurationSchema").IConfigurationReference<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>;
|
|
74
53
|
}, {
|
|
75
54
|
readonly name: string;
|
|
76
55
|
readonly description: string;
|
|
@@ -79,22 +58,21 @@ declare const stateModelFactory: (configSchema: HTTPBasicInternetAccountConfigMo
|
|
|
79
58
|
readonly tokenType: string;
|
|
80
59
|
readonly domains: string[];
|
|
81
60
|
readonly toggleContents: React.ReactNode;
|
|
82
|
-
readonly SelectorComponent: import("@jbrowse/core/util").AnyReactComponentType | undefined;
|
|
83
61
|
readonly selectorLabel: string | undefined;
|
|
62
|
+
readonly showInFileSelector: boolean;
|
|
84
63
|
} & {
|
|
85
|
-
handlesLocation(location: UriLocation): boolean;
|
|
64
|
+
handlesLocation(location: import("@jbrowse/core/util").UriLocation): boolean;
|
|
86
65
|
readonly tokenKey: string;
|
|
87
66
|
} & {
|
|
88
67
|
getTokenFromUser(_resolve: (token: string) => void, _reject: (error: Error) => void): void;
|
|
89
68
|
storeToken(token: string): void;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
validateToken(token: string, _loc: UriLocation): Promise<string>;
|
|
69
|
+
retrieveToken(): string | undefined;
|
|
70
|
+
validateToken(token: string, _loc: import("@jbrowse/core/util").UriLocation): Promise<string>;
|
|
93
71
|
} & {
|
|
94
|
-
|
|
72
|
+
removeToken(): void;
|
|
73
|
+
getToken(location?: import("@jbrowse/core/util").UriLocation): Promise<string>;
|
|
95
74
|
} & {
|
|
96
75
|
addAuthHeaderToInit(init?: RequestInit, token?: string): {
|
|
97
|
-
headers: Headers;
|
|
98
76
|
body?: BodyInit | null;
|
|
99
77
|
cache?: RequestCache;
|
|
100
78
|
credentials?: RequestCredentials;
|
|
@@ -108,23 +86,34 @@ declare const stateModelFactory: (configSchema: HTTPBasicInternetAccountConfigMo
|
|
|
108
86
|
referrerPolicy?: ReferrerPolicy;
|
|
109
87
|
signal?: AbortSignal | null;
|
|
110
88
|
window?: null;
|
|
89
|
+
headers: Headers;
|
|
111
90
|
};
|
|
112
|
-
|
|
91
|
+
fetchWithToken(loc: import("@jbrowse/core/util").UriLocation | undefined, run: (token: string) => Promise<Response>): Promise<Response>;
|
|
92
|
+
getPreAuthorizationInformation(location: import("@jbrowse/core/util").UriLocation): Promise<{
|
|
113
93
|
internetAccountType: string;
|
|
114
94
|
authInfo: {
|
|
115
95
|
token: string;
|
|
116
|
-
configuration: any
|
|
96
|
+
configuration: import("@jbrowse/mobx-state-tree").ModelSnapshotType<Record<string, any>>;
|
|
117
97
|
};
|
|
118
98
|
}>;
|
|
119
99
|
} & {
|
|
120
|
-
getFetcher(loc?: UriLocation): (input: RequestInfo, init?: RequestInit) => Promise<Response>;
|
|
100
|
+
getFetcher(loc?: import("@jbrowse/core/util").UriLocation): (input: RequestInfo, init?: RequestInit) => Promise<Response>;
|
|
121
101
|
} & {
|
|
122
|
-
openLocation(location:
|
|
102
|
+
openLocation(location: import("@jbrowse/core/util").UriLocation): import("@gmod/range-cache-filehandle").RemoteFileWithRangeCache;
|
|
123
103
|
} & {
|
|
124
104
|
readonly validateWithHEAD: boolean;
|
|
125
105
|
} & {
|
|
126
106
|
getTokenFromUser(resolve: (token: string) => void, reject: (error: Error) => void): void;
|
|
127
|
-
validateToken(token: string, location: UriLocation): Promise<string>;
|
|
107
|
+
validateToken(token: string, location: import("@jbrowse/core/util").UriLocation): Promise<string>;
|
|
108
|
+
} & {
|
|
109
|
+
/**
|
|
110
|
+
* #getter
|
|
111
|
+
* There is nothing to pick: an HTTP Basic account matches by domain and
|
|
112
|
+
* prompts on its own. RpcManager also mints one of these per origin on a
|
|
113
|
+
* 401, so offering them would fill the picker with a toggle per server the
|
|
114
|
+
* session happened to touch.
|
|
115
|
+
*/
|
|
116
|
+
readonly showInFileSelector: boolean;
|
|
128
117
|
}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>;
|
|
129
118
|
export default stateModelFactory;
|
|
130
119
|
export type HTTPBasicStateModel = ReturnType<typeof stateModelFactory>;
|
|
@@ -1,52 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
{
|
|
23
|
-
internetAccountId: self.internetAccountId,
|
|
24
|
-
handleClose: (token) => {
|
|
25
|
-
if (token) {
|
|
26
|
-
resolve(token);
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
reject(new Error('User cancelled entry'));
|
|
30
|
-
}
|
|
31
|
-
doneCallback();
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
]);
|
|
35
|
-
},
|
|
36
|
-
async validateToken(token, location) {
|
|
37
|
-
if (!self.validateWithHEAD) {
|
|
38
|
-
return token;
|
|
39
|
-
}
|
|
40
|
-
const newInit = self.addAuthHeaderToInit({ method: 'HEAD' }, token);
|
|
41
|
-
const response = await fetch(location.uri, newInit);
|
|
42
|
-
if (!response.ok) {
|
|
43
|
-
throw new Error(await getResponseError({
|
|
44
|
-
response,
|
|
45
|
-
reason: 'Error validating token',
|
|
46
|
-
}));
|
|
47
|
-
}
|
|
48
|
-
return token;
|
|
49
|
-
},
|
|
50
|
-
}));
|
|
51
|
-
};
|
|
1
|
+
import { HTTPBasicLoginForm } from '../lazyLoginForms.js';
|
|
2
|
+
import { tokenEntryModelFactory } from '../tokenEntryModelFactory.js';
|
|
3
|
+
/**
|
|
4
|
+
* #stateModel HTTPBasicInternetAccount
|
|
5
|
+
* Internet account that authenticates requests with an HTTP Basic
|
|
6
|
+
* username/password the user enters through a dialog, optionally validated with
|
|
7
|
+
* a HEAD request. See [TokenEntryInternetAccount](../tokenentryinternetaccount)
|
|
8
|
+
* for the shared behavior.
|
|
9
|
+
*/
|
|
10
|
+
const stateModelFactory = (configSchema) => tokenEntryModelFactory('HTTPBasicInternetAccount', 'HTTPBasicInternetAccount', configSchema, HTTPBasicLoginForm).views(() => ({
|
|
11
|
+
/**
|
|
12
|
+
* #getter
|
|
13
|
+
* There is nothing to pick: an HTTP Basic account matches by domain and
|
|
14
|
+
* prompts on its own. RpcManager also mints one of these per origin on a
|
|
15
|
+
* 401, so offering them would fill the picker with a toggle per server the
|
|
16
|
+
* session happened to touch.
|
|
17
|
+
*/
|
|
18
|
+
get showInFileSelector() {
|
|
19
|
+
return false;
|
|
20
|
+
},
|
|
21
|
+
}));
|
|
52
22
|
export default stateModelFactory;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Dialog } from '@jbrowse/core/ui';
|
|
3
|
+
import { Button, DialogActions, DialogContent, Typography } from '@mui/material';
|
|
4
|
+
export function OAuthLoginPrompt({ internetAccountId, handleClose, }) {
|
|
5
|
+
return (_jsxs(Dialog, { open: true, maxWidth: "xs", "data-testid": "oauth-login-prompt", title: `Log in to ${internetAccountId}`, onClose: () => {
|
|
6
|
+
handleClose(false);
|
|
7
|
+
}, children: [_jsx(DialogContent, { children: _jsxs(Typography, { children: ["This session has a track that needs you to log in to", ' ', internetAccountId, ". Browsers only allow the login window to open from a click, so it could not be opened on your behalf."] }) }), _jsxs(DialogActions, { children: [_jsx(Button, { color: "secondary", variant: "contained", onClick: () => {
|
|
8
|
+
handleClose(false);
|
|
9
|
+
}, children: "Cancel" }), _jsx(Button, { color: "primary", variant: "contained", onClick: () => {
|
|
10
|
+
handleClose(true);
|
|
11
|
+
}, children: "Log in" })] })] }));
|
|
12
|
+
}
|