UNPKG

@uppy/companion

Version:

OAuth helper and remote fetcher for Uppy's (https://uppy.io) extensible file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Dropbox and Google Drive, S3 and more :dog:

120 lines (119 loc) 5.07 kB
"use strict"; var _a; const Provider = require('../Provider'); const logger = require('../../logger'); const adaptData = require('./adapter'); const { withProviderErrorHandling } = require('../providerErrors'); const { prepareStream } = require('../../helpers/utils'); const got = require('../../got'); const getClient = async ({ token }) => (await got).extend({ prefixUrl: 'https://graph.microsoft.com/v1.0', headers: { authorization: `Bearer ${token}`, }, }); const getOauthClient = async () => (await got).extend({ prefixUrl: 'https://login.live.com', }); const getRootPath = (query) => query.driveId ? `drives/${query.driveId}` : 'me/drive'; /** * Adapter for API https://docs.microsoft.com/en-us/onedrive/developer/rest-api/ */ class OneDrive extends Provider { static get oauthProvider() { return 'microsoft'; } /** * Makes 2 requests in parallel - 1. to get files, 2. to get user email * it then waits till both requests are done before proceeding with the callback * * @param {object} options * @param {string} options.directory * @param {any} options.query * @param {string} options.token */ async list({ directory, query, token }) { return this.#withErrorHandling('provider.onedrive.list.error', async () => { const path = directory ? `items/${directory}` : 'root'; // https://learn.microsoft.com/en-us/graph/query-parameters?tabs=http#top-parameter const pageSize = 999; // const pageSize = 20 // to test pagination easily const qs = { $expand: 'thumbnails', $top: pageSize }; if (query.cursor) { qs.$skiptoken = query.cursor; } const client = await getClient({ token }); const [{ mail, userPrincipalName }, list] = await Promise.all([ client.get('me', { responseType: 'json' }).json(), client .get(`${getRootPath(query)}/${path}/children`, { searchParams: qs, responseType: 'json', }) .json(), ]); return adaptData(list, mail || userPrincipalName, query, directory); }); } async download({ id, token, query }) { return this.#withErrorHandling('provider.onedrive.download.error', async () => { const stream = (await getClient({ token })).stream.get(`${getRootPath(query)}/items/${id}/content`, { responseType: 'json' }); const { size } = await prepareStream(stream); return { stream, size }; }); } async thumbnail() { // not implementing this because a public thumbnail from onedrive will be used instead logger.error('call to thumbnail is not implemented', 'provider.onedrive.thumbnail.error'); throw new Error('call to thumbnail is not implemented'); } async size({ id, query, token }) { return this.#withErrorHandling('provider.onedrive.size.error', async () => { const { size } = await (await getClient({ token })) .get(`${getRootPath(query)}/items/${id}`, { responseType: 'json' }) .json(); return size; }); } async logout() { // apparently M$ doesn't support programmatic oauth2 revoke return { revoked: false, manual_revoke_url: 'https://account.live.com/consent/Manage', }; } async refreshToken({ clientId, clientSecret, refreshToken, redirectUri }) { return this.#withErrorHandling('provider.onedrive.token.refresh.error', async () => { const { access_token: accessToken } = await (await getOauthClient()) .post('oauth20_token.srf', { responseType: 'json', form: { refresh_token: refreshToken, grant_type: 'refresh_token', client_id: clientId, client_secret: clientSecret, redirect_uri: redirectUri, }, }) .json(); return { accessToken }; }); } async #withErrorHandling(tag, fn) { return withProviderErrorHandling({ fn, tag, providerName: _a.oauthProvider, isAuthError: (response) => response.statusCode === 401, isUserFacingError: (response) => [400, 403].includes(response.statusCode), // onedrive gives some errors here that the user might want to know about // e.g. these happen if you try to login to a users in an organization, // without an Office365 licence or OneDrive account setup completed // 400: Tenant does not have a SPO license // 403: You do not have access to create this personal site or you do not have a valid license getJsonErrorMessage: (body) => body?.error?.message, }); } } _a = OneDrive; module.exports = OneDrive;