Add application_id column to AuditEvent
Use application_id and portfolio_id if the resource is a portfolio in AuditableMixin Clean up some residual references to workspace
This commit is contained in:
parent
42900a20a6
commit
b3ecd1658c
@ -0,0 +1,32 @@
|
|||||||
|
"""add_appliction_id_to_auditevent
|
||||||
|
|
||||||
|
Revision ID: c5deba1826be
|
||||||
|
Revises: 404bb5bb3a0e
|
||||||
|
Create Date: 2019-05-15 16:30:27.981456
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import postgresql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'c5deba1826be'
|
||||||
|
down_revision = '404bb5bb3a0e'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('audit_events', sa.Column('application_id', postgresql.UUID(as_uuid=True), nullable=True))
|
||||||
|
op.create_index(op.f('ix_audit_events_application_id'), 'audit_events', ['application_id'], unique=False)
|
||||||
|
op.create_foreign_key('audit_events_application_application_id', 'audit_events', 'applications', ['application_id'], ['id'])
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_constraint('audit_events_application_application_id', 'audit_events', type_='foreignkey')
|
||||||
|
op.drop_index(op.f('ix_audit_events_application_id'), table_name='audit_events')
|
||||||
|
op.drop_column('audit_events', 'application_id')
|
||||||
|
# ### end Alembic commands ###
|
@ -14,15 +14,10 @@ class AuditEventQuery(Query):
|
|||||||
return cls.paginate(query, pagination_opts)
|
return cls.paginate(query, pagination_opts)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_ws_events(cls, portfolio_id, pagination_opts):
|
def get_portfolio_events(cls, portfolio_id, pagination_opts):
|
||||||
query = (
|
query = (
|
||||||
db.session.query(cls.model)
|
db.session.query(cls.model)
|
||||||
.filter(
|
.filter(cls.model.portfolio_id == portfolio_id)
|
||||||
or_(
|
|
||||||
cls.model.portfolio_id == portfolio_id,
|
|
||||||
cls.model.resource_id == portfolio_id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.order_by(cls.model.time_created.desc())
|
.order_by(cls.model.time_created.desc())
|
||||||
)
|
)
|
||||||
return cls.paginate(query, pagination_opts)
|
return cls.paginate(query, pagination_opts)
|
||||||
@ -39,7 +34,8 @@ class AuditLog(object):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_portfolio_events(cls, portfolio, pagination_opts=None):
|
def get_portfolio_events(cls, portfolio, pagination_opts=None):
|
||||||
return AuditEventQuery.get_ws_events(portfolio.id, pagination_opts)
|
return AuditEventQuery.get_portfolio_events(portfolio.id, pagination_opts)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_by_resource(cls, resource_id):
|
def get_by_resource(cls, resource_id):
|
||||||
|
@ -17,11 +17,17 @@ class AuditEvent(Base, TimestampsMixin):
|
|||||||
portfolio_id = Column(UUID(as_uuid=True), ForeignKey("portfolios.id"), index=True)
|
portfolio_id = Column(UUID(as_uuid=True), ForeignKey("portfolios.id"), index=True)
|
||||||
portfolio = relationship("Portfolio", backref="audit_events")
|
portfolio = relationship("Portfolio", backref="audit_events")
|
||||||
|
|
||||||
|
application_id = Column(
|
||||||
|
UUID(as_uuid=True), ForeignKey("applications.id"), index=True
|
||||||
|
)
|
||||||
|
application = relationship("Application", backref="audit_events")
|
||||||
|
|
||||||
changed_state = Column(JSONB())
|
changed_state = Column(JSONB())
|
||||||
event_details = Column(JSONB())
|
event_details = Column(JSONB())
|
||||||
|
|
||||||
resource_type = Column(String(), nullable=False)
|
resource_type = Column(String(), nullable=False)
|
||||||
resource_id = Column(UUID(as_uuid=True), index=True, nullable=False)
|
resource_id = Column(UUID(as_uuid=True), index=True, nullable=False)
|
||||||
|
|
||||||
display_name = Column(String())
|
display_name = Column(String())
|
||||||
action = Column(String(), nullable=False)
|
action = Column(String(), nullable=False)
|
||||||
|
|
||||||
@ -29,6 +35,7 @@ class AuditEvent(Base, TimestampsMixin):
|
|||||||
def log(self):
|
def log(self):
|
||||||
return {
|
return {
|
||||||
"portfolio_id": str(self.portfolio_id),
|
"portfolio_id": str(self.portfolio_id),
|
||||||
|
"application_id": str(self.application_id),
|
||||||
"changed_state": self.changed_state,
|
"changed_state": self.changed_state,
|
||||||
"event_details": self.event_details,
|
"event_details": self.event_details,
|
||||||
"resource_type": self.resource_type,
|
"resource_type": self.resource_type,
|
||||||
|
@ -13,17 +13,27 @@ class AuditableMixin(object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def create_audit_event(connection, resource, action, changed_state=None):
|
def create_audit_event(connection, resource, action, changed_state=None):
|
||||||
user_id = getattr_path(g, "current_user.id")
|
user_id = getattr_path(g, "current_user.id")
|
||||||
portfolio_id = resource.portfolio_id
|
|
||||||
resource_type = resource.resource_type
|
resource_type = resource.resource_type
|
||||||
display_name = resource.displayname
|
display_name = resource.displayname
|
||||||
event_details = resource.event_details
|
event_details = resource.event_details
|
||||||
|
|
||||||
|
if resource_type == "portfolio":
|
||||||
|
portfolio_id = resource.id
|
||||||
|
else:
|
||||||
|
portfolio_id = resource.portfolio_id
|
||||||
|
|
||||||
|
if resource_type == "application":
|
||||||
|
application_id = resource.id
|
||||||
|
else:
|
||||||
|
application_id = resource.application_id
|
||||||
|
|
||||||
if changed_state is None:
|
if changed_state is None:
|
||||||
changed_state = resource.history if action == ACTION_UPDATE else None
|
changed_state = resource.history if action == ACTION_UPDATE else None
|
||||||
|
|
||||||
audit_event = AuditEvent(
|
audit_event = AuditEvent(
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
portfolio_id=portfolio_id,
|
portfolio_id=portfolio_id,
|
||||||
|
application_id=application_id,
|
||||||
resource_type=resource_type,
|
resource_type=resource_type,
|
||||||
resource_id=resource.id,
|
resource_id=resource.id,
|
||||||
display_name=display_name,
|
display_name=display_name,
|
||||||
@ -95,6 +105,10 @@ class AuditableMixin(object):
|
|||||||
def portfolio_id(self):
|
def portfolio_id(self):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def application_id(self):
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def displayname(self):
|
def displayname(self):
|
||||||
return None
|
return None
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from atst.domain.applications import Applications
|
||||||
from atst.domain.audit_log import AuditLog
|
from atst.domain.audit_log import AuditLog
|
||||||
from atst.domain.exceptions import UnauthorizedError
|
from atst.domain.exceptions import UnauthorizedError
|
||||||
from atst.domain.permission_sets import PermissionSets
|
from atst.domain.permission_sets import PermissionSets
|
||||||
@ -45,7 +46,7 @@ def test_paginate_ws_audit_log():
|
|||||||
assert len(events) == 25
|
assert len(events) == 25
|
||||||
|
|
||||||
|
|
||||||
def test_ws_audit_log_only_includes_current_ws_events():
|
def test_portfolio_audit_log_only_includes_current_portfolio_events():
|
||||||
owner = UserFactory.create()
|
owner = UserFactory.create()
|
||||||
portfolio = PortfolioFactory.create(owner=owner)
|
portfolio = PortfolioFactory.create(owner=owner)
|
||||||
other_portfolio = PortfolioFactory.create(owner=owner)
|
other_portfolio = PortfolioFactory.create(owner=owner)
|
||||||
@ -55,8 +56,30 @@ def test_ws_audit_log_only_includes_current_ws_events():
|
|||||||
|
|
||||||
events = AuditLog.get_portfolio_events(portfolio)
|
events = AuditLog.get_portfolio_events(portfolio)
|
||||||
for event in events:
|
for event in events:
|
||||||
assert event.portfolio_id == portfolio.id or event.resource_id == portfolio.id
|
assert event.portfolio_id == portfolio.id
|
||||||
assert (
|
assert (
|
||||||
not event.portfolio_id == other_portfolio.id
|
not event.portfolio_id == other_portfolio.id
|
||||||
or event.resource_id == other_portfolio.id
|
or event.resource_id == other_portfolio.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_portfolio_audit_log_includes_app_and_env_events():
|
||||||
|
# TODO: add in events for
|
||||||
|
# creating/updating/deleting env_role and app_role
|
||||||
|
# creating an app_invitation
|
||||||
|
owner = UserFactory.create()
|
||||||
|
portfolio = PortfolioFactory.create(owner=owner)
|
||||||
|
application = ApplicationFactory.create(portfolio=portfolio)
|
||||||
|
Applications.update(application, {"name": "Star Cruiser"})
|
||||||
|
|
||||||
|
events = AuditLog.get_portfolio_events(portfolio)
|
||||||
|
|
||||||
|
for event in events:
|
||||||
|
assert event.portfolio_id == portfolio.id
|
||||||
|
if event.resource_type == 'application':
|
||||||
|
assert event.application_id == application.id
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_application_audit_log_does_not_include_portfolio_events():
|
||||||
|
pass
|
||||||
|
Loading…
x
Reference in New Issue
Block a user