fix: ensure token refresh works regardless where API client is used

This commit is contained in:
Lance Edgar 2026-02-28 12:53:18 -06:00
parent c353d5bcef
commit d465934818
7 changed files with 30 additions and 23 deletions

View file

@ -136,7 +136,7 @@ class WuttaFarmAppHandler(base.AppHandler):
factory = self.load_object(spec) factory = self.load_object(spec)
return factory(self.config, farmos_client) return factory(self.config, farmos_client)
def auto_sync_to_farmos(self, obj, model_name=None, token=None, require=True): def auto_sync_to_farmos(self, obj, model_name=None, client=None, require=True):
""" """
Export the given object to farmOS, using configured handler. Export the given object to farmOS, using configured handler.
@ -147,8 +147,8 @@ class WuttaFarmAppHandler(base.AppHandler):
:param obj: Any data object in WuttaFarm, e.g. AnimalAsset :param obj: Any data object in WuttaFarm, e.g. AnimalAsset
instance. instance.
:param token: OAuth2 token for the farmOS client. If not :param client: Existing farmOS API client to use. If not
specified, the import handler will obtain a new token. specified, a new one will be instantiated.
:param require: If true, this will *require* the export :param require: If true, this will *require* the export
handler to support objects of the given type. If false, handler to support objects of the given type. If false,
@ -165,12 +165,12 @@ class WuttaFarmAppHandler(base.AppHandler):
return return
# nb. begin txn to establish the API client # nb. begin txn to establish the API client
handler.begin_target_transaction(token) handler.begin_target_transaction(client)
importer = handler.get_importer(model_name, caches_target=False) importer = handler.get_importer(model_name, caches_target=False)
normal = importer.normalize_source_object(obj) normal = importer.normalize_source_object(obj)
importer.process_data(source_data=[normal]) importer.process_data(source_data=[normal])
def auto_sync_from_farmos(self, obj, model_name, token=None, require=True): def auto_sync_from_farmos(self, obj, model_name, client=None, require=True):
""" """
Import the given object from farmOS, using configured handler. Import the given object from farmOS, using configured handler.
@ -179,8 +179,8 @@ class WuttaFarmAppHandler(base.AppHandler):
:param model_name': Model name for the importer to use, :param model_name': Model name for the importer to use,
e.g. ``"AnimalAsset"``. e.g. ``"AnimalAsset"``.
:param token: OAuth2 token for the farmOS client. If not :param client: Existing farmOS API client to use. If not
specified, the import handler will obtain a new token. specified, a new one will be instantiated.
:param require: If true, this will *require* the import :param require: If true, this will *require* the import
handler to support objects of the given type. If false, handler to support objects of the given type. If false,
@ -195,7 +195,7 @@ class WuttaFarmAppHandler(base.AppHandler):
return return
# nb. begin txn to establish the API client # nb. begin txn to establish the API client
handler.begin_source_transaction(token) handler.begin_source_transaction(client)
with self.short_session(commit=True) as session: with self.short_session(commit=True) as session:
handler.target_session = session handler.target_session = session
importer = handler.get_importer(model_name, caches_target=False) importer = handler.get_importer(model_name, caches_target=False)

View file

@ -50,13 +50,15 @@ class ToFarmOSHandler(ImportHandler):
# TODO: a lot of duplication to cleanup here; see FromFarmOSHandler # TODO: a lot of duplication to cleanup here; see FromFarmOSHandler
def begin_target_transaction(self, token=None): def begin_target_transaction(self, client=None):
""" """
Establish the farmOS API client. Establish the farmOS API client.
""" """
if not token: if client:
self.farmos_client = client
else:
token = self.get_farmos_oauth2_token() token = self.get_farmos_oauth2_token()
self.farmos_client = self.app.get_farmos_client(token=token) self.farmos_client = self.app.get_farmos_client(token=token)
self.farmos_4x = self.app.is_farmos_4x(self.farmos_client) self.farmos_4x = self.app.is_farmos_4x(self.farmos_client)
def get_farmos_oauth2_token(self): def get_farmos_oauth2_token(self):

View file

@ -46,13 +46,15 @@ class FromFarmOSHandler(ImportHandler):
source_key = "farmos" source_key = "farmos"
generic_source_title = "farmOS" generic_source_title = "farmOS"
def begin_source_transaction(self, token=None): def begin_source_transaction(self, client=None):
""" """
Establish the farmOS API client. Establish the farmOS API client.
""" """
if not token: if client:
self.farmos_client = client
else:
token = self.get_farmos_oauth2_token() token = self.get_farmos_oauth2_token()
self.farmos_client = self.app.get_farmos_client(token=token) self.farmos_client = self.app.get_farmos_client(token=token)
self.farmos_4x = self.app.is_farmos_4x(self.farmos_client) self.farmos_4x = self.app.is_farmos_4x(self.farmos_client)
self.normal = self.app.get_normalizer(self.farmos_client) self.normal = self.app.get_normalizer(self.farmos_client)

