diff --git a/application/api/connector/routes.py b/application/api/connector/routes.py index 96f02625..c487ba41 100644 --- a/application/api/connector/routes.py +++ b/application/api/connector/routes.py @@ -441,9 +441,29 @@ class ConnectorValidateSession(Resource): auth = ConnectorCreator.create_auth(provider) is_expired = auth.is_token_expired(token_info) + if is_expired and token_info.get('refresh_token'): + try: + new_token_info = auth.refresh_access_token(token_info.get('refresh_token')) + + sessions_collection.update_one( + {"session_token": session_token}, + {"$set": {"token_info": new_token_info}} + ) + token_info = new_token_info + is_expired = False + except Exception as refresh_error: + current_app.logger.error(f"Failed to refresh token: {refresh_error}") + + if is_expired: + return make_response(jsonify({ + "success": False, + "expired": True, + "error": "Session token has expired. Please reconnect." + }), 401) + return make_response(jsonify({ "success": True, - "expired": is_expired, + "expired": False, "user_email": session.get('user_email', 'Connected User'), "access_token": token_info.get('access_token') }), 200) diff --git a/frontend/src/components/ConnectorAuth.tsx b/frontend/src/components/ConnectorAuth.tsx index 61b6e895..402ddcb4 100644 --- a/frontend/src/components/ConnectorAuth.tsx +++ b/frontend/src/components/ConnectorAuth.tsx @@ -7,20 +7,21 @@ interface ConnectorAuthProps { onSuccess: (data: { session_token: string; user_email: string }) => void; onError: (error: string) => void; label?: string; + isConnected?: boolean; + userEmail?: string; + onDisconnect?: () => void; + errorMessage?: string; } -const providerLabel = (provider: string) => { - const map: Record = { - google_drive: 'Google Drive', - }; - return map[provider] || provider.replace(/_/g, ' '); -}; - const ConnectorAuth: React.FC = ({ provider, onSuccess, onError, label, + isConnected = false, + userEmail = '', + onDisconnect, + errorMessage, }) => { const token = useSelector(selectToken); const completedRef = useRef(false); @@ -36,12 +37,8 @@ const ConnectorAuth: React.FC = ({ const handleAuthMessage = (event: MessageEvent) => { const successGeneric = event.data?.type === 'connector_auth_success'; - const successProvider = - event.data?.type === `${provider}_auth_success` || - event.data?.type === 'google_drive_auth_success'; - const errorProvider = - event.data?.type === `${provider}_auth_error` || - event.data?.type === 'google_drive_auth_error'; + const successProvider = event.data?.type === `${provider}_auth_success`; + const errorProvider = event.data?.type === `${provider}_auth_error`; if (successGeneric || successProvider) { completedRef.current = true; @@ -109,22 +106,60 @@ const ConnectorAuth: React.FC = ({ } }; - const buttonLabel = label || `Connect ${providerLabel(provider)}`; - return ( - + <> + {errorMessage && ( +
+ + + + + {errorMessage} + +
+ )} + + {isConnected ? ( +
+
+
+ + + + Connected as {userEmail} +
+ {onDisconnect && ( + + )} +
+
+ ) : ( + + )} + ); }; -export default ConnectorAuth; +export default ConnectorAuth; \ No newline at end of file diff --git a/frontend/src/components/GoogleDrivePicker.tsx b/frontend/src/components/GoogleDrivePicker.tsx index c47794a0..57d27d60 100644 --- a/frontend/src/components/GoogleDrivePicker.tsx +++ b/frontend/src/components/GoogleDrivePicker.tsx @@ -119,9 +119,10 @@ const GoogleDrivePicker: React.FC = ({ clientId: clientId, developerKey: developerKey, appId: appId, + setSelectFolderEnabled: true, viewId: "DOCS", showUploadView: false, - showUploadFolders: false, + showUploadFolders: true, supportDrives: false, multiselect: true, token: accessToken, @@ -201,122 +202,103 @@ const GoogleDrivePicker: React.FC = ({ onSelectionChange([], []); }; - if (!isConnected) { - return ( -
- {authError && ( -
{authError}
- )} - { - setUserEmail(data.user_email || 'Connected User'); - setIsConnected(true); - setAuthError(''); - - if (data.session_token) { - setSessionToken('google_drive', data.session_token); - validateSession(data.session_token); - } - }} - onError={(error) => { - setAuthError(error); - setIsConnected(false); - }} - /> -
- ); - } - return (
-
-
-
- - - - Connected as {userEmail} -
- -
-
+ { + setUserEmail(data.user_email || 'Connected User'); + setIsConnected(true); + setAuthError(''); -
-
-
-

Selected Files

- -
+ if (data.session_token) { + setSessionToken('google_drive', data.session_token); + validateSession(data.session_token); + } + }} + onError={(error) => { + setAuthError(error); + setIsConnected(false); + }} + isConnected={isConnected} + userEmail={userEmail} + onDisconnect={handleDisconnect} + errorMessage={authError} + /> - {selectedFiles.length === 0 && selectedFolders.length === 0 ? ( -

No files or folders selected

- ) : ( -
- {selectedFolders.length > 0 && ( -
-

Folders

- {selectedFolders.map((folder) => ( -
- Folder - {folder.name} - -
- ))} -
- )} - - {selectedFiles.length > 0 && ( -
-

Files

- {selectedFiles.map((file) => ( -
- File - {file.name} - -
- ))} -
- )} + {isConnected && ( +
+
+
+

Selected Files

+
- )} + + {selectedFiles.length === 0 && selectedFolders.length === 0 ? ( +

No files or folders selected

+ ) : ( +
+ {selectedFolders.length > 0 && ( +
+

Folders

+ {selectedFolders.map((folder) => ( +
+ Folder + {folder.name} + +
+ ))} +
+ )} + + {selectedFiles.length > 0 && ( +
+

Files

+ {selectedFiles.map((file) => ( +
+ File + {file.name} + +
+ ))} +
+ )} +
+ )} +
-
+ )}
); };