Kaynağa Gözat

chore(dropbox-web) Accommodate short-lived access token

master
hmuresan 4 yıl önce
ebeveyn
işleme
bec9920c79

+ 11
- 5
package-lock.json Dosyayı Görüntüle

@@ -7489,12 +7489,18 @@
7489 7489
       }
7490 7490
     },
7491 7491
     "dropbox": {
7492
-      "version": "4.0.9",
7493
-      "resolved": "https://registry.npmjs.org/dropbox/-/dropbox-4.0.9.tgz",
7494
-      "integrity": "sha512-UeaKw7DY24ZGLRV8xboZvbZXhbTVrFjPjfpr0LfF/KVOzBUad9vJJwqz3udqTLNxD0FXbFlC9rlNLLNXaj9msg==",
7492
+      "version": "10.7.0",
7493
+      "resolved": "https://registry.npmjs.org/dropbox/-/dropbox-10.7.0.tgz",
7494
+      "integrity": "sha512-btNLOYHxukACfnkEUNhlTPCnkecfbL89mrPU3RMKAWdCQXM18aRLm+t+0xIpzvRUSGeXPER+3d+QJk5Wi+4QGw==",
7495 7495
       "requires": {
7496
-        "buffer": "^5.0.8",
7497
-        "moment": "^2.19.3"
7496
+        "node-fetch": "^2.6.1"
7497
+      },
7498
+      "dependencies": {
7499
+        "node-fetch": {
7500
+          "version": "2.6.1",
7501
+          "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
7502
+          "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
7503
+        }
7498 7504
       }
7499 7505
     },
7500 7506
     "duplexer": {

+ 1
- 1
package.json Dosyayı Görüntüle

@@ -47,7 +47,7 @@
47 47
     "base64-js": "1.3.1",
48 48
     "bc-css-flags": "3.0.0",
49 49
     "clipboard-copy": "4.0.1",
50
-    "dropbox": "4.0.9",
50
+    "dropbox": "10.7.0",
51 51
     "focus-visible": "5.1.0",
52 52
     "i18n-iso-countries": "6.8.0",
53 53
     "i18next": "17.0.6",

+ 10
- 4
react/features/dropbox/actions.js Dosyayı Görüntüle

@@ -24,7 +24,7 @@ export function authorizeDropbox() {
24 24
 
25 25
         _authorizeDropbox(dropbox.appKey, redirectURI)
26 26
             .then(
27
-                token => dispatch(updateDropboxToken(token)));
27
+                ({ token, rToken, expireDate }) => dispatch(updateDropboxToken(token, rToken, expireDate)));
28 28
     };
29 29
 }
30 30
 
