Compare commits

...

3 commits

Author SHA1 Message Date
e7d6a10751 docs: update docs link in readme 2026-01-05 13:02:38 -06:00
552c03af3e bump: version 0.3.0 → 0.3.1 2025-12-31 19:11:18 -06:00
d22a9963bf fix: set transaction user based on session info, when applicable
combined with `--runas` CLI param, this gives "any" command a way to
assign authorship for versioning
2025-12-29 10:41:09 -06:00
5 changed files with 69 additions and 29 deletions

View file

@ -5,6 +5,12 @@ All notable changes to Wutta-Continuum will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## v0.3.1 (2025-12-31)
### Fix
- set transaction user based on session info, when applicable
## v0.3.0 (2025-12-20)
### Feat

View file

@ -3,4 +3,4 @@
SQLAlchemy-Continuum versioning for Wutta Framework
See docs at https://rattailproject.org/docs/wutta-continuum/
See docs at https://docs.wuttaproject.org/wutta-continuum/

View file

@ -6,7 +6,7 @@ build-backend = "hatchling.build"
[project]
name = "Wutta-Continuum"
version = "0.3.0"
version = "0.3.1"
description = "SQLAlchemy-Continuum versioning for Wutta Framework"
readme = "README.md"
authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]

View file

@ -80,6 +80,9 @@ class WuttaContinuumConfigExtension(WuttaConfigExtension):
[wutta_continuum]
wutta_plugin_spec = poser.db.continuum:PoserContinuumPlugin
See also the SQLAlchemy-Continuum docs for
:doc:`sqlalchemy-continuum:plugins`.
"""
# only do this if config enables it
if not config.get_bool(
@ -113,44 +116,64 @@ class WuttaContinuumPlugin(Plugin):
"""
SQLAlchemy-Continuum manager plugin for Wutta-Continuum.
This tries to assign the current user and IP address to the
transaction.
This is the default plugin used within
:meth:`~WuttaContinuumConfigExtension.startup()` unless config
overrides.
It will assume the "current machine" IP address, which may be
suitable for some apps but not all (e.g. web apps, where IP
address should reflect an arbitrary client machine).
However it does not actually have a way to determine the current
user. WuttaWeb therefore uses a different plugin, based on this
one, to get both the user and IP address from current request.
You can override this to use a custom plugin for this purpose; if
so you must specify in your config file:
.. code-block:: ini
[wutta_continuum]
wutta_plugin_spec = poser.db.continuum:PoserContinuumPlugin
This tries to establish the user and IP address responsible, and
comment if applicable, for the current transaction.
See also the SQLAlchemy-Continuum docs for
:doc:`sqlalchemy-continuum:plugins`.
"""
def get_remote_addr( # pylint: disable=empty-docstring,unused-argument
self, uow, session
):
""" """
def get_remote_addr(self, uow, session): # pylint: disable=unused-argument
"""
This should return the effective IP address responsible for
the current change(s).
Default logic will assume the "current machine" e.g. where a
CLI command or script is running. In practice that often
means this winds up being ``127.0.0.1`` or similar.
:returns: IP address (v4 or v6) as string
"""
host = socket.gethostname()
return socket.gethostbyname(host)
def get_user_id( # pylint: disable=empty-docstring,unused-argument
self, uow, session
):
""" """
def get_user_id(self, uow, session): # pylint: disable=unused-argument
"""
This should return the effective ``User.uuid`` indicating who
is responsible for the current change(s).
Default logic does not have a way to determine current user on
its own per se. However it can inspect the session, and use a
value from there if found.
Any session can therefore declare the resonsible user::
myuser = session.query(model.User).first()
session.info["continuum_user_id"] = myuser.uuid
:returns: :attr:`wuttjamaican.db.model.auth.User.uuid` value,
or ``None``
"""
if user_id := session.info.get("continuum_user_id"):
return user_id
return None
def transaction_args(self, uow, session): # pylint: disable=empty-docstring
""" """
def transaction_args(self, uow, session):
"""
This is a standard hook method for SQLAchemy-Continuum
plugins. We use it to (try to) inject these values, which
then become set on the current (new) transaction:
* ``remote_addr`` - effective IP address causing the change
* see :meth:`get_remote_addr()`
* ``user_id`` - effective ``User.uuid`` for change authorship
* see :meth:`get_user_id()`
"""
kwargs = {}
remote_addr = self.get_remote_addr(uow, session)

View file

@ -55,9 +55,20 @@ class TestWuttaContinuumPlugin(DataTestCase):
self.assertEqual(plugin.get_remote_addr(None, self.session), "127.0.0.1")
def test_user_id(self):
model = self.app.model
plugin = self.make_plugin()
fred = model.User(username="fred")
self.session.add(fred)
self.session.commit()
# empty by default
self.assertIsNone(plugin.get_user_id(None, self.session))
# but session can declare one
self.session.info["continuum_user_id"] = fred.uuid
self.assertEqual(plugin.get_user_id(None, self.session), fred.uuid)
def test_transaction_args(self):
plugin = self.make_plugin()
with patch.object(socket, "gethostbyname", return_value="127.0.0.1"):