Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
nilbacardit26 committed Dec 11, 2023
2 parents 1f66221 + c6ba827 commit 3a0b1b2
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 5 deletions.
1 change: 0 additions & 1 deletion .python-version

This file was deleted.

2 changes: 1 addition & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
1.0.4 (2023-11-16)
-----------------
------------------

- Changing requirement of guillotina

Expand Down
1 change: 1 addition & 0 deletions guillotina_audit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ def includeme(root, settings):
configure.scan("guillotina_audit.subscriber")
configure.scan("guillotina_audit.api")
configure.scan("guillotina_audit.permissions")
configure.scan("guillotina_audit.models")
30 changes: 30 additions & 0 deletions guillotina_audit/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import json
import datetime

from pydantic import BaseModel, field_serializer
from enum import Enum
from typing import Optional
from datetime import date

from datetime import timezone


class Action(str, Enum):
modified = "modified"
added = "added"
removed = "removed"
moved = "moved"
duplicated = "duplicated"

class Document(BaseModel):
action: Action
path: Optional[str] = None
uuid: Optional[str] = None
payload: Optional[dict] = None
creator: Optional[str] = None
creation_date: date = datetime.datetime.now(timezone.utc)
type_name: str

@field_serializer('payload')
def serialize_payload(self, payload: dict, _info):
return json.dumps(payload)
34 changes: 32 additions & 2 deletions guillotina_audit/subscriber.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from guillotina.interfaces import IObjectAddedEvent
from guillotina.interfaces import IObjectModifiedEvent
from guillotina.interfaces import IObjectRemovedEvent
from guillotina.interfaces import IObjectMovedEvent
from guillotina.interfaces import IObjectDuplicatedEvent
from guillotina.interfaces import IResource
from guillotina_audit.interfaces import IAuditUtility

Expand All @@ -17,9 +19,15 @@
) # after indexing
async def audit_object_added(obj, event):
try:
audit = query_utility(IAuditUtility)
audit.log_entry(obj, event)
if event.__providedBy__(IObjectDuplicatedEvent) is True:
pass
elif event.__providedBy__(IObjectMovedEvent) is True:
pass
elif event.__providedBy__(IObjectAddedEvent) is True:
audit = query_utility(IAuditUtility)
audit.log_entry(obj, event)
except Exception:
__import__("pdb").set_trace()
logger.error("Error adding audit", exc_info=True)


Expand All @@ -43,3 +51,25 @@ async def audit_object_removed(obj, event):
audit.log_entry(obj, event)
except Exception:
logger.error("Error adding audit", exc_info=True)


@configure.subscriber(
for_=(IResource, IObjectMovedEvent), priority=1001
) # after indexing
async def audit_object_moved(obj, event):
try:
audit = query_utility(IAuditUtility)
audit.log_entry(obj, event)
except Exception:
logger.error("Error adding audit", exc_info=True)


@configure.subscriber(
for_=(IResource, IObjectDuplicatedEvent), priority=1001
) # after indexing
async def audit_object_duplicated(obj, event):
try:
audit = query_utility(IAuditUtility)
audit.log_entry(obj, event)
except Exception:
logger.error("Error adding audit", exc_info=True)
69 changes: 69 additions & 0 deletions guillotina_audit/tests/test_audit_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from datetime import timedelta
from guillotina.component import query_utility
from guillotina_audit.interfaces import IAuditUtility
from guillotina_audit.models import Document

import asyncio
import json
Expand Down Expand Up @@ -84,3 +85,71 @@ async def test_audit_basic(guillotina_es):
) # noqa
assert len(resp["hits"]["hits"]) == 0
assert status == 200

response, status = await guillotina_es(
"POST",
"/db/guillotina/",
data=json.dumps({"@type": "Folder", "id": "foo_folder1", "title": "Foo Folder"}),
)
assert status == 201

response, status = await guillotina_es(
"POST",
"/db/guillotina/foo_folder1/@duplicate",
data=json.dumps({"destination": "/", "new_id": "foo_folder2"}),
)
assert status == 200

await asyncio.sleep(2)
resp, status = await guillotina_es(
"GET",
"/db/guillotina/@audit?action=duplicated",
) # noqa
assert len(resp["hits"]["hits"]) == 1
assert status == 200

response, status = await guillotina_es(
"POST",
"/db/guillotina/foo_folder2/@move",
data=json.dumps({"destination": "/foo_folder1"}),
)
assert status == 200
await asyncio.sleep(2)

resp, status = await guillotina_es(
"GET",
"/db/guillotina/@audit?action=moved",
) # noqa
assert len(resp["hits"]["hits"]) == 1
assert status == 200


async def test_audit_wildcard(guillotina_es):
response, status = await guillotina_es(
"POST", "/db/guillotina/@addons", data=json.dumps({"id": "audit"})
)
assert status == 200
await asyncio.sleep(2)
audit_utility = query_utility(IAuditUtility)

payload = Document(action="added", type_name="Fullscreen")
audit_utility.log_wildcard(payload)
await asyncio.sleep(2)

resp, status = await guillotina_es(
"GET",
"/db/guillotina/@audit?action=added&type_name=Fullscreen",
) # noqa
assert status == 200
assert len(resp["hits"]["hits"]) == 1

payload = Document(action="added", type_name="Click", path="/foopath", payload={"hola": "hola"}, creator="creator", uuid="12345")
audit_utility.log_wildcard(payload)
await asyncio.sleep(2)

resp, status = await guillotina_es(
"GET",
"/db/guillotina/@audit?action=added&type_name=Click",
) # noqa
assert status == 200
assert len(resp["hits"]["hits"]) == 1
16 changes: 15 additions & 1 deletion guillotina_audit/utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
from guillotina.interfaces import IObjectAddedEvent
from guillotina.interfaces import IObjectModifiedEvent
from guillotina.interfaces import IObjectRemovedEvent
from guillotina.interfaces import IObjectMovedEvent
from guillotina.interfaces import IObjectDuplicatedEvent
from guillotina.utils.auth import get_authenticated_user
from guillotina.utils.content import get_content_path
from guillotina_audit.models import Document

import asyncio
import datetime
Expand Down Expand Up @@ -65,10 +68,21 @@ def default_mappings(self):
},
}

def log_wildcard(self, payload: Document):
coroutine = self.async_es.index(index=self.index, body=payload.dict(exclude_unset=True))
asyncio.create_task(coroutine)

def log_entry(self, obj, event):
document = {}
user = get_authenticated_user()
if IObjectModifiedEvent.providedBy(event):

if IObjectDuplicatedEvent.providedBy(event):
document["action"] = "duplicated"
document["creation_date"] = datetime.datetime.now(timezone.utc)
elif IObjectMovedEvent.providedBy(event):
document["action"] = "moved"
document["creation_date"] = datetime.datetime.now(timezone.utc)
elif IObjectModifiedEvent.providedBy(event):
document["action"] = "modified"
document["creation_date"] = obj.modification_date
if self._settings.get("save_payload", False) is True:
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
packages=find_packages(exclude=["ez_setup"]),
install_requires=[
"guillotina>=6.0.0a16",
"pydantic",
"elasticsearch[async]>=7.8.0,<8.0.0",
"zope.interface==5.1.0" # TODO: remove once guillotina has solved this
],
Expand Down

0 comments on commit 3a0b1b2

Please sign in to comment.