Skip to content

Commit

Permalink
harden logic for updating access & refresh token
Browse files Browse the repository at this point in the history
  • Loading branch information
jheld committed Nov 26, 2023
1 parent 20e6d46 commit 5b1cc91
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 50 deletions.
44 changes: 40 additions & 4 deletions diycrate/diycrate_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
import configparser
import logging
import os
import sys
import threading
import time
from pathlib import Path
from typing import Union, Optional
from typing import List, Union, Optional

import bottle
import httpx
import pyinotify
from bottle import ServerAdapter
from boxsdk import Client, exception, OAuth2
from boxsdk import BoxAPIException, Client, exception, OAuth2
from boxsdk.auth import RemoteOAuth2
from cheroot import wsgi as wsgiserver
from cheroot.ssl.builtin import BuiltinSSLAdapter
Expand All @@ -30,14 +31,16 @@
from diycrate.path_utils import re_walk

from diycrate.log_utils import setup_logger
from diycrate.utils import Bottle

setup_logger()

crate_logger = logging.getLogger(__name__)

cloud_provider_name = "Box"

bottle_app = bottle.Bottle()

bottle_app = Bottle()

# The watch manager stores the watches and provides operations on watches

Expand Down Expand Up @@ -137,6 +140,35 @@ def start_cloud_threads(client_oauth):
while not failed:
try:
box_folder = client.folder(folder_id="0").get()
except BoxAPIException as e:
crate_logger.info("Bad box api response.", exc_info=e)
remote_url = conf_obj["box"]["token_url"]
if client.auth._refresh_token or client.auth._access_token:
response = httpx.post(
remote_url,
data={
"refresh_token": client.auth._refresh_token,
"access_token": client.auth._access_token,
},
verify=True,
)
else:
response = None
if not response or response.status_code > 399:
if r_c.exists("diy_crate.auth.access_token") and r_c.exists(
"diy_crate.auth.refresh_token"
):
r_c.delete(
"diy_crate.auth.access_token", "diy_crate.auth.refresh_token"
)
sys.exit(1)
else:
response_json: List[str] = response.json()
access_token_resolved, refresh_token = response_json
r_c.set("diy_crate.auth.access_token", access_token_resolved)
r_c.set("diy_crate.auth.refresh_token", refresh_token)
client.auth._update_current_tokens(access_token_resolved, refresh_token)

except Exception:
crate_logger.warning(
"Encountered error getting root box folder", exc_info=True
Expand Down Expand Up @@ -311,7 +343,7 @@ def main():
oauth = bottle_app.oauth
else:
try:
oauth = setup_remote_oauth(r_c, conf=conf_obj)
oauth = setup_remote_oauth(r_c, conf=conf_obj, bottle_app=bottle_app)
start_cloud_threads(oauth)
bottle_app.started_cloud_threads = True
except exception.BoxOAuthException:
Expand All @@ -329,6 +361,10 @@ def main():
if bottle_thread and not bottle_thread.is_alive():
bottle_thread.start()

while threading.active_count() > 1:
time.sleep(0.1)
notifier.stop()


if __name__ == "__main__":
main()
29 changes: 24 additions & 5 deletions diycrate/file_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import json
import os
import queue
import sys
import threading
import logging
import time
Expand All @@ -10,6 +11,7 @@
from functools import partial
from pathlib import Path
from typing import Union, List, Dict, Optional
import typing

import boxsdk.object.file
import dateutil
Expand Down Expand Up @@ -40,7 +42,7 @@
)
from .iter_utils import SafeIter
from .log_utils import setup_logger
from .oauth_utils import setup_remote_oauth
from .oauth_utils import get_access_token, setup_remote_oauth

setup_logger()

Expand Down Expand Up @@ -722,7 +724,9 @@ def process_move_event(self, event: pyinotify.Event):
r_c.set(redis_key(src_file.object_id), json.dumps(version_info))
r_c.set("diy_crate.last_save_time_stamp", int(time.time()))
path_builder = BOX_DIR
oauth = setup_remote_oauth(r_c, conf=conf_obj)
oauth = setup_remote_oauth(
r_c, conf=conf_obj, bottle_app=self.bottle_app
)
client = Client(oauth)
parent_folders: list[Folder] = (
client.file(file_obj.object_id)
Expand Down Expand Up @@ -1151,7 +1155,7 @@ def process_IN_CLOSE(self, event: pyinotify.Event):

def get_box_folder(
client: Client, cur_box_folder: Optional[Folder], folder_id: str, retry_limit: int
):
) -> Folder:
"""
:param client:
Expand All @@ -1162,15 +1166,30 @@ def get_box_folder(
"""
for i in range(retry_limit):
try:
box_folder = client.folder(folder_id=folder_id).get()
box_folder_skeleton: Folder = typing.cast(
Folder, client.folder(folder_id=folder_id)
)
box_folder: Folder = typing.cast(Folder, box_folder_skeleton.get())
cur_box_folder = box_folder
break
except BoxAPIException as e:
get_access_token(
client.auth._access_token, bottle_app=None, oauth=client.auth
)
if i == retry_limit - 1:
crate_logger.info("Bad box api response.", exc_info=e)
if r_c.exists("diy_crate.auth.access_token") and r_c.exists(
"diy_crate.auth.refresh_token"
):
r_c.delete(
"diy_crate.auth.access_token", "diy_crate.auth.refresh_token"
)
sys.exit(1)
except (
ConnectionError,
BrokenPipeError,
ProtocolError,
ConnectionResetError,
BoxAPIException,
):
if i + 1 >= retry_limit:
crate_logger.warning(
Expand Down
2 changes: 1 addition & 1 deletion diycrate/item_queue_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ def download_queue_processor(queue_item: "DownloadQueueItem"):
)


def perform_download(item: File, path: Union[str, Path], retry_limit=15):
def perform_download(item: File | Folder, path: Union[str, Path], retry_limit=15):
if isinstance(path, str):
path = Path(path)
for i in range(retry_limit):
Expand Down
8 changes: 7 additions & 1 deletion diycrate/long_poll_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
download_queue_processor,
)
from diycrate.log_utils import setup_logger
from diycrate.oauth_utils import get_access_token

setup_logger()

Expand Down Expand Up @@ -948,7 +949,12 @@ def long_poll_event_listener(file_event_handler):
timedelta(days=32),
str(next_stream_position),
)
except (exception.BoxAPIException, AttributeError):
except exception.BoxAPIException as e:
crate_logger.warning("Box or AttributeError occurred.", exc_info=e)
get_access_token(
client.auth._access_token, bottle_app=None, oauth=client.auth
)
except (AttributeError):
crate_logger.warning("Box or AttributeError occurred.", exc_info=True)
except Exception:
crate_logger.warning("General error occurred.", exc_info=True)
Loading

0 comments on commit 5b1cc91

Please sign in to comment.