diff --git a/src/wuttafarm/web/util.py b/src/wuttafarm/web/util.py index ec88525..938c84b 100644 --- a/src/wuttafarm/web/util.py +++ b/src/wuttafarm/web/util.py @@ -27,7 +27,26 @@ from pyramid import httpexceptions from webhelpers2.html import HTML -def get_farmos_client_for_user(request): +def get_farmos_client_for_user(request, main_thread=True): + """ + Make and return a new farmOS API client instance. + + This is a wrapper around + :meth:`~wuttafarm.farmos.handler.FarmOSHandler.get_farmos_client()` + with conveniences to automatically handle token refresh for the + current user session. + + :param request: Current web request; this determines the user. + + :param main_thread: Boolean indicating whether this client is for + use within the main thread, or a separate one. In the latter + case it must perform certain extra steps to help with token + refresh. This defaults to ``True`` in which case the client is + part of the main thread, i.e. the normal request/response + cycle. + + :returns: farmOS API client instance + """ token = request.session.get("farmos.oauth2.token") if not token: raise httpexceptions.HTTPForbidden() @@ -39,14 +58,14 @@ def get_farmos_client_for_user(request): token = dict(token) def token_updater(token): - save_farmos_oauth2_token(request, token) + save_farmos_oauth2_token(request, token, main_thread=main_thread) config = request.wutta_config app = config.get_app() return app.get_farmos_client(token=token, token_updater=token_updater) -def save_farmos_oauth2_token(request, token): +def save_farmos_oauth2_token(request, token, main_thread=True): """ Common logic for saving the given OAuth2 token within the user session. This function is called from 2 places: @@ -61,6 +80,12 @@ def save_farmos_oauth2_token(request, token): # save token to user session request.session["farmos.oauth2.token"] = token + if not main_thread: + # nb. must call persist() explicitly in separate thread, since + # pyramid_beaker may not be in effect (iiuc?) + request.session.save() + request.session.persist() + def use_farmos_style_grid_links(config): return config.get_bool(f"{config.appname}.farmos_style_grid_links", default=True) diff --git a/src/wuttafarm/web/views/master.py b/src/wuttafarm/web/views/master.py index c828b96..e010f56 100644 --- a/src/wuttafarm/web/views/master.py +++ b/src/wuttafarm/web/views/master.py @@ -120,7 +120,7 @@ class WuttaFarmMasterView(MasterView): if self.app.is_farmos_mirror(): if self.creating: session.flush() # need the new uuid - client = get_farmos_client_for_user(self.request) + client = get_farmos_client_for_user(self.request, main_thread=False) thread = threading.Thread( target=self.auto_sync_to_farmos, args=(client, obj.uuid) ) @@ -168,7 +168,7 @@ class WuttaFarmMasterView(MasterView): # maybe delete from farmOS also if farmos_uuid: - client = get_farmos_client_for_user(self.request) + client = get_farmos_client_for_user(self.request, main_thread=False) # nb. must use separate thread to avoid some kind of race # condition (?) - seems as though maybe a "boomerang" # effect is happening; this seems to help anyway