Skip to content

Audit log: log invitations #9607

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Nov 23, 2022
Merged

Audit log: log invitations #9607

merged 16 commits into from
Nov 23, 2022

Conversation

stsewd
Copy link
Member

@stsewd stsewd commented Sep 16, 2022

Had to do some refactoring now that we are introducing more actions to logs, there are:

  • Add a json field (data) to the auditlog model, this is so we can store additional information about the log entry
    (useful to store information about the invitation)
  • Use an enum for the action choices (https://docs.djangoproject.com/en/4.1/ref/models/fields/#enumeration-types), they are easier to manage without duplicating things.
  • Change the tests from organizations/test_forms to test things at the view level, this is to avoid mocking more things from the request object.
  • Changed the tests from security logs to test the expected queryset instead of just the count, so we don't need to re-calculate everything every time we add a new thing.
  • Had to change how we display log entries, since we now have more actions and it gets complicated having one paragraph for each case (action / with/out user / with/out project, etc). This was suggested by Anthony on slack.

Screenshots

Screenshot 2022-09-20 at 13-10-29 Security Log - Read the Docs for Business
Screenshot 2022-09-20 at 13-10-10 Organization Security Log - Read the Docs for Business

Closes #9456.


📚 Documentation previews 📚

We are consuming more things from the request
object, instead of mocking more attributes,
let's just test at the view level.
@stsewd stsewd force-pushed the log-invitations branch 3 times, most recently from a2f42a8 to 5e8bc7d Compare September 20, 2022 18:22
@stsewd stsewd marked this pull request as ready for review September 20, 2022 18:33
@stsewd stsewd requested review from a team as code owners September 20, 2022 18:33
@stsewd stsewd requested review from agjohnson and humitos September 20, 2022 18:33
Comment on lines 88 to 96
PAGEVIEW = Actions.PAGEVIEW
DOWNLOAD = Actions.DOWNLOAD
AUTHN = Actions.AUTHN
AUTHN_FAILURE = Actions.AUTHN_FAILURE
LOGOUT = Actions.LOGOUT
INVITATION_SENT = Actions.INVITATION_SENT
INVITATION_REVOKED = Actions.INVITATION_REVOKED
INVITATION_ACCEPTED = Actions.INVITATION_ACCEPTED
INVITATION_DECLINED = Actions.INVITATION_DECLINED
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set these here to avoid having to refactor every place where we use them, and it's also easier to write AuditLog.PAGEVIEW than AuditLog.Actions.PAGEVIEW. We could also move this outside the model, so we can just write Actions.PAGEVIEW, but that will require changing every usage too, so.


<span class="quiet right" title="{{ log.created|date:"DATETIME_FORMAT" }}">
{% blocktrans trimmed with log.created|timesince as date %}
{{ date }} ago
{% endblocktrans %}
</span>

{# Data about the log entry #}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub displays logs as

Screenshot 2022-09-20 at 13-36-35 Security log

They show the IP and location

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This matches what I was describing the other day. The main translated string is "Country changed from your previous session", without introducing variables, and metadata is listed below.

Copy link
Contributor

@agjohnson agjohnson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't do a thorough job looking at Python, so would be good to get secondary review there. I'll have a lot of updates for this view when we get to reworking this UI, but for now, my inclination is probably to keep this UI very simple, and add more complex UI with new templates.

Addressing what we're storing and displaying is a great focus for this stage. We can come back to this UI with more complex additions, like filtering and search.


<span class="quiet right" title="{{ log.created|date:"DATETIME_FORMAT" }}">
{% blocktrans trimmed with log.created|timesince as date %}
{{ date }} ago
{% endblocktrans %}
</span>

{# Data about the log entry #}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This matches what I was describing the other day. The main translated string is "Country changed from your previous session", without introducing variables, and metadata is listed below.

Copy link
Member

@humitos humitos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this PR is fine. However, I'd invite another person to do a code review as well. To me, there are some new magic added in this PR that we have not been using and it's changing some of the patterns we have for the same things. I usually prefer consistency in these cases.

These new decisions made me spent more time than I would normally require to review this code. Changes aren't huge or complex, but I had to re-read multiple times them to understand the new approaches used for the same things we have solved in a different --and no that magic-- way.

AuditLog.objects.new(
action=action,
request=request,
data=InvitationSerializer(self).data,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This called my attention. I was wondering why we had created the readthedocs/invitations/serializers.py file if we are not exposing invitations via a REST API.

It seems we are using the DRF serializers for a different purpose here and I'm not convinced this is the right approach.

@agjohnson
Copy link
Contributor

@stsewd We're doing some sprint clean up, is there anything required on this PR to move forward?

@stsewd
Copy link
Member Author

stsewd commented Oct 26, 2022

@agjohnson there is a disagreement about using django's enum types for constants/options #9607 (comment).

@stsewd stsewd requested a review from humitos November 14, 2022 23:20

to_user = UserSerializer()
from_user = UserSerializer()
object = serializers.SerializerMethodField()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isnt' it a problem to override the object reserved word?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only when used as variable name, we can change it to obj if we want

Comment on lines 68 to 72
def get_object(self, obj):
serializers = {
"organization": OrganizationSerializer,
"project": ProjectSerializer,
"team": TeamSerializer,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to have a comment here saying that the value of object will depend on the object type and a different serializer will be used.

@stsewd stsewd merged commit 6e42d46 into main Nov 23, 2022
@stsewd stsewd deleted the log-invitations branch November 23, 2022 18:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Audit logs: add audit logs for invitations
3 participants