Skip to content
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

Rewrite actionlogs not to specify constants based on other apps #229

Open
czlee opened this issue Aug 25, 2015 · 7 comments
Open

Rewrite actionlogs not to specify constants based on other apps #229

czlee opened this issue Aug 25, 2015 · 7 comments

Comments

@czlee
Copy link
Member

czlee commented Aug 25, 2015

Either write in a registration model like django-tagging, or better still, use an existing app that probably has the implementation done far better than we could, like (but not necessarily) django-activity-stream.

@czlee
Copy link
Member Author

czlee commented Sep 10, 2016

Rough plan/notes, assuming use of django-activity stream:

  • ActionLog.type would be replaced by the free-form Action.verb, and would no longer be restricted to a predefined list. I don't think this lack of restriction is a bad thing.
  • ActionLog.user would be replaced by Action.actor, except…
    • Not all actions have a user—public submissions only have an IP address. Since all actions must have a user, I'm not sure what to do about this.
  • ActionLog.tournament and ActionLog.ip_address don't have analogues in Action. One can argue these aren't really necessary, but I think they're useful information, so I'd be inclined to put them in an auxiliary model with a OneToOneField with Action. In particular, I think we'd want to preserve the ability to have feeds for everything relating to a tournament. This means we can't get rid of actionlog, but then, there are other reasons we can't as well—for example, django-activity-stream doesn't provide a LogActionMixin analogue either.
  • ActionLog.timestamp is replaced by Action.timestamp (obviously).
  • The fields storing the action object currently in ActionLog would be collapsed into a single content_object, which is how it should be anyway. No action currently takes more than one object, I'm happy just to restrict ourselves to one object per action in future.

That said, considering what django-activity-stream would actually add for us, over collapsing the plethora of object fields into a single content_object:

  • Generating/logging actions wouldn't be much different. We'd mostly go through LogActionMixin, which would also take care of the auxiliary model.
  • django-activity-stream provides a bunch of useful URLs, but we'd want to login-protect basically all of them, and I'm not sure if there's an easy way to do that. It looks like this tends to be done using middleware. Worst case, we can live without them, though they do seem pretty powerful.
    • There's also a public flag on Actions, which I assume hides it from public views if False. We'd presumably set this for everything, but we still don't really want the URLs to be accessible to the public at all.
  • django-activity-stream provides for the ability to follow and unfollow users. It's not clear to me that this is useful in our application.
  • Even without the URLs, though the streams and associated template tags might simplify doing things like implementing Add a page to view the action log #46.

That's a pretty inconclusive list of advantages to me—the main advantage would be collapsing eight fields into a GenericForeignKey, but we can do that ourselves fairly easily.

@czlee
Copy link
Member Author

czlee commented Sep 10, 2016

One option would be to create a new IPAddressUser model (which has no relation to any other model) whose sole purpose is to be an actor for the purposes of activity streams. This would allow IP addresses of public submissions to be searched as if they were an actor, I guess. Just not having an actor isn't really an option; that violates the Activity Streams spec.

@philipbelesky
Copy link
Member

Django-activity-stream sounds interesting; some of those URLs could be good drop-ins for the activity feeds on the dashboard. Plausibly there could be some actions marked as public if we ever wanted a public (sanitised) activity field.

Not sure I entirely get the issue with the actor/user problem. Could there be an intermediary model (say Actor in actionlogs) that could optionally link to a User, an ip_address field, or any other potential actor?

@czlee
Copy link
Member Author

czlee commented Sep 10, 2016

Yeah, but it's not necessary to go that far. The actor field takes a GenericForeignKey, so it can point to anything. For example, it could point to either an organization or a person, even if they're represented by different models.

In our case, logged-in user actions could just get the actor to point at the user, without any need for an intermediary model. The problem is that with anonymous users, there isn't currently an object associated with the actor at all. One way to resolve this would be to have a (different) model for anonymous users, one instance for each IP address. Unfortunately Django's AnonymousUser won't work here, because it's not a database object. This has been thought about before, it seems: justquick/django-activity-stream#16

I think the Activity Streams standard is actually a JSON/ATOM compatibility standard: http://activitystrea.ms/. I suppose in some distant future this would allow for third-party sites to pull information from Tabbycat sites as if they were a social activity stream?

Relatedly, Activity Streams 2.0 is currently a W3C Candidate Recommendation. It does look quite different from Activity Streams 1.0 though (which is what django-activity-streams implements). Activity Streams 2.0 is a bit more specific about things, for example, it predefined a bunch of action and object types that make sense for social media sites, but not really for us. If we went there, we'd be defining our own objects a lot ("debate", "ballot"). On one hand, this makes it seem that we're probably not its primary use-case. On the other hand, defining our own objects is permitted, and it might be sensible for, say, debating software to have a standard "extended vocabulary" over the standard vocabulary.

The compatibility stuff is all hypothetical though. If the question is, "would this help us now?", I don't know the answer.

czlee added a commit that referenced this issue Sep 11, 2016
- Includes migrations and data migrations
- Deprecated get_parameters_display in favour of get_content_object_display
- Does NOT remove existing fields (that will come later)
@czlee
Copy link
Member Author

czlee commented Sep 11, 2016

I converted ActionLogEntry to use ContentType rather than seven optional fields. Consequential changes to know about:

  1. LogActionMixin.get_action_log_type_fields() should no longer be overridden. Instead, the class attribute action_log_content_object_attr should be set to the name of the attribute of the view instance where LogActionMixin should look to find the relevant content_object for the ActionLogEntry. For example, in the case of feedback stored in self.adj_feedback, we set action_log_content_object_attr = 'adj_feedback'.
  2. ActionLogEntry still optionally takes both a tournament and a round in every entry. (Previously, it was just a tournament.) LogActionMixin will look in get_tournament() and get_round() if they exist. But some views pertaining to rounds aren't RoundMixins, for example, ballot submission views relate to ballots, not rounds. These views may wish to set self.round before self.log_action() is called. If self.round is a Round, then LogActionMixin will take that as the round.
  3. Where the relevant object is a tournament or round, the content_object of ActionLogEntry should now take it. (Previously, this wasn't an applicable concept.) LogActionMixin will take care of this automatically for TournamentMixins and RoundMixins, so long as self.action_log_content_object_attr isn't set.

Hopefully that's not too confusing (it's intuitive to me, but then, I wrote it). Basically, the bottom line is that if the relevant object isn't a tournament or round, you should set action_log_content_object_attr, and optionally set self.round to something useful before self.log_action() is called.

On the broader scale—I think this clears away most of the mess with ActionLogEntry. I think I'd still need to be persuaded of more benefits before investing any time into integrating django-activity-stream, or more precisely, I think we should just do it once we know what we want to implement that demands it, rather than doing it in anticipation of a possible future feature. Thoughts?

@czlee
Copy link
Member Author

czlee commented Sep 11, 2016

Also, migrations here might be risky. There is a data migration so it's meant to be a seamless upgrade, but I've had issues with migrations involving ContentType in the past. I think I've ironed them out with this one, but let me know if you hit anything.

@czlee czlee added this to the Foldex milestone Sep 11, 2016
@czlee czlee self-assigned this Sep 11, 2016
@czlee czlee modified the milestones: Genetta, Foldex Jan 13, 2017
@czlee czlee removed this from the Genetta milestone Feb 20, 2017
@tienne-B
Copy link
Member

Other view would be to remove public submissions, requiring all of them to be performed by a Person. A table linking Person to User (Staff?) could be made for it to be used as an Actor in the activity stream. Then the private URLs would identify the people.

This is quite an old task :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants