@adobe/helix-onedrive-support 7.1.2 → 8.0.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/.eslintrc.cjs +33 -0
- package/.husky/pre-commit +4 -0
- package/.jsdoc.json +4 -2
- package/.nycrc.json +4 -3
- package/.releaserc.cjs +16 -0
- package/CHANGELOG.md +35 -0
- package/docs/API.md +106 -341
- package/package.json +20 -20
- package/src/OneDrive.d.ts +4 -72
- package/src/OneDrive.js +62 -326
- package/src/OneDriveAuth.d.ts +98 -0
- package/src/OneDriveAuth.js +310 -0
- package/src/OneDriveMock.js +19 -12
- package/src/SharePointSite.js +5 -7
- package/src/StatusCodeError.js +2 -4
- package/src/cache/FSCacheManager.d.ts +28 -0
- package/src/cache/FSCacheManager.js +77 -0
- package/src/cache/FSCachePlugin.d.ts +29 -0
- package/src/cache/FSCachePlugin.js +70 -0
- package/src/cache/MemCachePlugin.d.ts +34 -0
- package/src/cache/MemCachePlugin.js +88 -0
- package/src/cache/S3CacheManager.d.ts +40 -0
- package/src/cache/S3CacheManager.js +107 -0
- package/src/cache/S3CachePlugin.d.ts +49 -0
- package/src/cache/S3CachePlugin.js +116 -0
- package/src/cache/encrypt.js +70 -0
- package/src/{NamedItem.d.ts → excel/NamedItem.d.ts} +0 -0
- package/src/{NamedItemContainer.js → excel/NamedItemContainer.js} +3 -5
- package/src/{Range.d.ts → excel/Range.d.ts} +2 -2
- package/src/{Range.js → excel/Range.js} +3 -5
- package/src/{Table.d.ts → excel/Table.d.ts} +2 -2
- package/src/{Table.js → excel/Table.js} +3 -5
- package/src/{Workbook.d.ts → excel/Workbook.d.ts} +2 -2
- package/src/{Workbook.js → excel/Workbook.js} +5 -10
- package/src/{Worksheet.d.ts → excel/Worksheet.d.ts} +4 -4
- package/src/{Worksheet.js → excel/Worksheet.js} +5 -10
- package/src/index.d.ts +14 -5
- package/src/index.js +9 -7
- package/src/package.cjs +12 -0
- package/src/utils.js +95 -45
- package/src/fuzzy-helper.js +0 -89
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
import {AuthenticationResult, ClientApplication, ICachePlugin} from "@azure/msal-node";
|
|
13
|
+
|
|
14
|
+
export declare interface OneDriveAuthOptions {
|
|
15
|
+
clientId: string;
|
|
16
|
+
clientSecret?: string;
|
|
17
|
+
refreshToken?: string;
|
|
18
|
+
log?: Console;
|
|
19
|
+
tenant?: string;
|
|
20
|
+
scopes?: string[];
|
|
21
|
+
localAuthCache?:boolean;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* use cache plugin instead for default (global) token cache.
|
|
25
|
+
*/
|
|
26
|
+
cachePlugin?: ICachePlugin,
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Disables the cache for the tenant lookup.
|
|
30
|
+
* @default process.env.HELIX_ONEDRIVE_NO_TENANT_CACHE
|
|
31
|
+
*/
|
|
32
|
+
noTenantCache?: boolean;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Map to use for the tenant lookup cache. If empty, a module-global cache will be used.
|
|
36
|
+
* Note that the cache is only used, if the `noTenantCache` flag is `falsy`
|
|
37
|
+
*/
|
|
38
|
+
tenantCache?: Map<string, string>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Helper class that facilitates authentication for one drive.
|
|
43
|
+
*/
|
|
44
|
+
export declare class OneDriveAuth {
|
|
45
|
+
/**
|
|
46
|
+
* Creates a new OneDriveAuth helper.
|
|
47
|
+
* @param {OneDriveAuthOptions} opts Options.
|
|
48
|
+
*/
|
|
49
|
+
constructor(opts: OneDriveAuthOptions);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* {@code true} if this client is initialized.
|
|
53
|
+
*/
|
|
54
|
+
isAuthenticated(): boolean;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* the logger of this client
|
|
58
|
+
*/
|
|
59
|
+
log: Console;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* the MSAL client application
|
|
63
|
+
*/
|
|
64
|
+
app: ClientApplication;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* the authority url for login.
|
|
68
|
+
*/
|
|
69
|
+
getAuthorityUrl(): string;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Performs a login using an interactive flow which prompts the user to open a browser window and
|
|
73
|
+
* enter the authorization code.
|
|
74
|
+
* @params {function} [onCode] - optional function that gets invoked after code was retrieved.
|
|
75
|
+
* @returns {Promise<AuthenticationResult>}
|
|
76
|
+
*/
|
|
77
|
+
acquireTokenByDeviceCode(onCode: Function): Promise<AuthenticationResult>;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Sets the access token to use for all requests. if the token is a valid JWT token,
|
|
81
|
+
* its `tid` claim is used a tenant (if no tenant is already set).
|
|
82
|
+
*
|
|
83
|
+
* @param {string} bearerToken
|
|
84
|
+
* @returns {OneDriveAuth} this
|
|
85
|
+
*/
|
|
86
|
+
setAccessToken(bearerToken): OneDriveAuth;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Acquires the access token either from the cache or from MS.
|
|
90
|
+
* @param {boolean} silentOnly
|
|
91
|
+
* @returns {Promise<AuthenticationResult>}
|
|
92
|
+
*/
|
|
93
|
+
authenticate(silentOnly: boolean): Promise<AuthenticationResult>;
|
|
94
|
+
|
|
95
|
+
dispose() : Promise<void>;
|
|
96
|
+
|
|
97
|
+
initTenantFromUrl(sharingUrl: string|URL): Promise<void>;
|
|
98
|
+
}
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2019 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// eslint-disable-next-line max-classes-per-file
|
|
14
|
+
import { keepAliveNoCache } from '@adobe/helix-fetch';
|
|
15
|
+
import { ConfidentialClientApplication, LogLevel } from '@azure/msal-node';
|
|
16
|
+
import { decodeJwt } from 'jose';
|
|
17
|
+
import { MemCachePlugin } from './cache/MemCachePlugin.js';
|
|
18
|
+
import { StatusCodeError } from './StatusCodeError.js';
|
|
19
|
+
|
|
20
|
+
const { fetch, reset } = keepAliveNoCache({ userAgent: 'helix-fetch' });
|
|
21
|
+
|
|
22
|
+
const AZ_AUTHORITY_HOST_URL = 'https://login.windows.net';
|
|
23
|
+
const AZ_COMMON_TENANT = 'common';
|
|
24
|
+
|
|
25
|
+
const DEFAULT_SCOPES = ['https://graph.microsoft.com/.default', 'openid', 'profile', 'offline_access'];
|
|
26
|
+
|
|
27
|
+
const MSAL_LOG_LEVELS = [
|
|
28
|
+
'error',
|
|
29
|
+
'warn',
|
|
30
|
+
'info',
|
|
31
|
+
'debug',
|
|
32
|
+
'trace',
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* aliases
|
|
37
|
+
* @typedef {import('@azure/msal-node').AuthenticationResult} AuthenticationResult
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* map that caches the tenant ids
|
|
42
|
+
* @type {Map<string, string>}
|
|
43
|
+
*/
|
|
44
|
+
const globalTenantCache = new Map();
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Helper class that facilitates accessing one drive.
|
|
48
|
+
*
|
|
49
|
+
* @class
|
|
50
|
+
* @field {ConfidentialClientApplication|PublicClientApplication} app
|
|
51
|
+
*/
|
|
52
|
+
export class OneDriveAuth {
|
|
53
|
+
/**
|
|
54
|
+
* @param {OneDriveAuthOptions} opts Options
|
|
55
|
+
*/
|
|
56
|
+
constructor(opts) {
|
|
57
|
+
if (!opts.clientId) {
|
|
58
|
+
throw new Error('Missing clientId.');
|
|
59
|
+
}
|
|
60
|
+
if (opts.username || opts.password) {
|
|
61
|
+
throw new Error('Username/password authentication no longer supported.');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
this.clientId = opts.clientId;
|
|
65
|
+
this.clientSecret = opts.clientSecret || '';
|
|
66
|
+
this.refreshToken = opts.refreshToken || '';
|
|
67
|
+
this._log = opts.log || console;
|
|
68
|
+
this.tenant = opts.tenant;
|
|
69
|
+
this.cachePlugin = opts.cachePlugin;
|
|
70
|
+
this.scopes = opts.scopes || DEFAULT_SCOPES;
|
|
71
|
+
|
|
72
|
+
if (!opts.noTenantCache && !process.env.HELIX_ONEDRIVE_NO_TENANT_CACHE) {
|
|
73
|
+
/** @type {Map<string, string>} */
|
|
74
|
+
this.tenantCache = opts.tenantCache || globalTenantCache;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if ((opts.localAuthCache || process.env.HELIX_ONEDRIVE_LOCAL_AUTH_CACHE) && !this.cachePlugin) {
|
|
78
|
+
this.cachePlugin = new MemCachePlugin({
|
|
79
|
+
log: this._log,
|
|
80
|
+
key: 'default',
|
|
81
|
+
caches: new Map(),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
get app() {
|
|
87
|
+
if (!this._app) {
|
|
88
|
+
const {
|
|
89
|
+
log,
|
|
90
|
+
cachePlugin,
|
|
91
|
+
} = this;
|
|
92
|
+
const msalConfig = {
|
|
93
|
+
auth: {
|
|
94
|
+
clientId: this.clientId,
|
|
95
|
+
clientSecret: this.clientSecret,
|
|
96
|
+
authority: this.getAuthorityUrl(),
|
|
97
|
+
},
|
|
98
|
+
system: {
|
|
99
|
+
loggerOptions: {
|
|
100
|
+
loggerCallback(loglevel, message) {
|
|
101
|
+
log[MSAL_LOG_LEVELS[loglevel]](message);
|
|
102
|
+
},
|
|
103
|
+
piiLoggingEnabled: false,
|
|
104
|
+
logLevel: LogLevel.Verbose,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
if (cachePlugin) {
|
|
110
|
+
msalConfig.cache = {
|
|
111
|
+
cachePlugin,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
this._app = new ConfidentialClientApplication(msalConfig);
|
|
115
|
+
}
|
|
116
|
+
return this._app;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async resolveTenant(tenantHostName) {
|
|
120
|
+
const { log } = this;
|
|
121
|
+
const configUrl = `https://login.windows.net/${tenantHostName}.onmicrosoft.com/.well-known/openid-configuration`;
|
|
122
|
+
const res = await fetch(configUrl);
|
|
123
|
+
if (!res.ok) {
|
|
124
|
+
log.info(`error fetching openid-configuration for ${tenantHostName}: ${res.status}. Fallback to 'common'`);
|
|
125
|
+
return AZ_COMMON_TENANT;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const { issuer } = await res.json();
|
|
129
|
+
if (!issuer) {
|
|
130
|
+
log.info(`unable to extract tenant from openid-configuration for ${tenantHostName}: no 'issuer'. Fallback to 'common'`);
|
|
131
|
+
return AZ_COMMON_TENANT;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// eslint-disable-next-line prefer-destructuring
|
|
135
|
+
const tenant = new URL(issuer).pathname.split('/')[1];
|
|
136
|
+
log.info(`fetched tenant information from for ${tenantHostName}: ${tenant}`);
|
|
137
|
+
return tenant;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
static getTenantHostFromUrl(sharingUrl) {
|
|
141
|
+
const url = sharingUrl instanceof URL
|
|
142
|
+
? sharingUrl
|
|
143
|
+
: new URL(sharingUrl);
|
|
144
|
+
let [tenantHost] = url.hostname.split('.');
|
|
145
|
+
// special case: `xxxx-my.sharepoint.com`
|
|
146
|
+
if (url.hostname.endsWith('-my.sharepoint.com')) {
|
|
147
|
+
tenantHost = tenantHost.substring(0, tenantHost.length - 3);
|
|
148
|
+
}
|
|
149
|
+
return tenantHost;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async initTenantFromUrl(sharingUrl) {
|
|
153
|
+
if (this.tenant) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const { log } = this;
|
|
157
|
+
const tenantHost = OneDriveAuth.getTenantHostFromUrl(sharingUrl);
|
|
158
|
+
|
|
159
|
+
if (this.tenantCache) {
|
|
160
|
+
this.tenant = this.tenantCache.get(tenantHost);
|
|
161
|
+
}
|
|
162
|
+
if (!this.tenant) {
|
|
163
|
+
this.tenant = await this.resolveTenant(tenantHost);
|
|
164
|
+
if (this.tenantCache) {
|
|
165
|
+
this.tenantCache.set(tenantHost, this.tenant);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
log.info(`using tenant ${this.tenant} for ${tenantHost} from ${sharingUrl}`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
*/
|
|
173
|
+
// eslint-disable-next-line class-methods-use-this
|
|
174
|
+
async dispose() {
|
|
175
|
+
// TODO: clear other state?
|
|
176
|
+
return reset();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
*/
|
|
181
|
+
get log() {
|
|
182
|
+
return this._log;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
getAuthorityUrl() {
|
|
186
|
+
if (!this.tenant) {
|
|
187
|
+
throw new Error('unable to compute authority url. no tenant.');
|
|
188
|
+
}
|
|
189
|
+
return `${AZ_AUTHORITY_HOST_URL}/${this.tenant}`;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* @returns {boolean}
|
|
194
|
+
*/
|
|
195
|
+
async isAuthenticated() {
|
|
196
|
+
const accounts = await this.app.getTokenCache().getAllAccounts();
|
|
197
|
+
return accounts.length > 0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Performs a login using an interactive flow which prompts the user to open a browser window and
|
|
202
|
+
* enter the authorization code.
|
|
203
|
+
* @params {function} [onCode] - optional function that gets invoked after code was retrieved.
|
|
204
|
+
* @returns {Promise<AuthenticationResult>}
|
|
205
|
+
*/
|
|
206
|
+
async acquireTokenByDeviceCode(onCode) {
|
|
207
|
+
const { log, app } = this;
|
|
208
|
+
try {
|
|
209
|
+
return await app.acquireTokenByDeviceCode({
|
|
210
|
+
deviceCodeCallback: async (code) => {
|
|
211
|
+
log.info(code.message);
|
|
212
|
+
if (typeof onCode === 'function') {
|
|
213
|
+
await onCode(code);
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
scopes: this.scopes,
|
|
217
|
+
});
|
|
218
|
+
} catch (e) {
|
|
219
|
+
log.error('Error while requesting access token with device code', e);
|
|
220
|
+
throw e;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Sets the access token to use for all requests. if the token is a valid JWT token,
|
|
226
|
+
* its `tid` claim is used a tenant (if no tenant is already set).
|
|
227
|
+
*
|
|
228
|
+
* @param {string} bearerToken
|
|
229
|
+
* @returns {OneDriveAuth} this
|
|
230
|
+
*/
|
|
231
|
+
setAccessToken(bearerToken) {
|
|
232
|
+
const { log } = this;
|
|
233
|
+
/** @type AuthenticationResult */
|
|
234
|
+
this.authResult = {
|
|
235
|
+
accessToken: bearerToken,
|
|
236
|
+
};
|
|
237
|
+
if (!this.tenant) {
|
|
238
|
+
try {
|
|
239
|
+
const { tid } = decodeJwt(bearerToken);
|
|
240
|
+
if (tid) {
|
|
241
|
+
log.info(`using tenant from access token: ${tid}`);
|
|
242
|
+
this.tenant = tid;
|
|
243
|
+
}
|
|
244
|
+
} catch (e) {
|
|
245
|
+
log.warn(`unable to decode access token: ${e.message}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
this.authResult.tenantId = this.tenant;
|
|
249
|
+
return this;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Authenticates against MS
|
|
254
|
+
* @param {boolean} silentOnly
|
|
255
|
+
* @returns {Promise<null|AuthenticationResult>}
|
|
256
|
+
*/
|
|
257
|
+
async doAuthenticate(silentOnly) {
|
|
258
|
+
const { log, app } = this;
|
|
259
|
+
const accounts = await app.getTokenCache().getAllAccounts();
|
|
260
|
+
if (accounts.length > 0) {
|
|
261
|
+
try {
|
|
262
|
+
return await app.acquireTokenSilent({
|
|
263
|
+
account: accounts[0],
|
|
264
|
+
});
|
|
265
|
+
} catch (e) {
|
|
266
|
+
if (e.message !== 'Entry not found in cache.') {
|
|
267
|
+
log.warn(`Unable to acquire token from cache: ${e}`);
|
|
268
|
+
} else {
|
|
269
|
+
log.debug(`Unable to acquire token from cache: ${e}`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (silentOnly) {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
if (this.refreshToken) {
|
|
279
|
+
log.debug('acquire token with refresh token.');
|
|
280
|
+
return await app.acquireTokenByRefreshToken({
|
|
281
|
+
refreshToken: this.refreshToken,
|
|
282
|
+
});
|
|
283
|
+
} else if (this.clientSecret) {
|
|
284
|
+
log.debug('acquire token with client credentials.');
|
|
285
|
+
return await app.acquireTokenByClientCredential({
|
|
286
|
+
scopes: this.scopes,
|
|
287
|
+
});
|
|
288
|
+
} else {
|
|
289
|
+
const err = new StatusCodeError('No valid authentication credentials supplied.');
|
|
290
|
+
err.statusCode = 401;
|
|
291
|
+
throw err;
|
|
292
|
+
}
|
|
293
|
+
} catch (e) {
|
|
294
|
+
log.error(`Error while acquiring access token ${e}`);
|
|
295
|
+
throw e;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Authenticates by either using the cached result or talking to MS
|
|
301
|
+
* @param {boolean} silentOnly
|
|
302
|
+
* @returns {Promise<AuthenticationResult>}
|
|
303
|
+
*/
|
|
304
|
+
async authenticate(silentOnly) {
|
|
305
|
+
if (!this.authResult) {
|
|
306
|
+
this.authResult = await this.doAuthenticate(silentOnly);
|
|
307
|
+
}
|
|
308
|
+
return this.authResult;
|
|
309
|
+
}
|
|
310
|
+
}
|
package/src/OneDriveMock.js
CHANGED
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
import { OneDrive } from './OneDrive.js';
|
|
13
|
+
import { OneDriveAuth } from './OneDriveAuth.js';
|
|
14
|
+
import { Workbook } from './excel/Workbook.js';
|
|
15
|
+
import { StatusCodeError } from './StatusCodeError.js';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Handle the `namedItems` operation on a workbook / worksheet
|
|
@@ -139,10 +139,22 @@ function handleTable(sheet, segs, method, body) {
|
|
|
139
139
|
/**
|
|
140
140
|
* Mock OneDrive client that supports some of the operations the `OneDrive` class does.
|
|
141
141
|
*/
|
|
142
|
-
class OneDriveMock extends OneDrive {
|
|
143
|
-
constructor() {
|
|
142
|
+
export class OneDriveMock extends OneDrive {
|
|
143
|
+
constructor({ auth } = {}) {
|
|
144
|
+
if (!auth) {
|
|
145
|
+
// eslint-disable-next-line no-param-reassign
|
|
146
|
+
auth = new OneDriveAuth({
|
|
147
|
+
clientId: 'mock-id',
|
|
148
|
+
tenant: 'test-tenant',
|
|
149
|
+
});
|
|
150
|
+
// eslint-disable-next-line no-param-reassign
|
|
151
|
+
auth.accessToken = {
|
|
152
|
+
accessToken: 'dummy-token',
|
|
153
|
+
tenantId: 'test-tenant',
|
|
154
|
+
};
|
|
155
|
+
}
|
|
144
156
|
super({
|
|
145
|
-
|
|
157
|
+
auth,
|
|
146
158
|
});
|
|
147
159
|
this.workbooks = [];
|
|
148
160
|
this.sharelinks = {};
|
|
@@ -310,8 +322,3 @@ class OneDriveMock extends OneDrive {
|
|
|
310
322
|
}
|
|
311
323
|
}
|
|
312
324
|
}
|
|
313
|
-
|
|
314
|
-
module.exports = Object.assign(OneDriveMock, {
|
|
315
|
-
driveItemToURL,
|
|
316
|
-
driveItemFromURL,
|
|
317
|
-
});
|
package/src/SharePointSite.js
CHANGED
|
@@ -9,14 +9,15 @@
|
|
|
9
9
|
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
|
+
import { keepAliveNoCache } from '@adobe/helix-fetch';
|
|
13
|
+
import { StatusCodeError } from './StatusCodeError.js';
|
|
12
14
|
|
|
13
|
-
const { fetch } =
|
|
14
|
-
const StatusCodeError = require('./StatusCodeError.js');
|
|
15
|
+
const { fetch } = keepAliveNoCache({ userAgent: 'helix-fetch' });
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Helper class accessing folders and files using the SharePoint V1 API.
|
|
18
19
|
*/
|
|
19
|
-
class SharePointSite {
|
|
20
|
+
export class SharePointSite {
|
|
20
21
|
constructor(opts) {
|
|
21
22
|
this._owner = opts.owner;
|
|
22
23
|
this._site = opts.site;
|
|
@@ -113,11 +114,10 @@ class SharePointSite {
|
|
|
113
114
|
// await result in order to be able to catch any error
|
|
114
115
|
return await (rawResponseBody || !json ? resp.buffer() : resp.json());
|
|
115
116
|
} catch (e) {
|
|
116
|
-
/*
|
|
117
|
+
/* c8 ignore next 4 */
|
|
117
118
|
if (e instanceof StatusCodeError) {
|
|
118
119
|
throw e;
|
|
119
120
|
}
|
|
120
|
-
/* istanbul ignore next */
|
|
121
121
|
throw StatusCodeError.fromError(e);
|
|
122
122
|
}
|
|
123
123
|
}
|
|
@@ -126,5 +126,3 @@ class SharePointSite {
|
|
|
126
126
|
return this._log;
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
|
-
|
|
130
|
-
module.exports = SharePointSite;
|
package/src/StatusCodeError.js
CHANGED
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
import { AbortError, FetchError } from '@adobe/helix-fetch';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Internal error class
|
|
17
17
|
* @private
|
|
18
18
|
*/
|
|
19
|
-
class StatusCodeError extends Error {
|
|
19
|
+
export class StatusCodeError extends Error {
|
|
20
20
|
/**
|
|
21
21
|
* Converts a fetch error to a status code error.
|
|
22
22
|
* @param {Error} err The original error
|
|
@@ -63,5 +63,3 @@ class StatusCodeError extends Error {
|
|
|
63
63
|
this.details = details;
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
|
|
67
|
-
module.exports = StatusCodeError;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
import { FSCachePlugin } from "./FSCachePlugin";
|
|
13
|
+
|
|
14
|
+
export declare interface FSCacheManagerOptions {
|
|
15
|
+
log: Console;
|
|
16
|
+
dirPath: string;
|
|
17
|
+
type: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export declare class FSCacheManager {
|
|
21
|
+
constructor(opts: FSCacheManagerOptions);
|
|
22
|
+
|
|
23
|
+
listCacheKeys():Promise<string[]>;
|
|
24
|
+
|
|
25
|
+
hasCache(key:string):Promise<boolean>;
|
|
26
|
+
|
|
27
|
+
getCache(key:string):Promise<FSCachePlugin>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
import fs from 'fs/promises';
|
|
13
|
+
import path from 'path';
|
|
14
|
+
import { FSCachePlugin } from './FSCachePlugin.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* aliases
|
|
18
|
+
* @typedef {import("@azure/msal-node").ICachePlugin} ICachePlugin
|
|
19
|
+
* @typedef {import("@azure/msal-node").TokenCacheContext} TokenCacheContext
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
export class FSCacheManager {
|
|
23
|
+
constructor(opts) {
|
|
24
|
+
this.dirPath = opts.dirPath;
|
|
25
|
+
this.log = opts.log || console;
|
|
26
|
+
this.type = opts.type;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getCacheFilePath(key) {
|
|
30
|
+
return path.resolve(this.dirPath, `auth-${this.type}-${key}.json`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async listCacheKeys() {
|
|
34
|
+
try {
|
|
35
|
+
const files = await fs.readdir(this.dirPath);
|
|
36
|
+
return files
|
|
37
|
+
.filter((name) => (name.startsWith('auth-') && name.endsWith('.json')))
|
|
38
|
+
.map((name) => name.replace(/auth-([a-z0-9]+)-([a-z0-9]+).json/i, '$2'));
|
|
39
|
+
} catch (e) {
|
|
40
|
+
if (e.code === 'ENOENT') {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
throw e;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async hasCache(key) {
|
|
48
|
+
try {
|
|
49
|
+
await fs.lstat(this.getCacheFilePath(key));
|
|
50
|
+
return true;
|
|
51
|
+
} catch (e) {
|
|
52
|
+
if (e.code !== 'ENOENT') {
|
|
53
|
+
throw e;
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param key
|
|
61
|
+
* @returns {FSCachePlugin}
|
|
62
|
+
*/
|
|
63
|
+
async getCache(key) {
|
|
64
|
+
try {
|
|
65
|
+
await fs.lstat(this.dirPath);
|
|
66
|
+
} catch (e) {
|
|
67
|
+
if (e.code !== 'ENOENT') {
|
|
68
|
+
throw e;
|
|
69
|
+
}
|
|
70
|
+
await fs.mkdir(this.dirPath);
|
|
71
|
+
}
|
|
72
|
+
return new FSCachePlugin({
|
|
73
|
+
log: this.log,
|
|
74
|
+
filePath: this.getCacheFilePath(key),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
import { ICachePlugin, TokenCacheContext } from '@azure/msal-node';
|
|
13
|
+
|
|
14
|
+
import { Logger } from "../OneDrive";
|
|
15
|
+
|
|
16
|
+
export declare interface FSCachePluginOptions {
|
|
17
|
+
log: Console;
|
|
18
|
+
filePath: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export declare class FSCachePlugin implements ICachePlugin {
|
|
22
|
+
constructor(opts: FSCachePluginOptions);
|
|
23
|
+
|
|
24
|
+
deleteCache(): Promise<void>;
|
|
25
|
+
|
|
26
|
+
afterCacheAccess(tokenCacheContext: TokenCacheContext): Promise<boolean>;
|
|
27
|
+
|
|
28
|
+
beforeCacheAccess(tokenCacheContext: TokenCacheContext): Promise<boolean>;
|
|
29
|
+
}
|