View file

@ -32,6 +32,7 @@ from wuttafarm.db.model import AnimalType, AnimalAsset
from wuttafarm.web.views.assets import AssetTypeMasterView, AssetMasterView from wuttafarm.web.views.assets import AssetTypeMasterView, AssetMasterView
from wuttafarm.web.forms.schema import AnimalTypeRef from wuttafarm.web.forms.schema import AnimalTypeRef
from wuttafarm.web.forms.widgets import ImageWidget from wuttafarm.web.forms.widgets import ImageWidget
from wuttafarm.web.util import get_farmos_client_for_user
class AnimalTypeView(AssetTypeMasterView): class AnimalTypeView(AssetTypeMasterView):
@ -168,8 +169,8 @@ class AnimalTypeView(AssetTypeMasterView):
session.flush() session.flush()
if self.app.is_farmos_mirror(): if self.app.is_farmos_mirror():
token = self.request.session.get("farmos.oauth2.token") client = get_farmos_client_for_user(self.request)
self.app.auto_sync_to_farmos(animal_type, token=token) self.app.auto_sync_to_farmos(animal_type, client=client)
return { return {
"uuid": animal_type.uuid.hex, "uuid": animal_type.uuid.hex,

View file

@ -112,8 +112,8 @@ class WuttaFarmMasterView(MasterView):
# maybe also sync change to farmOS # maybe also sync change to farmOS
if self.app.is_farmos_mirror(): if self.app.is_farmos_mirror():
token = self.request.session.get("farmos.oauth2.token") client = get_farmos_client_for_user(self.request)
self.app.auto_sync_to_farmos(obj, token=token, require=False) self.app.auto_sync_to_farmos(obj, client=client, require=False)
def get_farmos_entity_type(self): def get_farmos_entity_type(self):
if self.farmos_entity_type: if self.farmos_entity_type:

View file

@ -32,6 +32,7 @@ from wuttafarm.db.model import PlantType, PlantAsset
from wuttafarm.web.views.assets import AssetTypeMasterView, AssetMasterView from wuttafarm.web.views.assets import AssetTypeMasterView, AssetMasterView
from wuttafarm.web.forms.schema import PlantTypeRefs from wuttafarm.web.forms.schema import PlantTypeRefs
from wuttafarm.web.forms.widgets import ImageWidget from wuttafarm.web.forms.widgets import ImageWidget
from wuttafarm.web.util import get_farmos_client_for_user
class PlantTypeView(AssetTypeMasterView): class PlantTypeView(AssetTypeMasterView):
@ -161,8 +162,8 @@ class PlantTypeView(AssetTypeMasterView):
session.flush() session.flush()
if self.app.is_farmos_mirror(): if self.app.is_farmos_mirror():
token = self.request.session.get("farmos.oauth2.token") client = get_farmos_client_for_user(self.request)
self.app.auto_sync_to_farmos(plant_type, token=token) self.app.auto_sync_to_farmos(plant_type, client=client)
return { return {
"uuid": plant_type.uuid.hex, "uuid": plant_type.uuid.hex,

View file

@ -34,6 +34,7 @@ from wuttaweb.forms.schema import WuttaDateTime
from wuttaweb.forms.widgets import WuttaDateTimeWidget from wuttaweb.forms.widgets import WuttaDateTimeWidget
from wuttafarm.web.views.quick import QuickFormView from wuttafarm.web.views.quick import QuickFormView
from wuttafarm.web.util import get_farmos_client_for_user
class EggsQuickForm(QuickFormView): class EggsQuickForm(QuickFormView):
@ -118,11 +119,11 @@ class EggsQuickForm(QuickFormView):
if self.app.is_farmos_mirror(): if self.app.is_farmos_mirror():
quantity = json.loads(response["create-quantity"]["body"]) quantity = json.loads(response["create-quantity"]["body"])
token = self.request.session.get("farmos.oauth2.token") client = get_farmos_client_for_user(self.request)
self.app.auto_sync_from_farmos( self.app.auto_sync_from_farmos(
quantity["data"], "StandardQuantity", token=token quantity["data"], "StandardQuantity", client=client
) )
self.app.auto_sync_from_farmos(log["data"], "HarvestLog", token=token) self.app.auto_sync_from_farmos(log["data"], "HarvestLog", client=client)
return log return log