@@ -32,14 +32,20 @@ export function authorizeDropbox() {
32 32
  * Action to update the dropbox access token.
33 33
  *
34 34
  * @param {string} token - The new token.
35
+ * @param {string} rToken - The refresh token.
36
+ * @param {string} expireDate - The token expiration date as ISO string.
35 37
  * @returns {{
36 38
  *     type: UPDATE_DROPBOX_TOKEN,
37
- *     token: string
39
+ *     token: string,
40
+ *     rToken: string,
41
+ *     expireDate: string
38 42
  * }}
39 43
  */
40
-export function updateDropboxToken(token: string) {
44
+export function updateDropboxToken(token: string, rToken: string, expireDate: string) {
41 45
     return {
42 46
         type: UPDATE_DROPBOX_TOKEN,
43
-        token
47
+        token,
48
+        rToken,
49
+        expireDate
44 50
     };
45 51
 }

+ 4
- 1
react/features/dropbox/functions.native.js Dosyayı Görüntüle

@@ -13,7 +13,10 @@ const { Dropbox } = NativeModules;
13 13
  * access token or rejected with an error.
14 14
  */
15 15
 export function _authorizeDropbox(): Promise<string> {
16
-    return Dropbox.authorize();
16
+    return Dropbox.authorize()
17
+        .then(token => {
18
+            return { token };
19
+        });
17 20
 }
18 21
 
19 22
 /**

+ 53
- 16
react/features/dropbox/functions.web.js Dosyayı Görüntüle

@@ -1,12 +1,8 @@
1 1
 // @flow
2 2
 
3
-import { Dropbox } from 'dropbox';
3
+import { Dropbox, DropboxAuth } from 'dropbox';
4 4
 
5
-import {
6
-    getJitsiMeetGlobalNS,
7
-    parseStandardURIString,
8
-    parseURLParams
9
-} from '../base/util';
5
+import { getJitsiMeetGlobalNS } from '../base/util';
10 6
 
11 7
 /**
12 8
  * Executes the oauth flow.
@@ -31,6 +27,16 @@ function authorize(authUrl: string): Promise<string> {
31 27
     });
32 28
 }
33 29
 
30
+/**
31
+ * Returns the token's expiry date as ISO string.
32
+ *
33
+ * @param {number} expiresIn - The seconds in which the token expires.
34
+ * @returns {string} - The ISO value for the expiry date.
35
+ */
36
+function getTokenExpiresAtDate(expiresIn: number) {
37
+    return new Date(Date.now() + (expiresIn * 1000)).toISOString();
38
+}
39
+
34 40
 /**
35 41
  * Action to authorize the Jitsi Recording app in dropbox.
36 42
  *
@@ -41,16 +47,47 @@ function authorize(authUrl: string): Promise<string> {
41 47
 export function _authorizeDropbox(
42 48
         appKey: string,
43 49
         redirectURI: string
44
-): Promise<string> {
45
-    const dropboxAPI = new Dropbox({ clientId: appKey });
46
-    const url = dropboxAPI.getAuthenticationUrl(redirectURI);
50
+): Promise<Object> {
51
+    const dropbox = new DropboxAuth({ clientId: appKey });
52
+
53
+    return dropbox.getAuthenticationUrl(redirectURI, undefined, 'code', 'offline', undefined, undefined, true)
54
+        .then(authorize)
55
+        .then(returnUrl => {
56
+            const params = new URLSearchParams(new URL(returnUrl).search);
57
+            const code = params.get('code');
58
+
59
+            return dropbox.getAccessTokenFromCode(redirectURI, code);
60
+        })
61
+        .then(resp => {
62
+            return {
63
+                token: resp.result.access_token,
64
+                rToken: resp.result.refresh_token,
65
+                expireDate: getTokenExpiresAtDate(resp.result.expires_in)
66
+            };
67
+        });
68
+}
47 69
 
48
-    return authorize(url).then(returnUrl => {
49
-        const params
50
-            = parseURLParams(parseStandardURIString(returnUrl), true) || {};
51 70
 
52
-        return params.access_token;
53
-    });
71
+/**
72
+ * Gets a new acccess token based on the refresh token.
73
+ *
74
+ * @param {string} appKey - The dropbox appKey.
75
+ * @param {string} rToken - The refresh token.
76
+ * @returns {Promise}
77
+ */
78
+export function getNewAccessToken(appKey: string, rToken: string) {
79
+    const dropbox = new DropboxAuth({ clientId: appKey });
80
+
81
+    dropbox.setRefreshToken(rToken);
82
+
83
+    return dropbox.refreshAccessToken()
84
+        .then(() => {
85
+            return {
86
+                token: dropbox.getAccessToken(),
87
+                rToken: dropbox.getRefreshToken(),
88
+                expireDate: dropbox.getAccessTokenExpiresAt().toISOString()
89
+            };
90
+        });
54 91
 }
55 92
 
56 93
 /**
@@ -68,7 +105,7 @@ export function getDisplayName(token: string, appKey: string) {
68 105
 
69 106
     return (
70 107
         dropboxAPI.usersGetCurrentAccount()
71
-            .then(account => account.name.display_name));
108
+            .then(account => account.result.name.display_name));
72 109
 }
73 110
 
74 111
 /**
@@ -85,7 +122,7 @@ export function getSpaceUsage(token: string, appKey: string) {
85 122
     });
86 123
 
87 124
     return dropboxAPI.usersGetSpaceUsage().then(space => {
88
-        const { allocation, used } = space;
125
+        const { allocation, used } = space.result;
89 126
         const { allocated } = allocation;
90 127
 
91 128
         return {

+ 3
- 1
react/features/dropbox/reducer.js Dosyayı Görüntüle

@@ -19,7 +19,9 @@ ReducerRegistry.register(STORE_NAME, (state = {}, action) => {
19 19
     case UPDATE_DROPBOX_TOKEN:
20 20
         return {
21 21
             ...state,
22
-            token: action.token
22
+            token: action.token,
23
+            rToken: action.rToken,
24
+            expireDate: action.expireDate
23 25
         };
24 26
     default:
25 27
         return state;

+ 37
- 4
react/features/recording/components/Recording/AbstractStartRecordingDialog.js Dosyayı Görüntüle

@@ -9,7 +9,9 @@ import {
9 9
 import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
10 10
 import {
11 11
     getDropboxData,
12
-    isEnabled as isDropboxEnabled
12
+    isEnabled as isDropboxEnabled,
13
+    getNewAccessToken,
14
+    updateDropboxToken
13 15
 } from '../../../dropbox';
14 16
 import { showErrorNotification } from '../../../notifications';
15 17
 import { toggleRequestingSubtitles } from '../../../subtitles';
@@ -50,6 +52,16 @@ type Props = {
50 52
      */
51 53
     _isDropboxEnabled: boolean,
52 54
 
55
+    /**
56
+     * The dropbox refresh token.
57
+     */
58
+    _rToken: string,
59
+
60
+    /**
61
+     * Access token's expiration date as ISO string.
62
+     */
63
+    _tokenExpireDate?: string,
64
+
53 65
     /**
54 66
      * The dropbox access token.
55 67
      */
@@ -209,7 +221,7 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
209 221
      * @returns {void}
210 222
      */
211 223
     _onTokenUpdated() {
212
-        const { _appKey, _isDropboxEnabled, _token } = this.props;
224
+        const { _appKey, _isDropboxEnabled, _token, _rToken, _tokenExpireDate, dispatch } = this.props;
213 225
 
214 226
         if (!_isDropboxEnabled) {
215 227
             return;
@@ -221,6 +233,13 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
221 233
                 isValidating: false
222 234
             });
223 235
         } else {
236
+            if (_tokenExpireDate && Date.now() > new Date(_tokenExpireDate)) {
237
+                getNewAccessToken(_appKey, _rToken)
238
+                    .then(resp => dispatch(updateDropboxToken(resp.token, resp.rToken, resp.expireDate)));
239
+
240
+                return;
241
+            }
242
+
224 243
             this.setState({
225 244
                 isTokenValid: false,
226 245
                 isValidating: true
@@ -251,7 +270,15 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
251 270
      * @returns {boolean} - True (to note that the modal should be closed).
252 271
      */
253 272
     _onSubmit() {
254
-        const { _autoCaptionOnRecord, _conference, _isDropboxEnabled, _token, dispatch } = this.props;
273
+        const {
274
+            _appKey,
275
+            _autoCaptionOnRecord,
276
+            _conference,
277
+            _isDropboxEnabled,
278
+            _rToken,
279
+            _token,
280
+            dispatch
281
+        } = this.props;
255 282
         let appData;
256 283
         const attributes = {};
257 284
 
@@ -261,7 +288,9 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
261 288
                     'file_recording_metadata': {
262 289
                         'upload_credentials': {
263 290
                             'service_name': RECORDING_TYPES.DROPBOX,
264
-                            'token': _token
291
+                            'token': _token,
292
+                            'r_token': _rToken,
293
+                            'app_key': _appKey
265 294
                         }
266 295
                     }
267 296
                 });
@@ -320,6 +349,8 @@ class AbstractStartRecordingDialog extends Component<Props, State> {
320 349
  *     _fileRecordingsServiceEnabled: boolean,
321 350
  *     _fileRecordingsServiceSharingEnabled: boolean,
322 351
  *     _isDropboxEnabled: boolean,
352
+ *     _rToken:string,
353
+ *     _tokenExpireDate: string,
323 354
  *     _token: string
324 355
  * }}
325 356
  */
@@ -338,6 +369,8 @@ export function mapStateToProps(state: Object) {
338 369
         _fileRecordingsServiceEnabled: fileRecordingsServiceEnabled,
339 370
         _fileRecordingsServiceSharingEnabled: fileRecordingsServiceSharingEnabled,
340 371
         _isDropboxEnabled: isDropboxEnabled(state),
372
+        _rToken: state['features/dropbox'].rToken,
373
+        _tokenExpireDate: state['features/dropbox'].expireDate,
341 374
         _token: state['features/dropbox'].token
342 375
     };
343 376
 }

Loading…
İptal
Kaydet