kvesteri / postgresql-audit

Audit trigger for PostgreSQL
BSD 2-Clause "Simplified" License
126 stars 28 forks source link

Does not seem to work with a minimal pyramid application #39

Open mateus-geru opened 5 years ago

mateus-geru commented 5 years ago

Hi!

I've been failing to make PostgreSQL-Audit work with a small pyramid application I've built to test their integration: the application declares a Customer model and exposes an endpoint which updates the versioned table by suffixing an s to the customer's name... it should be enough to trigger the due listeners and populate the transaction and activity tables, but no such thing happens.

Given the documentation, there shouldn't be much setup to use this lib.

My actual goal is to use PostgreSQL-Audit in a pyramid application using pyramid-tm to back the commit/rollback at request time and a ZopeTransactionExtension to back the db sessions with a transaction, but it doesn't seem to work with a way simpler setup.

Am I missing something? Any thoughts?

Thanks!

some dependencies:

python: 3.6.7
PostgreSQL-Audit==0.11.1
SQLAlchemy==1.3.8 
SQLAlchemy-Utils==0.34.2
psycopg2==2.8.3
pyramid==1.10.4

Application structure:

├── alembic.ini
├── app.py
├── conf.ini
├── migrations
│   ├── env.py
│   └── versions
│       ├── 9c2b8f5f3aca_first.py
│       └── a9a328ebaaaa_add_versioning.py
└── setup.py

app.py (it can be ran with gunicorn --paste conf.ini)

from pyramid.config import Configurator
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker

DBSession = scoped_session(sessionmaker(autoflush=False))
Base = declarative_base()

from postgresql_audit import versioning_manager
versioning_manager.init(Base)

class Customer(Base):

    __tablename__ = 'customer'
    __versioned__ = {}

    id = Column(Integer, primary_key=True)
    name = Column(String)

    def json(self):
        return {'id': self.id, 'name': self.name}

def main(global_config, **settings):

    config = Configurator()

    engine = create_engine(name_or_url=settings['sqlalchemy.url'])
    DBSession.configure(bind=engine)
    Base.metadata.bind = engine

    def customer(request):
        customers = []
        for c in DBSession.query(Customer).all():
            customers.append(c.json())

        return customers

    config.add_route('customer', '/')
    config.add_view(customer, route_name='customer', renderer='json')

    def update(request):
        c = DBSession.query(Customer).first()
        c.name = c.name + 's'

        DBSession.flush()
        DBSession.commit()

        return {'id': c.id, 'name': c.name}

    config.add_route('update', '/update')
    config.add_view(update, route_name='update', renderer='json')

    return config.make_wsgi_app()

conf.ini

[app:main]
use = egg:test_pg_audit

sqlalchemy.url = postgres+psycopg2://dev:dev@localhost:5432/test_pg_audit

[server:main]
use = egg:gunicorn#main
workers = 4
preload = true
reload = false
accesslog = -
loglevel = debug
host = 127.0.0.1
port = 6543