chore(dropbox-web) Accommodate short-lived access token
This commit is contained in:
parent
5367d43c26
commit
bec9920c79
|
@ -7489,12 +7489,18 @@
|
|||
}
|
||||
},
|
||||
"dropbox": {
|
||||
"version": "4.0.9",
|
||||
"resolved": "https://registry.npmjs.org/dropbox/-/dropbox-4.0.9.tgz",
|
||||
"integrity": "sha512-UeaKw7DY24ZGLRV8xboZvbZXhbTVrFjPjfpr0LfF/KVOzBUad9vJJwqz3udqTLNxD0FXbFlC9rlNLLNXaj9msg==",
|
||||
"version": "10.7.0",
|
||||
"resolved": "https://registry.npmjs.org/dropbox/-/dropbox-10.7.0.tgz",
|
||||
"integrity": "sha512-btNLOYHxukACfnkEUNhlTPCnkecfbL89mrPU3RMKAWdCQXM18aRLm+t+0xIpzvRUSGeXPER+3d+QJk5Wi+4QGw==",
|
||||
"requires": {
|
||||
"buffer": "^5.0.8",
|
||||
"moment": "^2.19.3"
|
||||
"node-fetch": "^2.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"node-fetch": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"duplexer": {
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
"base64-js": "1.3.1",
|
||||
"bc-css-flags": "3.0.0",
|
||||
"clipboard-copy": "4.0.1",
|
||||
"dropbox": "4.0.9",
|
||||
"dropbox": "10.7.0",
|
||||
"focus-visible": "5.1.0",
|
||||
"i18n-iso-countries": "6.8.0",
|
||||
"i18next": "17.0.6",
|
||||
|
|
|
@ -24,7 +24,7 @@ export function authorizeDropbox() {
|
|||
|
||||
_authorizeDropbox(dropbox.appKey, redirectURI)
|
||||
.then(
|
||||
token => dispatch(updateDropboxToken(token)));
|
||||
({ token, rToken, expireDate }) => dispatch(updateDropboxToken(token, rToken, expireDate)));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -32,14 +32,20 @@ export function authorizeDropbox() {
|
|||
* Action to update the dropbox access token.
|
||||
*
|
||||
* @param {string} token - The new token.
|
||||
* @param {string} rToken - The refresh token.
|
||||
* @param {string} expireDate - The token expiration date as ISO string.
|
||||
* @returns {{
|
||||
* type: UPDATE_DROPBOX_TOKEN,
|
||||
* token: string
|
||||
* token: string,
|
||||
* rToken: string,
|
||||
* expireDate: string
|
||||
* }}
|
||||
*/
|
||||
export function updateDropboxToken(token: string) {
|
||||
export function updateDropboxToken(token: string, rToken: string, expireDate: string) {
|
||||
return {
|
||||
type: UPDATE_DROPBOX_TOKEN,
|
||||
token
|
||||
token,
|
||||
rToken,
|
||||
expireDate
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,7 +13,10 @@ const { Dropbox } = NativeModules;
|
|||
* access token or rejected with an error.
|
||||
*/
|
||||
export function _authorizeDropbox(): Promise<string> {
|
||||
return Dropbox.authorize();
|
||||
return Dropbox.authorize()
|
||||
.then(token => {
|
||||
return { token };
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
// @flow
|
||||
|
||||
import { Dropbox } from 'dropbox';
|
||||
import { Dropbox, DropboxAuth } from 'dropbox';
|
||||
|
||||
import {
|
||||
getJitsiMeetGlobalNS,
|
||||
parseStandardURIString,
|
||||
parseURLParams
|
||||
} from '../base/util';
|
||||
import { getJitsiMeetGlobalNS } from '../base/util';
|
||||
|
||||
/**
|
||||
* Executes the oauth flow.
|
||||
|
@ -31,6 +27,16 @@ function authorize(authUrl: string): Promise<string> {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the token's expiry date as ISO string.
|
||||
*
|
||||
* @param {number} expiresIn - The seconds in which the token expires.
|
||||
* @returns {string} - The ISO value for the expiry date.
|
||||
*/
|
||||
function getTokenExpiresAtDate(expiresIn: number) {
|
||||
return new Date(Date.now() + (expiresIn * 1000)).toISOString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to authorize the Jitsi Recording app in dropbox.
|
||||
*
|
||||
|
@ -41,16 +47,47 @@ function authorize(authUrl: string): Promise<string> {
|
|||
export function _authorizeDropbox(
|
||||
appKey: string,
|
||||
redirectURI: string
|
||||
): Promise<string> {
|
||||
const dropboxAPI = new Dropbox({ clientId: appKey });
|
||||
const url = dropboxAPI.getAuthenticationUrl(redirectURI);
|
||||
): Promise<Object> {
|
||||
const dropbox = new DropboxAuth({ clientId: appKey });
|
||||
|
||||
return authorize(url).then(returnUrl => {
|
||||
const params
|
||||
= parseURLParams(parseStandardURIString(returnUrl), true) || {};
|
||||
return dropbox.getAuthenticationUrl(redirectURI, undefined, 'code', 'offline', undefined, undefined, true)
|
||||
.then(authorize)
|
||||
.then(returnUrl => {
|
||||
const params = new URLSearchParams(new URL(returnUrl).search);
|
||||
const code = params.get('code');
|
||||
|
||||
return params.access_token;
|
||||
});
|
||||
return dropbox.getAccessTokenFromCode(redirectURI, code);
|
||||
})
|
||||
.then(resp => {
|
||||
return {
|
||||
token: resp.result.access_token,
|
||||
rToken: resp.result.refresh_token,
|
||||
expireDate: getTokenExpiresAtDate(resp.result.expires_in)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a new acccess 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()
|
||||
.then(() => {
|
||||
return {
|
||||
token: dropbox.getAccessToken(),
|
||||
rToken: dropbox.getRefreshToken(),
|
||||
expireDate: dropbox.getAccessTokenExpiresAt().toISOString()
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,7 +105,7 @@ export function getDisplayName(token: string, appKey: string) {
|
|||
|
||||
return (
|
||||
dropboxAPI.usersGetCurrentAccount()
|
||||
.then(account => account.name.display_name));
|
||||
.then(account => account.result.name.display_name));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,7 +122,7 @@ export function getSpaceUsage(token: string, appKey: string) {
|
|||
});
|
||||
|
||||
return dropboxAPI.usersGetSpaceUsage().then(space => {
|
||||
const { allocation, used } = space;
|
||||
const { allocation, used } = space.result;
|
||||
const { allocated } = allocation;
|
||||
|
||||
return {
|
||||
|
|
|
@ -19,7 +19,9 @@ ReducerRegistry.register(STORE_NAME, (state = {}, action) => {
|
|||
case UPDATE_DROPBOX_TOKEN:
|
||||
return {
|
||||
...state,
|
||||
token: action.token
|
||||
token: action.token,
|
||||
rToken: action.rToken,
|
||||
expireDate: action.expireDate
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
|
|
|
@ -9,7 +9,9 @@ import {
|
|||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
|
||||
import {
|
||||
getDropboxData,
|
||||
isEnabled as isDropboxEnabled
|
||||
isEnabled as isDropboxEnabled,
|
||||
getNewAccessToken,
|
||||
updateDropboxToken
|
||||
} from '../../../dropbox';
|
||||
import { showErrorNotification } from '../../../notifications';
|
||||
import { toggleRequestingSubtitles } from '../../../subtitles';
|
||||
|
@ -50,6 +52,16 @@ type Props = {
|
|||
*/
|
||||
_isDropboxEnabled: boolean,
|
||||
|
||||
/**
|
||||
* The dropbox refresh token.
|
||||
*/
|
||||
_rToken: string,
|
||||
|
||||
/**
|
||||
* Access token's expiration date as ISO string.
|
||||
*/
|
||||
_tokenExpireDate?: string,
|
||||
|
||||
/**
|
||||
* The dropbox access token.
|
||||
*/
|
||||
|
@ -209,7 +221,7 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
|
|||
* @returns {void}
|
||||
*/
|
||||
_onTokenUpdated() {
|
||||
const { _appKey, _isDropboxEnabled, _token } = this.props;
|
||||
const { _appKey, _isDropboxEnabled, _token, _rToken, _tokenExpireDate, dispatch } = this.props;
|
||||
|
||||
if (!_isDropboxEnabled) {
|
||||
return;
|
||||
|
@ -221,6 +233,13 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
|
|||
isValidating: false
|
||||
});
|
||||
} else {
|
||||
if (_tokenExpireDate && Date.now() > new Date(_tokenExpireDate)) {
|
||||
getNewAccessToken(_appKey, _rToken)
|
||||
.then(resp => dispatch(updateDropboxToken(resp.token, resp.rToken, resp.expireDate)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
isTokenValid: false,
|
||||
isValidating: true
|
||||
|
@ -251,7 +270,15 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
|
|||
* @returns {boolean} - True (to note that the modal should be closed).
|
||||
*/
|
||||
_onSubmit() {
|
||||
const { _autoCaptionOnRecord, _conference, _isDropboxEnabled, _token, dispatch } = this.props;
|
||||
const {
|
||||
_appKey,
|
||||
_autoCaptionOnRecord,
|
||||
_conference,
|
||||
_isDropboxEnabled,
|
||||
_rToken,
|
||||
_token,
|
||||
dispatch
|
||||
} = this.props;
|
||||
let appData;
|
||||
const attributes = {};
|
||||
|
||||
|
@ -261,7 +288,9 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
|
|||
'file_recording_metadata': {
|
||||
'upload_credentials': {
|
||||
'service_name': RECORDING_TYPES.DROPBOX,
|
||||
'token': _token
|
||||
'token': _token,
|
||||
'r_token': _rToken,
|
||||
'app_key': _appKey
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -320,6 +349,8 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
|
|||
* _fileRecordingsServiceEnabled: boolean,
|
||||
* _fileRecordingsServiceSharingEnabled: boolean,
|
||||
* _isDropboxEnabled: boolean,
|
||||
* _rToken:string,
|
||||
* _tokenExpireDate: string,
|
||||
* _token: string
|
||||
* }}
|
||||
*/
|
||||
|
@ -338,6 +369,8 @@ export function mapStateToProps(state: Object) {
|
|||
_fileRecordingsServiceEnabled: fileRecordingsServiceEnabled,
|
||||
_fileRecordingsServiceSharingEnabled: fileRecordingsServiceSharingEnabled,
|
||||
_isDropboxEnabled: isDropboxEnabled(state),
|
||||
_rToken: state['features/dropbox'].rToken,
|
||||
_tokenExpireDate: state['features/dropbox'].expireDate,
|
||||
_token: state['features/dropbox'].token
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue