fix: preserve oauth2 token so auto-refresh works correctly

also add `get_farmos_client()` handler methods
This commit is contained in:
Lance Edgar 2026-02-05 20:06:55 -06:00
parent 45bb985465
commit 19dcc2d24b
6 changed files with 31 additions and 11 deletions

View file

@ -43,7 +43,7 @@ class WuttaFarmAppHandler(base.AppHandler):
if "farmos" not in self.handlers: if "farmos" not in self.handlers:
spec = self.config.get( spec = self.config.get(
f"{self.appname}.farmos_handler", f"{self.appname}.farmos_handler",
default="wuttafarm.farmos:FarmOSHandler", default="wuttafarm.farmos.handler:FarmOSHandler",
) )
factory = self.load_object(spec) factory = self.load_object(spec)
self.handlers["farmos"] = factory(self.config) self.handlers["farmos"] = factory(self.config)
@ -52,7 +52,15 @@ class WuttaFarmAppHandler(base.AppHandler):
def get_farmos_url(self, *args, **kwargs): def get_farmos_url(self, *args, **kwargs):
""" """
Get a farmOS URL. This is a convenience wrapper around Get a farmOS URL. This is a convenience wrapper around
:meth:`~wuttafarm.farmos.FarmOSHandler.get_farmos_url()`. :meth:`~wuttafarm.farmos.handler.FarmOSHandler.get_farmos_url()`.
""" """
handler = self.get_farmos_handler() handler = self.get_farmos_handler()
return handler.get_farmos_url(*args, **kwargs) return handler.get_farmos_url(*args, **kwargs)
def get_farmos_client(self, *args, **kwargs):
"""
Get a farmOS client. This is a convenience wrapper around
:meth:`~wuttafarm.farmos.handler.FarmOSHandler.get_farmos_client()`.
"""
handler = self.get_farmos_handler()
return handler.get_farmos_client(*args, **kwargs)

View file

@ -25,7 +25,6 @@ Auth handler for use with farmOS
from uuid import UUID from uuid import UUID
from farmOS import farmOS
from oauthlib.oauth2.rfc6749.errors import InvalidGrantError from oauthlib.oauth2.rfc6749.errors import InvalidGrantError
from sqlalchemy import orm from sqlalchemy import orm
@ -89,8 +88,7 @@ class WuttaFarmAuthHandler(AuthHandler):
return None return None
def get_farmos_oauth2_token(self, username, password): def get_farmos_oauth2_token(self, username, password):
url = self.app.get_farmos_url() client = self.app.get_farmos_client()
client = farmOS(url)
try: try:
return client.authorize(username=username, password=password) return client.authorize(username=username, password=password)
except InvalidGrantError: except InvalidGrantError:

View file

View file

@ -23,6 +23,8 @@
farmOS integration handler farmOS integration handler
""" """
from farmOS import farmOS
from wuttjamaican.app import GenericHandler from wuttjamaican.app import GenericHandler
@ -32,6 +34,14 @@ class FarmOSHandler(GenericHandler):
:term:`handler`. :term:`handler`.
""" """
def get_farmos_client(self, hostname=None, **kwargs):
"""
Returns a new farmOS API client.
"""
if not hostname:
hostname = self.get_farmos_url()
return farmOS(hostname, **kwargs)
def get_farmos_url(self, path=None, require=True): def get_farmos_url(self, path=None, require=True):
""" """
Returns the base URL for farmOS, or one with ``path`` appended. Returns the base URL for farmOS, or one with ``path`` appended.

View file

@ -27,8 +27,6 @@ import datetime
import colander import colander
from farmOS import farmOS
from wuttafarm.web.views.farmos import FarmOSMasterView from wuttafarm.web.views.farmos import FarmOSMasterView
from wuttafarm.web.forms.widgets import AnimalImage from wuttafarm.web.forms.widgets import AnimalImage

View file

@ -23,8 +23,6 @@
Base class for farmOS master views Base class for farmOS master views
""" """
from farmOS import farmOS
from wuttaweb.views import MasterView from wuttaweb.views import MasterView
@ -54,8 +52,16 @@ class FarmOSMasterView(MasterView):
if not token: if not token:
raise self.forbidden() raise self.forbidden()
url = self.app.get_farmos_url() def token_updater(token):
return farmOS(url, token=token) self.request.session["farmos.oauth2.token"] = token
# nb. must give a *copy* of the token to farmOS client, since
# it will mutate it in-place and we don't want that to happen
# for our original copy in the user session. (otherwise the
# auto-refresh will not work correctly for subsequent calls.)
token = dict(token)
return self.app.get_farmos_client(token=token, token_updater=token_updater)
def get_template_context(self, context): def get_template_context(self, context):