This commit is contained in:
9
react/features/dropbox/actionTypes.ts
Normal file
9
react/features/dropbox/actionTypes.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* The type of (redux) action to update the dropbox access token.
|
||||
*
|
||||
* {
|
||||
* type: UPDATE_DROPBOX_TOKEN,
|
||||
* token: string
|
||||
* }
|
||||
*/
|
||||
export const UPDATE_DROPBOX_TOKEN = 'UPDATE_DROPBOX_TOKEN';
|
||||
56
react/features/dropbox/actions.ts
Normal file
56
react/features/dropbox/actions.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { IStore } from '../app/types';
|
||||
|
||||
import { UPDATE_DROPBOX_TOKEN } from './actionTypes';
|
||||
import { _authorizeDropbox } from './functions';
|
||||
import logger from './logger';
|
||||
|
||||
/**
|
||||
* Action to authorize the Jitsi Recording app in dropbox.
|
||||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function authorizeDropbox() {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const state = getState();
|
||||
const { locationURL } = state['features/base/connection'];
|
||||
const { dropbox = { appKey: '',
|
||||
redirectURI: undefined } } = state['features/base/config'];
|
||||
|
||||
// By default we use the static page on the main domain for redirection.
|
||||
// So we need to setup only one redirect URI in dropbox app
|
||||
// configuration (not multiple for all the tenants).
|
||||
// In case deployment is running in subfolder dropbox.redirectURI
|
||||
// can be configured.
|
||||
const redirectURI
|
||||
= dropbox.redirectURI || `${locationURL?.origin}/static/oauth.html`;
|
||||
|
||||
_authorizeDropbox(dropbox.appKey, redirectURI)
|
||||
.then(
|
||||
({ token, rToken, expireDate }) => {
|
||||
dispatch(updateDropboxToken(token, rToken, expireDate));
|
||||
})
|
||||
.catch(error => logger.log('Cannot authorize dropbox', error));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to update the dropbox access token.
|
||||
*
|
||||
* @param {string} token - The new token.
|
||||
* @param {string} rToken - The refresh token.
|
||||
* @param {number} expireDate - The token expiration date as UNIX timestamp.
|
||||
* @returns {{
|
||||
* type: UPDATE_DROPBOX_TOKEN,
|
||||
* token: string,
|
||||
* rToken: string,
|
||||
* expireDate: number
|
||||
* }}
|
||||
*/
|
||||
export function updateDropboxToken(token?: string, rToken?: string, expireDate?: number) {
|
||||
return {
|
||||
type: UPDATE_DROPBOX_TOKEN,
|
||||
token,
|
||||
rToken,
|
||||
expireDate
|
||||
};
|
||||
}
|
||||
48
react/features/dropbox/functions.any.ts
Normal file
48
react/features/dropbox/functions.any.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
export * from './functions';
|
||||
|
||||
import { getDisplayName, getSpaceUsage } from './functions';
|
||||
import logger from './logger';
|
||||
|
||||
/**
|
||||
* Information related to the user's dropbox account.
|
||||
*/
|
||||
type DropboxUserData = {
|
||||
|
||||
/**
|
||||
* The available space left in MB into the user's Dropbox account.
|
||||
*/
|
||||
spaceLeft: number;
|
||||
|
||||
/**
|
||||
* The display name of the user in Dropbox.
|
||||
*/
|
||||
userName: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetches information about the user's dropbox account.
|
||||
*
|
||||
* @param {string} token - The dropbox access token.
|
||||
* @param {string} appKey - The Jitsi Recorder dropbox app key.
|
||||
* @returns {Promise<DropboxUserData|undefined>}
|
||||
*/
|
||||
export function getDropboxData(
|
||||
token: string,
|
||||
appKey: string
|
||||
): Promise<DropboxUserData | undefined> {
|
||||
return Promise.all(
|
||||
[ getDisplayName(token, appKey), getSpaceUsage(token, appKey) ]
|
||||
).then(([ userName, space ]) => {
|
||||
const { allocated, used } = space;
|
||||
|
||||
return {
|
||||
userName,
|
||||
spaceLeft: Math.floor((allocated - used) / 1048576)// 1MiB=1048576B
|
||||
};
|
||||
|
||||
}, error => {
|
||||
logger.error(error);
|
||||
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
74
react/features/dropbox/functions.native.ts
Normal file
74
react/features/dropbox/functions.native.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { NativeModules } from 'react-native';
|
||||
|
||||
import { IReduxState } from '../app/types';
|
||||
import { setPictureInPictureEnabled } from '../mobile/picture-in-picture/functions';
|
||||
|
||||
const { Dropbox } = NativeModules;
|
||||
|
||||
/**
|
||||
* Action to authorize the Jitsi Recording app in dropbox.
|
||||
*
|
||||
* @param {any} _appKey - Used on web.
|
||||
* @param {any} _redirectURI - Used on web.
|
||||
* @returns {Promise<Object>} - The promise will be resolved with the dropbox
|
||||
* access token or rejected with an error.
|
||||
*/
|
||||
export async function _authorizeDropbox(_appKey?: any, _redirectURI?: any): Promise<any> {
|
||||
setPictureInPictureEnabled(false);
|
||||
|
||||
try {
|
||||
return await Dropbox.authorize();
|
||||
} finally {
|
||||
setPictureInPictureEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a new access token based on the refresh token.
|
||||
*
|
||||
* @param {string} _appKey - The dropbox appKey.
|
||||
* @param {string} _rToken - The refresh token.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function getNewAccessToken(_appKey: string, _rToken: string) {
|
||||
return _authorizeDropbox();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display name for the current dropbox account.
|
||||
*
|
||||
* @param {string} token - The dropbox access token.
|
||||
* @param {any} _appKey - Used on web.
|
||||
* @returns {Promise<string>} - The promise will be resolved with the display
|
||||
* name or rejected with an error.
|
||||
*/
|
||||
export function getDisplayName(token: string, _appKey?: any) {
|
||||
return Dropbox.getDisplayName(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about the space usage for the current dropbox account.
|
||||
*
|
||||
* @param {string} token - The dropbox access token.
|
||||
* @param {any} _appKey - Used on web.
|
||||
* @returns {Promise<{ used: number, allocated: number}>} - The promise will be
|
||||
* resolved with the object with information about the space usage (the used
|
||||
* space and the allocated space) for the current dropbox account or rejected
|
||||
* with an error.
|
||||
*/
|
||||
export function getSpaceUsage(token: string, _appKey?: any) {
|
||||
return Dropbox.getSpaceUsage(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if the dropbox features is enabled and <tt>false</tt>
|
||||
* otherwise.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isEnabled(state: IReduxState) {
|
||||
const { dropbox = { appKey: undefined } } = state['features/base/config'];
|
||||
|
||||
return Boolean(Dropbox?.ENABLED && typeof dropbox.appKey === 'string');
|
||||
}
|
||||
152
react/features/dropbox/functions.web.ts
Normal file
152
react/features/dropbox/functions.web.ts
Normal file
@@ -0,0 +1,152 @@
|
||||
import { Dropbox, DropboxAuth } from 'dropbox';
|
||||
|
||||
import { IReduxState } from '../app/types';
|
||||
|
||||
/**
|
||||
* Executes the oauth flow.
|
||||
*
|
||||
* @param {string} authUrl - The URL to oauth service.
|
||||
* @returns {Promise<string>} - The URL with the authorization details.
|
||||
*/
|
||||
function authorize(authUrl: string): Promise<string> {
|
||||
const windowName = `oauth${Date.now()}`;
|
||||
|
||||
return new Promise(resolve => {
|
||||
// eslint-disable-next-line prefer-const
|
||||
let popup: any;
|
||||
const handleAuth = ({ data }: { data: { type: string; url: string; windowName: string; }; }) => {
|
||||
if (data && data.type === 'dropbox-login' && data.windowName === windowName) {
|
||||
if (popup) {
|
||||
popup.close();
|
||||
}
|
||||
window.removeEventListener('message', handleAuth);
|
||||
resolve(data.url);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('message', handleAuth);
|
||||
popup = window.open(authUrl, windowName);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the token's expiry date as UNIX timestamp.
|
||||
*
|
||||
* @param {number} expiresIn - The seconds in which the token expires.
|
||||
* @returns {number} - The timestamp value for the expiry date.
|
||||
*/
|
||||
function getTokenExpiresAtTimestamp(expiresIn: number) {
|
||||
return new Date(Date.now() + (expiresIn * 1000)).getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to authorize the Jitsi Recording app in dropbox.
|
||||
*
|
||||
* @param {string} appKey - The Jitsi Recorder dropbox app key.
|
||||
* @param {string} redirectURI - The return URL.
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export function _authorizeDropbox(
|
||||
appKey: string,
|
||||
redirectURI: string
|
||||
): Promise<any> {
|
||||
const dropbox = new DropboxAuth({ clientId: appKey });
|
||||
|
||||
return dropbox.getAuthenticationUrl(redirectURI, undefined, 'code', 'offline', undefined, undefined, true)
|
||||
|
||||
// @ts-ignore
|
||||
.then(authorize)
|
||||
.then(returnUrl => {
|
||||
const params = new URLSearchParams(new URL(returnUrl).search);
|
||||
const code = params.get('code');
|
||||
|
||||
return dropbox.getAccessTokenFromCode(redirectURI, code ?? '');
|
||||
})
|
||||
.then((resp: any) => {
|
||||
return {
|
||||
token: resp.result.access_token,
|
||||
rToken: resp.result.refresh_token,
|
||||
expireDate: getTokenExpiresAtTimestamp(resp.result.expires_in)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a new access token based on the refresh token.
|
||||
*
|
||||
* @param {string} appKey - The dropbox appKey.
|
||||
* @param {string} rToken - The refresh token.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function getNewAccessToken(appKey: string, rToken: string) {
|
||||
const dropbox = new DropboxAuth({ clientId: appKey });
|
||||
|
||||
dropbox.setRefreshToken(rToken);
|
||||
|
||||
return dropbox.refreshAccessToken() // @ts-ignore
|
||||
.then(() => {
|
||||
return {
|
||||
token: dropbox.getAccessToken(),
|
||||
rToken: dropbox.getRefreshToken(),
|
||||
expireDate: dropbox.getAccessTokenExpiresAt().getTime()
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display name for the current dropbox account.
|
||||
*
|
||||
* @param {string} token - The dropbox access token.
|
||||
* @param {string} appKey - The Jitsi Recorder dropbox app key.
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
export function getDisplayName(token: string, appKey: string) {
|
||||
const dropboxAPI = new Dropbox({
|
||||
accessToken: token,
|
||||
clientId: appKey
|
||||
});
|
||||
|
||||
return (
|
||||
dropboxAPI.usersGetCurrentAccount()
|
||||
.then(account => account.result.name.display_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about the space usage for the current dropbox account.
|
||||
*
|
||||
* @param {string} token - The dropbox access token.
|
||||
* @param {string} appKey - The Jitsi Recorder dropbox app key.
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export function getSpaceUsage(token: string, appKey: string) {
|
||||
const dropboxAPI = new Dropbox({
|
||||
accessToken: token,
|
||||
clientId: appKey
|
||||
});
|
||||
|
||||
return dropboxAPI.usersGetSpaceUsage().then(space => {
|
||||
const { allocation, used } = space.result;
|
||||
|
||||
// @ts-ignore
|
||||
const { allocated } = allocation;
|
||||
|
||||
return {
|
||||
allocated,
|
||||
used
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if the dropbox features is enabled and <tt>false</tt>
|
||||
* otherwise.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isEnabled(state: IReduxState) {
|
||||
const { dropbox = { appKey: undefined } } = state['features/base/config'];
|
||||
|
||||
return typeof dropbox.appKey === 'string';
|
||||
}
|
||||
3
react/features/dropbox/logger.ts
Normal file
3
react/features/dropbox/logger.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { getLogger } from '../base/logging/functions';
|
||||
|
||||
export default getLogger('features/dropbox');
|
||||
34
react/features/dropbox/reducer.ts
Normal file
34
react/features/dropbox/reducer.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import PersistenceRegistry from '../base/redux/PersistenceRegistry';
|
||||
import ReducerRegistry from '../base/redux/ReducerRegistry';
|
||||
|
||||
import { UPDATE_DROPBOX_TOKEN } from './actionTypes';
|
||||
|
||||
/**
|
||||
* The redux subtree of this feature.
|
||||
*/
|
||||
const STORE_NAME = 'features/dropbox';
|
||||
|
||||
export interface IDropboxState {
|
||||
expireDate?: number;
|
||||
rToken?: string;
|
||||
token?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the persistence of the feature {@code dropbox}.
|
||||
*/
|
||||
PersistenceRegistry.register(STORE_NAME);
|
||||
|
||||
ReducerRegistry.register<IDropboxState>(STORE_NAME, (state = {}, action): IDropboxState => {
|
||||
switch (action.type) {
|
||||
case UPDATE_DROPBOX_TOKEN:
|
||||
return {
|
||||
...state,
|
||||
token: action.token,
|
||||
rToken: action.rToken,
|
||||
expireDate: action.expireDate
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user