@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 +1 @@
|
|
|
1
|
-
export declare
|
|
1
|
+
export declare const getDescriptiveErrorMessage: (response: Response, reason?: string) => Promise<string>;
|
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { descriptiveErrorMessage } from '../util.js';
|
|
2
|
+
/**
|
|
3
|
+
* Error messages from
|
|
4
|
+
* https://www.dropbox.com/developers/documentation/http/documentation#sharing-get_shared_link_file
|
|
5
|
+
* */
|
|
2
6
|
const dropboxErrorMessages = {
|
|
3
7
|
shared_link_not_found: "The shared link wasn't found.",
|
|
4
8
|
shared_link_access_denied: 'The caller is not allowed to access this shared link.',
|
|
5
9
|
unsupported_link_type: 'This type of link is not supported; use files/export instead.',
|
|
6
10
|
shared_link_is_directory: 'Directories cannot be retrieved by this endpoint.',
|
|
7
11
|
};
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const tag = err.error['.tag'];
|
|
13
|
-
errorMessage = dropboxErrorMessages[tag] || tag;
|
|
14
|
-
}
|
|
15
|
-
catch (error) {
|
|
16
|
-
}
|
|
17
|
-
return getResponseError({ response, reason, statusText: errorMessage });
|
|
18
|
-
}
|
|
12
|
+
export const getDescriptiveErrorMessage = descriptiveErrorMessage(err => {
|
|
13
|
+
const tag = err.error['.tag'];
|
|
14
|
+
return dropboxErrorMessages[tag] ?? tag;
|
|
15
|
+
});
|
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
1
|
+
import { jsx as _jsx } 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 const ExternalTokenEntryForm = ({ internetAccountId, handleClose, }) => {
|
|
6
6
|
const [token, setToken] = useState('');
|
|
7
|
-
return (
|
|
7
|
+
return (_jsx(SubmitDialog, { open: true, maxWidth: "xl", "data-testid": "externalToken-form", title: `Enter token for ${internetAccountId}`, submitText: "Add", submitDisabled: !token, onCancel: () => {
|
|
8
8
|
handleClose();
|
|
9
|
-
},
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
}, children: "Add" }), _jsx(Button, { variant: "contained", color: "secondary", onClick: () => {
|
|
18
|
-
handleClose();
|
|
19
|
-
}, children: "Cancel" })] })] }));
|
|
9
|
+
}, onSubmit: () => {
|
|
10
|
+
handleClose(token);
|
|
11
|
+
}, children: _jsx(TextField, { required: true, label: "Enter Token", variant: "outlined", onChange: event => {
|
|
12
|
+
setToken(event.target.value);
|
|
13
|
+
}, margin: "dense", slotProps: {
|
|
14
|
+
htmlInput: { 'data-testid': 'entry-externalToken' },
|
|
15
|
+
} }) }));
|
|
20
16
|
};
|
|
@@ -1,37 +1,98 @@
|
|
|
1
1
|
import type { Instance } from '@jbrowse/mobx-state-tree';
|
|
2
|
+
/**
|
|
3
|
+
* #config ExternalTokenInternetAccount
|
|
4
|
+
*
|
|
5
|
+
* #example
|
|
6
|
+
* For a token the user pastes in, or that an embedding portal hands over.
|
|
7
|
+
* JBrowse does not obtain the token itself — it prompts for one, then sends it
|
|
8
|
+
* on every request to a matching domain.
|
|
9
|
+
* ```js
|
|
10
|
+
* {
|
|
11
|
+
* type: 'ExternalTokenInternetAccount',
|
|
12
|
+
* internetAccountId: 'portalToken',
|
|
13
|
+
* name: 'Data portal token',
|
|
14
|
+
* domains: ['api.myportal.org'],
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
2
18
|
declare const ExternalTokenConfigSchema: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
19
|
+
authHeader: {
|
|
20
|
+
type: "string";
|
|
21
|
+
} & {
|
|
22
|
+
defaultValue: string;
|
|
23
|
+
};
|
|
24
|
+
description: {
|
|
25
|
+
type: "string";
|
|
26
|
+
} & {
|
|
27
|
+
defaultValue: string;
|
|
28
|
+
};
|
|
29
|
+
domains: {
|
|
30
|
+
type: "stringArray";
|
|
31
|
+
} & {
|
|
32
|
+
defaultValue: unknown;
|
|
33
|
+
};
|
|
34
|
+
internetAccountId: {
|
|
35
|
+
type: "string";
|
|
36
|
+
} & {
|
|
37
|
+
defaultValue: string;
|
|
38
|
+
};
|
|
39
|
+
name: {
|
|
40
|
+
type: "string";
|
|
41
|
+
} & {
|
|
42
|
+
defaultValue: string;
|
|
43
|
+
};
|
|
44
|
+
tokenType: {
|
|
45
|
+
type: "string";
|
|
46
|
+
} & {
|
|
47
|
+
defaultValue: string;
|
|
48
|
+
};
|
|
49
|
+
type: {
|
|
50
|
+
type: "string";
|
|
51
|
+
} & {
|
|
52
|
+
defaultValue: string;
|
|
53
|
+
};
|
|
3
54
|
validateWithHEAD: {
|
|
4
|
-
|
|
5
|
-
|
|
55
|
+
type: "boolean";
|
|
56
|
+
} & {
|
|
6
57
|
defaultValue: boolean;
|
|
7
58
|
};
|
|
8
59
|
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
9
|
-
name: {
|
|
10
|
-
|
|
11
|
-
|
|
60
|
+
readonly name: {
|
|
61
|
+
type: "string";
|
|
62
|
+
} & {
|
|
12
63
|
defaultValue: string;
|
|
13
64
|
};
|
|
14
|
-
description: {
|
|
15
|
-
|
|
16
|
-
|
|
65
|
+
readonly description: {
|
|
66
|
+
type: "string";
|
|
67
|
+
} & {
|
|
17
68
|
defaultValue: string;
|
|
18
69
|
};
|
|
19
|
-
authHeader: {
|
|
20
|
-
|
|
21
|
-
|
|
70
|
+
readonly authHeader: {
|
|
71
|
+
type: "string";
|
|
72
|
+
} & {
|
|
22
73
|
defaultValue: string;
|
|
23
74
|
};
|
|
24
|
-
tokenType: {
|
|
25
|
-
|
|
26
|
-
|
|
75
|
+
readonly tokenType: {
|
|
76
|
+
type: "string";
|
|
77
|
+
} & {
|
|
27
78
|
defaultValue: string;
|
|
28
79
|
};
|
|
29
|
-
domains: {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
defaultValue:
|
|
80
|
+
readonly domains: {
|
|
81
|
+
type: "stringArray";
|
|
82
|
+
} & {
|
|
83
|
+
defaultValue: unknown;
|
|
84
|
+
};
|
|
85
|
+
type: {
|
|
86
|
+
type: "string";
|
|
87
|
+
} & {
|
|
88
|
+
defaultValue: string;
|
|
89
|
+
};
|
|
90
|
+
internetAccountId: {
|
|
91
|
+
type: "string";
|
|
92
|
+
} & {
|
|
93
|
+
defaultValue: string;
|
|
33
94
|
};
|
|
34
|
-
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "internetAccountId">>, undefined>>;
|
|
95
|
+
}, 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>>;
|
|
35
96
|
export type ExternalTokenInternetAccountConfigModel = typeof ExternalTokenConfigSchema;
|
|
36
97
|
export type ExternalTokenInternetAccountConfig = Instance<ExternalTokenInternetAccountConfigModel>;
|
|
37
98
|
export default ExternalTokenConfigSchema;
|
|
@@ -1,13 +1,34 @@
|
|
|
1
1
|
import { ConfigurationSchema } from '@jbrowse/core/configuration';
|
|
2
2
|
import { BaseInternetAccountConfig } from '@jbrowse/core/pluggableElementTypes/models';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* #config ExternalTokenInternetAccount
|
|
5
|
+
*
|
|
6
|
+
* #example
|
|
7
|
+
* For a token the user pastes in, or that an embedding portal hands over.
|
|
8
|
+
* JBrowse does not obtain the token itself — it prompts for one, then sends it
|
|
9
|
+
* on every request to a matching domain.
|
|
10
|
+
* ```js
|
|
11
|
+
* {
|
|
12
|
+
* type: 'ExternalTokenInternetAccount',
|
|
13
|
+
* internetAccountId: 'portalToken',
|
|
14
|
+
* name: 'Data portal token',
|
|
15
|
+
* domains: ['api.myportal.org'],
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
4
19
|
const ExternalTokenConfigSchema = ConfigurationSchema('ExternalTokenInternetAccount', {
|
|
20
|
+
/**
|
|
21
|
+
* #slot
|
|
22
|
+
*/
|
|
5
23
|
validateWithHEAD: {
|
|
6
24
|
description: 'validate the token with a HEAD request before using it',
|
|
7
25
|
type: 'boolean',
|
|
8
26
|
defaultValue: true,
|
|
9
27
|
},
|
|
10
28
|
}, {
|
|
29
|
+
/**
|
|
30
|
+
* #baseConfiguration
|
|
31
|
+
*/
|
|
11
32
|
baseConfiguration: BaseInternetAccountConfig,
|
|
12
33
|
explicitlyTyped: true,
|
|
13
34
|
});
|
|
@@ -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,71 +1,56 @@
|
|
|
1
1
|
import type { ExternalTokenInternetAccountConfigModel } 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 ExternalTokenInternetAccount
|
|
5
|
+
* Internet account that authenticates requests with a user-supplied external
|
|
6
|
+
* token, prompting for the token via a dialog and optionally validating it with
|
|
7
|
+
* a HEAD request. See
|
|
8
|
+
* [TokenEntryInternetAccount](../tokenentryinternetaccount) for the shared
|
|
9
|
+
* behavior.
|
|
10
|
+
*/
|
|
11
|
+
declare const stateModelFactory: (configSchema: ExternalTokenInternetAccountConfigModel) => import("@jbrowse/mobx-state-tree").IModelType<Omit<{
|
|
5
12
|
id: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
6
13
|
type: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
|
|
7
|
-
configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
8
|
-
name: {
|
|
9
|
-
|
|
10
|
-
|
|
14
|
+
configuration: import("@jbrowse/core/configuration/configurationSchema").IConfigurationReference<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
15
|
+
readonly name: {
|
|
16
|
+
type: "string";
|
|
17
|
+
} & {
|
|
11
18
|
defaultValue: string;
|
|
12
19
|
};
|
|
13
|
-
description: {
|
|
14
|
-
|
|
15
|
-
|
|
20
|
+
readonly description: {
|
|
21
|
+
type: "string";
|
|
22
|
+
} & {
|
|
16
23
|
defaultValue: string;
|
|
17
24
|
};
|
|
18
|
-
authHeader: {
|
|
19
|
-
|
|
20
|
-
|
|
25
|
+
readonly authHeader: {
|
|
26
|
+
type: "string";
|
|
27
|
+
} & {
|
|
21
28
|
defaultValue: string;
|
|
22
29
|
};
|
|
23
|
-
tokenType: {
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
readonly tokenType: {
|
|
31
|
+
type: "string";
|
|
32
|
+
} & {
|
|
26
33
|
defaultValue: string;
|
|
27
34
|
};
|
|
28
|
-
domains: {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
defaultValue:
|
|
35
|
+
readonly domains: {
|
|
36
|
+
type: "stringArray";
|
|
37
|
+
} & {
|
|
38
|
+
defaultValue: unknown;
|
|
32
39
|
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
37
|
-
validateWithHEAD: {
|
|
38
|
-
description: string;
|
|
39
|
-
type: string;
|
|
40
|
-
defaultValue: boolean;
|
|
41
|
-
};
|
|
42
|
-
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
43
|
-
name: {
|
|
44
|
-
description: string;
|
|
45
|
-
type: string;
|
|
46
|
-
defaultValue: string;
|
|
47
|
-
};
|
|
48
|
-
description: {
|
|
49
|
-
description: string;
|
|
50
|
-
type: string;
|
|
51
|
-
defaultValue: string;
|
|
52
|
-
};
|
|
53
|
-
authHeader: {
|
|
54
|
-
description: string;
|
|
55
|
-
type: string;
|
|
40
|
+
type: {
|
|
41
|
+
type: "string";
|
|
42
|
+
} & {
|
|
56
43
|
defaultValue: string;
|
|
57
44
|
};
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
45
|
+
internetAccountId: {
|
|
46
|
+
type: "string";
|
|
47
|
+
} & {
|
|
61
48
|
defaultValue: string;
|
|
62
49
|
};
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
};
|
|
68
|
-
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "internetAccountId">>, undefined>>;
|
|
50
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "internetAccountId", true, import("@jbrowse/core/configuration").ConfigurationSchemaRequirement<Partial<Record<string, string[]>>, string>, any>>>;
|
|
51
|
+
}, "configuration" | "type"> & {
|
|
52
|
+
type: import("@jbrowse/mobx-state-tree").ILiteralType<"ExternalTokenInternetAccount">;
|
|
53
|
+
configuration: import("@jbrowse/core/configuration/configurationSchema").IConfigurationReference<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>;
|
|
69
54
|
}, {
|
|
70
55
|
readonly name: string;
|
|
71
56
|
readonly description: string;
|
|
@@ -74,22 +59,21 @@ declare const stateModelFactory: (configSchema: ExternalTokenInternetAccountConf
|
|
|
74
59
|
readonly tokenType: string;
|
|
75
60
|
readonly domains: string[];
|
|
76
61
|
readonly toggleContents: React.ReactNode;
|
|
77
|
-
readonly SelectorComponent: import("@jbrowse/core/util").AnyReactComponentType | undefined;
|
|
78
62
|
readonly selectorLabel: string | undefined;
|
|
63
|
+
readonly showInFileSelector: boolean;
|
|
79
64
|
} & {
|
|
80
|
-
handlesLocation(location: UriLocation): boolean;
|
|
65
|
+
handlesLocation(location: import("@jbrowse/core/util").UriLocation): boolean;
|
|
81
66
|
readonly tokenKey: string;
|
|
82
67
|
} & {
|
|
83
68
|
getTokenFromUser(_resolve: (token: string) => void, _reject: (error: Error) => void): void;
|
|
84
69
|
storeToken(token: string): void;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
validateToken(token: string, _loc: UriLocation): Promise<string>;
|
|
70
|
+
retrieveToken(): string | undefined;
|
|
71
|
+
validateToken(token: string, _loc: import("@jbrowse/core/util").UriLocation): Promise<string>;
|
|
88
72
|
} & {
|
|
89
|
-
|
|
73
|
+
removeToken(): void;
|
|
74
|
+
getToken(location?: import("@jbrowse/core/util").UriLocation): Promise<string>;
|
|
90
75
|
} & {
|
|
91
76
|
addAuthHeaderToInit(init?: RequestInit, token?: string): {
|
|
92
|
-
headers: Headers;
|
|
93
77
|
body?: BodyInit | null;
|
|
94
78
|
cache?: RequestCache;
|
|
95
79
|
credentials?: RequestCredentials;
|
|
@@ -103,23 +87,25 @@ declare const stateModelFactory: (configSchema: ExternalTokenInternetAccountConf
|
|
|
103
87
|
referrerPolicy?: ReferrerPolicy;
|
|
104
88
|
signal?: AbortSignal | null;
|
|
105
89
|
window?: null;
|
|
90
|
+
headers: Headers;
|
|
106
91
|
};
|
|
107
|
-
|
|
92
|
+
fetchWithToken(loc: import("@jbrowse/core/util").UriLocation | undefined, run: (token: string) => Promise<Response>): Promise<Response>;
|
|
93
|
+
getPreAuthorizationInformation(location: import("@jbrowse/core/util").UriLocation): Promise<{
|
|
108
94
|
internetAccountType: string;
|
|
109
95
|
authInfo: {
|
|
110
96
|
token: string;
|
|
111
|
-
configuration: any
|
|
97
|
+
configuration: import("@jbrowse/mobx-state-tree").ModelSnapshotType<Record<string, any>>;
|
|
112
98
|
};
|
|
113
99
|
}>;
|
|
114
100
|
} & {
|
|
115
|
-
getFetcher(loc?: UriLocation): (input: RequestInfo, init?: RequestInit) => Promise<Response>;
|
|
101
|
+
getFetcher(loc?: import("@jbrowse/core/util").UriLocation): (input: RequestInfo, init?: RequestInit) => Promise<Response>;
|
|
116
102
|
} & {
|
|
117
|
-
openLocation(location:
|
|
103
|
+
openLocation(location: import("@jbrowse/core/util").UriLocation): import("@gmod/range-cache-filehandle").RemoteFileWithRangeCache;
|
|
118
104
|
} & {
|
|
119
105
|
readonly validateWithHEAD: boolean;
|
|
120
106
|
} & {
|
|
121
107
|
getTokenFromUser(resolve: (token: string) => void, reject: (error: Error) => void): void;
|
|
122
|
-
validateToken(token: string, location: UriLocation): Promise<string>;
|
|
108
|
+
validateToken(token: string, location: import("@jbrowse/core/util").UriLocation): Promise<string>;
|
|
123
109
|
}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>;
|
|
124
110
|
export default stateModelFactory;
|
|
125
111
|
export type ExternalTokenStateModel = ReturnType<typeof stateModelFactory>;
|
|
@@ -1,55 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
get validateWithHEAD() {
|
|
13
|
-
return getConf(self, 'validateWithHEAD');
|
|
14
|
-
},
|
|
15
|
-
}))
|
|
16
|
-
.actions(self => ({
|
|
17
|
-
getTokenFromUser(resolve, reject) {
|
|
18
|
-
const { session } = getRoot(self);
|
|
19
|
-
session.queueDialog((doneCallback) => [
|
|
20
|
-
ExternalTokenEntryForm,
|
|
21
|
-
{
|
|
22
|
-
internetAccountId: self.internetAccountId,
|
|
23
|
-
handleClose: (token) => {
|
|
24
|
-
if (token) {
|
|
25
|
-
resolve(token);
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
reject(new Error('user cancelled entry'));
|
|
29
|
-
}
|
|
30
|
-
doneCallback();
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
]);
|
|
34
|
-
},
|
|
35
|
-
async validateToken(token, location) {
|
|
36
|
-
if (!self.validateWithHEAD) {
|
|
37
|
-
return token;
|
|
38
|
-
}
|
|
39
|
-
const newInit = self.addAuthHeaderToInit({ method: 'HEAD' }, token);
|
|
40
|
-
const response = await fetch(location.uri, newInit);
|
|
41
|
-
if (!response.ok) {
|
|
42
|
-
let errorMessage;
|
|
43
|
-
try {
|
|
44
|
-
errorMessage = await response.text();
|
|
45
|
-
}
|
|
46
|
-
catch (error) {
|
|
47
|
-
errorMessage = '';
|
|
48
|
-
}
|
|
49
|
-
throw new Error(`Token could not be validated — ${response.status} ${errorMessage ? ` (${errorMessage})` : ''}`);
|
|
50
|
-
}
|
|
51
|
-
return token;
|
|
52
|
-
},
|
|
53
|
-
}));
|
|
54
|
-
};
|
|
1
|
+
import { ExternalTokenEntryForm } from '../lazyLoginForms.js';
|
|
2
|
+
import { tokenEntryModelFactory } from '../tokenEntryModelFactory.js';
|
|
3
|
+
/**
|
|
4
|
+
* #stateModel ExternalTokenInternetAccount
|
|
5
|
+
* Internet account that authenticates requests with a user-supplied external
|
|
6
|
+
* token, prompting for the token via a dialog and optionally validating it with
|
|
7
|
+
* a HEAD request. See
|
|
8
|
+
* [TokenEntryInternetAccount](../tokenentryinternetaccount) for the shared
|
|
9
|
+
* behavior.
|
|
10
|
+
*/
|
|
11
|
+
const stateModelFactory = (configSchema) => tokenEntryModelFactory('ExternalTokenInternetAccount', 'ExternalTokenInternetAccount', configSchema, ExternalTokenEntryForm);
|
|
55
12
|
export default stateModelFactory;
|
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
import { RemoteFileWithRangeCache } from '@jbrowse/core/util/io';
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
metadataOnly?: boolean;
|
|
5
|
-
}
|
|
6
|
-
interface GoogleDriveFilehandleOptions extends FilehandleOptions {
|
|
7
|
-
fetch(input: RequestInfo, opts?: RequestInitWithMetadata): Promise<Response>;
|
|
8
|
-
}
|
|
2
|
+
import type { RequestInitWithMetadata } from './model.tsx';
|
|
3
|
+
import type { Stats } from 'generic-filehandle2';
|
|
9
4
|
export declare class GoogleDriveFile extends RemoteFileWithRangeCache {
|
|
10
5
|
private statsPromise;
|
|
11
|
-
constructor(source: string, opts: GoogleDriveFilehandleOptions);
|
|
12
6
|
fetch(input: RequestInfo, opts?: RequestInitWithMetadata): Promise<Response>;
|
|
13
7
|
stat(): Promise<Stats>;
|
|
14
8
|
}
|
|
15
|
-
export {};
|
|
@@ -1,16 +1,37 @@
|
|
|
1
1
|
import { RemoteFileWithRangeCache } from '@jbrowse/core/util/io';
|
|
2
2
|
export class GoogleDriveFile extends RemoteFileWithRangeCache {
|
|
3
3
|
statsPromise;
|
|
4
|
-
|
|
5
|
-
super(source, opts);
|
|
6
|
-
this.statsPromise = this.fetch(source, {
|
|
7
|
-
metadataOnly: true,
|
|
8
|
-
}).then(response => response.json());
|
|
9
|
-
}
|
|
4
|
+
// Override to widen opts type so metadataOnly can be passed through to getFetcher
|
|
10
5
|
async fetch(input, opts) {
|
|
11
6
|
return super.fetch(input, opts);
|
|
12
7
|
}
|
|
8
|
+
// Fetched on demand rather than from the constructor: openLocation builds a
|
|
9
|
+
// filehandle for every file a track opens and most are read by byte range
|
|
10
|
+
// only, so an eager metadata request cost a round trip (and a token
|
|
11
|
+
// validation) per handle for a size nobody asked for.
|
|
13
12
|
async stat() {
|
|
13
|
+
this.statsPromise ??= this.fetch(this.url, { metadataOnly: true })
|
|
14
|
+
.then(response => response.json())
|
|
15
|
+
// Drive serializes its int64 fields as JSON strings, so `size` arrives as
|
|
16
|
+
// "12345" — passed on untouched it satisfies `Stats` in name only, and
|
|
17
|
+
// the first caller to do arithmetic on it concatenates instead
|
|
18
|
+
.then(({ size }) => {
|
|
19
|
+
const stats = { size: Number(size) };
|
|
20
|
+
// This is the only place the size of a Drive file is ever observed: the
|
|
21
|
+
// metadata request carries no Content-Range, so the chunk cache's own
|
|
22
|
+
// way of learning it never fires here, and without it every bgzf
|
|
23
|
+
// reader's deliberate over-read of the final block goes to the network
|
|
24
|
+
// to be refused. Drive omits `size` for a file that has none, and
|
|
25
|
+
// recordSize drops the NaN that produces rather than caching it.
|
|
26
|
+
this.recordSize(stats.size);
|
|
27
|
+
return stats;
|
|
28
|
+
})
|
|
29
|
+
// a cached rejection is permanent, so one dropped request would take
|
|
30
|
+
// every later stat() of this file with it
|
|
31
|
+
.catch((error) => {
|
|
32
|
+
this.statsPromise = undefined;
|
|
33
|
+
throw error;
|
|
34
|
+
});
|
|
14
35
|
return this.statsPromise;
|
|
15
36
|
}
|
|
16
37
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { SvgIconProps } from '@mui/material';
|
|
2
|
-
export default function GoogleDriveIcon(props: SvgIconProps): import("react
|
|
2
|
+
export default function GoogleDriveIcon(props: SvgIconProps): import("react").JSX.Element;
|