diff --git a/app/main.py b/app/main.py index f666b37..78bbaea 100644 --- a/app/main.py +++ b/app/main.py @@ -24,49 +24,46 @@ secret_key = get_env_variable('APP_SECRET_KEY') app.secret_key = secret_key # https://www.inoreader.com/oauth2/auth +# Corrected URL for Inoreader OAuth +# AUTH_URL = 'https://www.inoreader.com/oauth2/auth' AUTH_URL = 'https://github.com/login/oauth/authorize' +#defining constant +# TOKEN_URL = 'https://www.inoreader.com/oauth2/token' +# USER_INFO_URL = 'https://www.inoreader.com/reader/api/0/user-info' @app.route('/') def home(): if is_logged_in(): - token_id = session.get('token_id') - resp = requests.get(f'{database_url}/token/{token_id}') - raise_for_status(resp) - resp_json = resp.json() - token = resp_json['token'] + return main_menu() + else: + return generate_login_page() - user_info = requests.get('https://api.github.com/user', headers={ - 'Authorization': f'Bearer {token.get("access_token")}' - }).json() +def main_menu(): + token_id = session.get('token_id') + token = get_token_from_database(token_id) + + user_info = get_user_info(token['access_token']) + last_synced, next_sync = format_sync_times(token) - last_synced = datetime.fromtimestamp(token.get('updated_at')).strftime('%Y-%m-%d %H:%M:%S') - next_sync = datetime.fromtimestamp(token.get('updated_at') + token.get('expiration_seconds')).strftime('%Y-%m-%d %H:%M:%S') - return render_template('home.html', - user_login=user_info.get('login'), - user_email=user_info.get('email'), # for inoreader it's userName and userEmail - readwise_api_key=token.get('readwise_api_key') or '', - last_synced=last_synced, next_sync=next_sync) + return render_template('home.html', user_login=user_info.get('userName'), + user_email=user_info.get('userEmail'), + readwise_api_key=token.get('readwise_api_key', ''), + last_synced=last_synced, next_sync=next_sync) - # Generate a CSRF protection string +def generate_login_page(): session['csrf_protection_string'] = os.urandom(16).hex() - # Construct the OAuth URL with URL encoding + oauth_params = { - 'client_id': client_id, - 'redirect_uri': redirect_uri, - 'response_type': 'code', - 'scope': optional_scopes, - 'state': session['csrf_protection_string'] - } - # Use urlencode to properly encode the URL parameters + 'client_id': client_id, + 'redirect_uri': redirect_uri, + 'response_type': 'code', + 'scope': optional_scopes, + 'state': session['csrf_protection_string'] + } oauth_url = f'{AUTH_URL}?{urlencode(oauth_params)}' - - - # Pass dynamic variables to the template - # return render_template('login.html',oauth_url) return render_template('login.html', oauth_url=oauth_url) - @app.route('/oauth-redirect') def oauth_redirect(): auth_code = request.args.get('code') @@ -76,57 +73,28 @@ def oauth_redirect(): if csrf_token != session.get('csrf_protection_string'): abort(403, 'Invalid CSRF token. Please try again.') - # Exchange authorization code for access and refresh tokens - # response = requests.post( - # 'https://www.inoreader.com/oauth2/token', - # headers={ - # 'Content-Type': 'application/x-www-form-urlencoded', - # }, - # data={ - # 'code': auth_code, - # 'redirect_uri': redirect_uri, - # 'client_id': client_id, - # 'client_secret': client_secret, - # 'scope': '', - # 'grant_type': 'authorization_code' - # } - # ) - - # TEST: Github OAuth - REMOVE + # Exchange authorization code for access and refresh tokens using the Inoreader API response = requests.post( - 'https://github.com/login/oauth/access_token', - headers={ - 'Accept': 'application/json' - }, + https://github.com/login/oauth/access_token', + headers={'Accept': 'application/json'}, data={ 'code': auth_code, 'redirect_uri': redirect_uri, 'client_id': client_id, 'client_secret': client_secret, + } ) - raise_for_status(response) - token = response.json() - # TEST: Github OAuth - REMOVE - token['refresh_token'] = 'N/A' - token['expires_in'] = 3600 - - # REPLACE user API call with inoreader API call - # https://www.inoreader.com/reader/api/0/user-info - user_info = requests.get('https://api.github.com/user', headers={ + # Fetch user information from Inoreader + user_info = requests.get(https://api.github.com/user', headers={ 'Authorization': f'Bearer {token.get("access_token")}' - }).json() + }).json() # Save tokens for later use - token_id = save_token( - user_info.get('email'), # for inoreader it's userEmail - token.get('access_token'), - token.get('refresh_token'), - token.get('expires_in') - ) + token_id = save_or_update_token(user_info.get('userEmail'), token) set_session_token_id(token_id) return redirect(url_for('home')) @@ -179,54 +147,52 @@ def is_logged_in(): return token.get('active', False) -def save_token(email, access_token, refresh_token, expiration_seconds): - # check if an active token with this email already exists - token_by_email_resp = requests.get(f'{database_url}/token?email={email}') - raise_for_status(token_by_email_resp) +def save_or_update_token(email, access_token, refresh_token, expiration_seconds): + response = requests.get(f'{database_url}/token?email={email}') + raise_for_status(response) - if token_by_email_resp.status_code != 200: - response = requests.post( - f'{database_url}/token', - headers={ - 'Content-Type': 'application/json' - }, - json={ - 'email': email, - 'access_token': access_token, - 'refresh_token': refresh_token, - 'expiration_seconds': expiration_seconds - } - ) - raise_for_status(response) - return response.json().get('id') + if response.status_code == 200: + update_login(response.json()['token']['id'], access_token, refresh_token, expiration_seconds) else: - token_by_email_resp_json = token_by_email_resp.json() - token = token_by_email_resp_json['token'] - response = requests.put( - f'{database_url}/token/{token["id"]}', - headers={ - 'Content-Type': 'application/json' - }, - json={ - 'access_token': access_token, - 'refresh_token': refresh_token, - 'expiration_seconds': expiration_seconds, - } - ) - raise_for_status(response) - return token['id'] + add_login(email, access_token, refresh_token, expiration_seconds) + +def add_login(email, access_token, refresh_token, expiration_seconds): + response = requests.post( + f'{database_url}/token', + headers={'Content-Type': 'application/json'}, + json={ + 'email': email, + 'access_token': access_token, + 'refresh_token': refresh_token, + 'expiration_seconds': expiration_seconds + } + ) + raise_for_status(response) + return response.json().get('id') + +def update_login(token_id, access_token, refresh_token, expiration_seconds): + response = requests.put( + f'{database_url}/token/{token_id}', + headers={'Content-Type': 'application/json'}, + json={ + 'access_token': access_token, + 'refresh_token': refresh_token, + 'expiration_seconds': expiration_seconds + } + ) + raise_for_status(response) + return token_id def set_session_token_id(token_id): session['token_id'] = token_id def raise_for_status(response): if response.status_code not in range(200, 300): - msg = None try: - msg = response.json().get('error', '') - except: + msg = response.json().get('error', 'No error message provided') + except Exception: msg = response.text - raise Exception(f'HTTPError: {response.status_code} \n Message: {msg}') + raise Exception(f'HTTPError: {response.status_code} - Message: {msg}') if __name__ == '__main__': app.run(host='0.0.0.0', debug=True, port=5000) \ No newline at end of file