123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549 |
- const request = require('supertest')
- const nock = require('nock')
- const mockOauthState = require('../mockoauthstate')
- jest.mock('tus-js-client')
- jest.mock('../../src/server/helpers/request', () => {
- return {
- getURLMeta: () => Promise.resolve({ size: 758051 }),
- }
- })
- jest.mock('../../src/server/helpers/oauth-state', () => mockOauthState())
- const fixtures = require('../fixtures')
- const { nockGoogleDownloadFile } = require('../fixtures/drive')
- const { nockZoomRecordings, nockZoomRevoke, expects: { localZoomKey, localZoomSecret } } = require('../fixtures/zoom')
- const defaults = require('../fixtures/constants')
- const tokenService = require('../../src/server/helpers/jwt')
- const { getServer } = require('../mockserver')
- // todo don't share server between tests. rewrite to not use env variables
- const authServer = getServer({ COMPANION_CLIENT_SOCKET_CONNECT_TIMEOUT: '0' })
- const OAUTH_STATE = 'some-cool-nice-encrytpion'
- const providers = require('../../src/server/provider').getDefaultProviders()
- const providerNames = Object.keys(providers)
- const oauthProviders = Object.fromEntries(
- Object.entries(providers).flatMap(([name, provider]) => (
- provider.oauthProvider != null ? [[name, provider.oauthProvider]] : []
- ))
- )
- const authData = {}
- providerNames.forEach((provider) => {
- authData[provider] = { accessToken: 'token value' }
- })
- const token = tokenService.generateEncryptedAuthToken(authData, process.env.COMPANION_SECRET)
- const thisOrThat = (value1, value2) => {
- if (value1 !== undefined) {
- return value1
- }
- return value2
- }
- beforeAll(() => {
- const url = new URL(defaults.THUMBNAIL_URL)
- nock(url.origin).get(url.pathname).reply(200, () => '').persist()
- })
- afterAll(() => {
- nock.cleanAll()
- nock.restore()
- })
- describe('list provider files', () => {
- async function runTest (providerName) {
- const providerFixture = fixtures.providers[providerName]?.expects ?? {}
- return request(authServer)
- .get(`/${providerName}/list/${providerFixture.listPath || ''}`)
- .set('uppy-auth-token', token)
- .expect(200)
- .then((res) => {
- expect(res.header['i-am']).toBe('http://localhost:3020')
- return {
- username: res.body.username,
- items: res.body.items,
- providerFixture,
- }
- })
- }
- function expect1({ username, items, providerFixture }) {
- expect(username).toBe(defaults.USERNAME)
- const item = items[0]
- expect(item.isFolder).toBe(false)
- expect(item.name).toBe(providerFixture.itemName || defaults.ITEM_NAME)
- expect(item.mimeType).toBe(providerFixture.itemMimeType || defaults.MIME_TYPE)
- expect(item.id).toBe(providerFixture.itemId || defaults.ITEM_ID)
- expect(item.size).toBe(thisOrThat(providerFixture.itemSize, defaults.FILE_SIZE))
- expect(item.requestPath).toBe(providerFixture.itemRequestPath || defaults.ITEM_ID)
- expect(item.icon).toBe(providerFixture.itemIcon || defaults.THUMBNAIL_URL)
- }
- test('dropbox', async () => {
- nock('https://api.dropboxapi.com').post('/2/users/get_current_account').reply(200, {
- name: {
- given_name: 'Franz',
- surname: 'Ferdinand',
- familiar_name: 'Franz',
- display_name: 'Franz Ferdinand (Personal)',
- abbreviated_name: 'FF',
- },
- email: defaults.USERNAME,
- email_verified: true,
- disabled: false,
- locale: 'en',
- referral_link: 'https://db.tt/ZITNuhtI',
- is_paired: true,
- })
- nock('https://api.dropboxapi.com').post('/2/files/list_folder').reply(200, {
- entries: [
- {
- '.tag': 'file',
- name: defaults.ITEM_NAME,
- id: defaults.ITEM_ID,
- client_modified: '2015-05-12T15:50:38Z',
- server_modified: '2015-05-12T15:50:38Z',
- rev: 'a1c10ce0dd78',
- size: defaults.FILE_SIZE,
- path_lower: '/homework/math/prime_numbers.txt',
- path_display: '/Homework/math/Prime_Numbers.txt',
- is_downloadable: true,
- has_explicit_shared_members: false,
- content_hash: 'e3b0c44298fc1c149afbf41e4649b934ca49',
- file_lock_info: {
- is_lockholder: true,
- lockholder_name: 'Imaginary User',
- created: '2015-05-12T15:50:38Z',
- },
- },
- ],
- cursor: 'ZtkX9_EHj3x7PMkVuFIhwKYXEpwpLwyxp9vMKomUhllil9q7eWiAu',
- has_more: false,
- })
- const { username, items, providerFixture } = await runTest('dropbox')
- expect1({ username, items, providerFixture })
- })
- test('box', async () => {
- nock('https://api.box.com').get('/2.0/users/me').reply(200, {
- login: defaults.USERNAME,
- })
- nock('https://api.box.com').get('/2.0/folders/0/items?fields=id%2Cmodified_at%2Cname%2Cpermissions%2Csize%2Ctype&limit=1000').reply(200, {
- entries: [
- {
- type: 'file',
- name: defaults.ITEM_NAME,
- id: defaults.ITEM_ID,
- modified_at: '2015-05-12T15:50:38Z',
- size: defaults.FILE_SIZE,
- },
- ],
- })
- const { username, items, providerFixture } = await runTest('box')
- expect1({ username, items, providerFixture })
- })
- test('drive', async () => {
- nock('https://www.googleapis.com').get('/drive/v3/drives?fields=*&pageToken=&pageSize=100').reply(200, {
- kind: 'drive#driveList', drives: [],
- })
- nock('https://www.googleapis.com').get('/drive/v3/files?fields=kind%2CnextPageToken%2CincompleteSearch%2Cfiles%28kind%2Cid%2CimageMediaMetadata%2Cname%2CmimeType%2CownedByMe%2Csize%2CmodifiedTime%2CiconLink%2CthumbnailLink%2CteamDriveId%2CvideoMediaMetadata%2CexportLinks%2CshortcutDetails%28targetId%2CtargetMimeType%29%29&q=%28%27root%27+in+parents%29+and+trashed%3Dfalse&pageSize=1000&orderBy=folder%2Cname&includeItemsFromAllDrives=true&supportsAllDrives=true').reply(200, {
- kind: 'drive#fileList',
- nextPageToken: defaults.NEXT_PAGE_TOKEN,
- files: [
- {
- kind: 'drive#file',
- id: defaults.ITEM_ID,
- name: defaults.ITEM_NAME,
- mimeType: defaults.MIME_TYPE,
- iconLink: 'https://drive-thirdparty.googleusercontent.com/16/type/video/mp4',
- thumbnailLink: defaults.THUMBNAIL_URL,
- modifiedTime: '2016-07-10T20:00:08.096Z',
- ownedByMe: true,
- permissions: [{ role: 'owner', emailAddress: defaults.USERNAME }],
- size: '758051',
- },
- ],
- })
- nock('https://www.googleapis.com').get((uri) => uri.includes('about')).reply(200, { user: { emailAddress: 'john.doe@transloadit.com' } })
- const { username, items, providerFixture } = await runTest('drive')
- // Drive has a virtual "shared-with-me" folder as the first item
- const [item0, ...rest] = items
- expect(item0.isFolder).toBe(true)
- expect(item0.name).toBe('Shared with me')
- expect(item0.mimeType).toBe('application/vnd.google-apps.folder')
- expect(item0.id).toBe('shared-with-me')
- expect(item0.requestPath).toBe('shared-with-me')
- expect(item0.icon).toBe('folder')
- expect1({ username, items: rest, providerFixture })
- })
- test('googlephotos', async () => {
- nock('https://photoslibrary.googleapis.com').get('/v1/albums?pageSize=50').reply(200, {
- albums: [
- {
- coverPhotoBaseUrl: 'https://test',
- title: 'album',
- id: '1',
- }
- ]
- })
- nock('https://photoslibrary.googleapis.com').get('/v1/sharedAlbums?pageSize=50').reply(200, {
- sharedAlbums: [
- {
- coverPhotoBaseUrl: 'https://test2',
- title: 'shared album',
- id: '2',
- }
- ]
- })
- nock('https://www.googleapis.com').get('/oauth2/v1/userinfo').reply(200, {
- email: defaults.USERNAME,
- })
- const { items } = await runTest('googlephotos')
- expect(items[0].isFolder).toBe(true)
- expect(items[0].name).toBe('album')
- expect(items[0].id).toBe('1')
- expect(items[0].requestPath).toBe('1')
- expect(items[0].icon).toBe('https://drive-thirdparty.googleusercontent.com/32/type/application/vnd.google-apps.folder')
- expect(items[0].thumbnail).toBe('https://test=w300-h300-c')
- expect(items[1].isFolder).toBe(true)
- expect(items[1].name).toBe('shared album')
- expect(items[1].id).toBe('2')
- expect(items[1].requestPath).toBe('2')
- expect(items[1].icon).toBe('https://drive-thirdparty.googleusercontent.com/32/type/application/vnd.google-apps.folder')
- expect(items[1].thumbnail).toBe('https://test2=w300-h300-c')
- })
- test('facebook', async () => {
- nock('https://graph.facebook.com').post('/',
- [
- 'access_token=token+value',
- 'appsecret_proof=ee28d8152093b877f193f5fe84a34544ec27160e7f34c7645d02930b3fa95160',
- `batch=${encodeURIComponent('[{"method":"GET","relative_url":"me?fields=email"},{"method":"GET","relative_url":"ALBUM-ID/photos?fields=icon%2Cimages%2Cname%2Cwidth%2Cheight%2Ccreated_time"}]')}`,
- ].join('&')
- ).reply(200,
- [
- {
- code: 200,
- body: JSON.stringify({
- name: 'Fiona Fox',
- birthday: '01/01/1985',
- email: defaults.USERNAME,
- }),
- },
- {
- code: 200,
- body: JSON.stringify({
- data: [
- {
- images: [
- {
- height: 1365,
- source: defaults.THUMBNAIL_URL,
- width: 2048,
- },
- ],
- width: 720,
- height: 479,
- created_time: '2015-07-17T17:26:50+0000',
- id: defaults.ITEM_ID,
- },
- ],
- paging: {},
- }),
- },
- ])
- const { username, items, providerFixture } = await runTest('facebook')
- expect1({ username, items, providerFixture })
- })
- test('instagram', async () => {
- nock('https://graph.instagram.com').get('/me?fields=username').reply(200, {
- id: '17841405793187218',
- username: defaults.USERNAME,
- })
- nock('https://graph.instagram.com').get('/me/media?fields=id%2Cmedia_type%2Cthumbnail_url%2Cmedia_url%2Ctimestamp%2Cchildren%7Bmedia_type%2Cmedia_url%2Cthumbnail_url%2Ctimestamp%7D').reply(200, {
- data: [
- {
- id: defaults.ITEM_ID,
- media_type: 'IMAGE',
- timestamp: '2017-08-31T18:10:00+0000',
- media_url: defaults.THUMBNAIL_URL,
- },
- ],
- })
- const { username, items, providerFixture } = await runTest('instagram')
- expect1({ username, items, providerFixture })
- })
- test('onedrive', async () => {
- nock('https://graph.microsoft.com').get('/v1.0/me').reply(200, {
- userPrincipalName: defaults.USERNAME,
- mail: defaults.USERNAME,
- })
- nock('https://graph.microsoft.com').get('/v1.0/me/drive/root/children?%24expand=thumbnails&%24top=999').reply(200, {
- value: [
- {
- createdDateTime: '2020-01-31T15:40:26.197Z',
- id: defaults.ITEM_ID,
- lastModifiedDateTime: '2020-01-31T15:40:38.723Z',
- name: defaults.ITEM_NAME,
- size: defaults.FILE_SIZE,
- parentReference: {
- driveId: 'DUMMY-DRIVE-ID',
- driveType: 'personal',
- path: '/drive/root:',
- },
- file: {
- mimeType: defaults.MIME_TYPE,
- },
- thumbnails: [{
- id: '0',
- large: {
- height: 452,
- url: defaults.THUMBNAIL_URL,
- width: 800,
- },
- medium: {
- height: 100,
- url: defaults.THUMBNAIL_URL,
- width: 176,
- },
- small: {
- height: 54,
- url: defaults.THUMBNAIL_URL,
- width: 96,
- },
- }],
- },
- ],
- })
- const { username, items, providerFixture } = await runTest('onedrive')
- expect1({ username, items, providerFixture })
- })
- test('zoom', async () => {
- nock('https://zoom.us').get('/v2/users/me').reply(200, {
- id: 'DUMMY-USER-ID',
- first_name: 'John',
- last_name: 'Doe',
- email: 'john.doe@transloadit.com',
- timezone: '',
- dept: '',
- created_at: '2020-07-21T09:13:30Z',
- last_login_time: '2020-10-12T07:55:02Z',
- group_ids: [],
- im_group_ids: [],
- account_id: 'DUMMY-ACCOUNT-ID',
- language: 'en-US',
- })
- nockZoomRecordings()
- const { username, items, providerFixture } = await runTest('zoom')
- expect1({ username, items, providerFixture })
- })
- })
- describe('provider file gets downloaded from', () => {
- async function runTest (providerName) {
- const providerFixture = fixtures.providers[providerName]?.expects ?? {}
- const res = await request(authServer)
- .post(`/${providerName}/get/${providerFixture.itemRequestPath || defaults.ITEM_ID}`)
- .set('uppy-auth-token', token)
- .set('Content-Type', 'application/json')
- .send({
- endpoint: 'http://tusd.tusdemo.net/files',
- protocol: 'tus',
- })
- .expect(200)
- expect(res.body.token).toBeTruthy()
- }
- test('dropbox', async () => {
- nock('https://api.dropboxapi.com').post('/2/files/get_metadata').reply(200, { size: defaults.FILE_SIZE })
- nock('https://content.dropboxapi.com').post('/2/files/download').reply(200, {})
- await runTest('dropbox')
- })
- test('box', async () => {
- nock('https://api.box.com').get(`/2.0/files/${defaults.ITEM_ID}`).reply(200, { size: defaults.FILE_SIZE })
- nock('https://api.box.com').get(`/2.0/files/${defaults.ITEM_ID}/content`).reply(200, { size: defaults.FILE_SIZE })
- await runTest('box')
- })
- test('drive', async () => {
- nockGoogleDownloadFile()
- await runTest('drive')
- })
- test('googlephotos', async () => {
- nock('https://photoslibrary.googleapis.com').get(`/v1/mediaItems/${defaults.ITEM_ID}`).reply(200, {
- baseUrl: 'https://lh3.googleusercontent.com/test',
- })
- nock('https://lh3.googleusercontent.com').get(`/test=d`).reply(200, ' ', { 'content-length': 1 })
- await runTest('googlephotos')
- })
- test('facebook', async () => {
- // times(2) because of size request
- nock('https://graph.facebook.com').post('/',
- [
- 'access_token=token+value',
- 'appsecret_proof=ee28d8152093b877f193f5fe84a34544ec27160e7f34c7645d02930b3fa95160',
- `batch=${encodeURIComponent('[{"method":"GET","relative_url":"DUMMY-FILE-ID?fields=images"}]')}`,
- ].join('&')
- ).times(2).reply(200,
- [{
- code: 200,
- body: JSON.stringify({
- images: [
- {
- height: 1365,
- source: defaults.THUMBNAIL_URL,
- width: 2048,
- },
- ],
- id: defaults.ITEM_ID,
- }),
- }])
- await runTest('facebook')
- })
- test('instagram', async () => {
- // times(2) because of size request
- nock('https://graph.instagram.com').get(`/${defaults.ITEM_ID}?fields=media_url`).times(2).reply(200, {
- id: defaults.ITEM_ID,
- media_type: 'IMAGE',
- media_url: defaults.THUMBNAIL_URL,
- timestamp: '2017-08-31T18:10:00+0000',
- })
- await runTest('instagram')
- })
- test('onedrive', async () => {
- nock('https://graph.microsoft.com').get(`/v1.0/drives/DUMMY-DRIVE-ID/items/${defaults.ITEM_ID}`).reply(200, {
- size: defaults.FILE_SIZE,
- })
- nock('https://graph.microsoft.com').get(`/v1.0/drives/DUMMY-DRIVE-ID/items/${defaults.ITEM_ID}/content`).reply(200, {})
- await runTest('onedrive')
- })
- test('zoom', async () => {
- // times(2) because of size request
- nockZoomRecordings({ times: 2 })
- nock('https://us02web.zoom.us').get('/rec/download/DUMMY-DOWNLOAD-PATH?access_token=token%20value').reply(200, {})
- await runTest('zoom')
- })
- })
- describe('connect to provider', () => {
- test.each(providerNames)('connect to %s via grant.js endpoint', async (providerName) => {
- const oauthProvider = oauthProviders[providerName]
- if (oauthProvider == null) return
- await request(authServer)
- .get(`/${providerName}/connect?foo=bar`)
- .set('uppy-auth-token', token)
- .expect(302)
- .expect('Location', `http://localhost:3020/connect/${oauthProvider}?state=${OAUTH_STATE}`)
- })
- })
- describe('logout of provider', () => {
- async function runTest (providerName) {
- const res = await request(authServer)
- .get(`/${providerName}/logout/`)
- .set('uppy-auth-token', token)
- .expect(200)
- // only some providers can actually be revoked
- const expectRevoked = ['box', 'dropbox', 'drive', 'googlephotos', 'facebook', 'zoom'].includes(providerName)
- expect(res.body).toMatchObject({
- ok: true,
- revoked: expectRevoked,
- })
- }
- test('dropbox', async () => {
- nock('https://api.dropboxapi.com').post('/2/auth/token/revoke').reply(200, {})
- await runTest('dropbox')
- })
- test('box', async () => {
- nock('https://api.box.com').post('/oauth2/revoke').reply(200, {})
- await runTest('box')
- })
- test('dropbox', async () => {
- nock('https://api.dropboxapi.com').post('/2/auth/token/revoke').reply(200, {})
- await runTest('dropbox')
- })
- test('drive', async () => {
- nock('https://accounts.google.com').post('/o/oauth2/revoke?token=token+value').reply(200, {})
- await runTest('drive')
- })
- test('googlephotos', async () => {
- nock('https://accounts.google.com').post('/o/oauth2/revoke?token=token+value').reply(200, {})
- await runTest('googlephotos')
- })
- test('facebook', async () => {
- // times(2) because of size request
- nock('https://graph.facebook.com').post('/',
- [
- 'access_token=token+value',
- 'appsecret_proof=ee28d8152093b877f193f5fe84a34544ec27160e7f34c7645d02930b3fa95160',
- `batch=${encodeURIComponent('[{"method":"DELETE","relative_url":"me/permissions"}]')}`,
- ].join('&')
- ).reply(200,
- [{
- code: 200,
- body: JSON.stringify({}),
- }])
-
- await runTest('facebook')
- })
- test('instagram', async () => {
- await runTest('instagram')
- })
- test('onedrive', async () => {
- await runTest('onedrive')
- })
- test('zoom', async () => {
- nockZoomRevoke({ key: localZoomKey, secret: localZoomSecret })
- await runTest('zoom')
- })
- })
|