laws-africa / peachjam

Project Peach Jam
https://agp.africanlii.org
GNU General Public License v3.0
2 stars 0 forks source link

Restricted collections #2112

Open actlikewill opened 1 week ago

actlikewill commented 1 week ago

Certain sets of users, e.g certain groups of the Tanzanian Law Society like National Prosecutors Service, want to host collections of documents that should not be viewable by the general public. Here is an example of their listing page on Tanzlii https://tanzlii.org/authors/TZNPS/

To do this we need to be able to restrict access to certain documents to certain sets of users. This restricted access control should encompass admin access, frontend listing pages and detail pages. We can leverage Django's in built group based permission system as much as possible to build out this feature.

All supported documents need this restrictions to be applied i.e judgments, legislation, gazettes, etc

Proposal

Workflow and UX

Editors While an editor is uploading a document, they have access to a checkbox that marks a document as restricted. They are then able to select from a list of user groups to set which ones are able to view the document.

Anonymous Site visitors A restricted document does not show up on any listing pages for anonymous users, including in search results. Visiting the detail page should return a 404 (not found) response.

Logged in Users If a logged in user belongs to an authorized group, they are able to see the document in the regular listing pages and view the document detail page as normal. If they are not authorized the experience is the same as that of an anonymous user.

Robots Restricted documents shouuld not be indexable by default.

Technical Implementation

Django Guardian Django Guardian library provides object level permissions that can be used for this solution. Install and configure the library, to setup support object permission.

Model changes and permissions Add a new 'restricted` boolean field and permission to the CoreDocument models.

class CoreDocument:
   restricted = models.BooleanField(default=False, db_index=True)

   class Meta:
        permissions = (
            ('view_restricted_document', 'Can view restricted document'),
        )

The restricted field can be used to filter out restricted documents in listing pages for all anonymous users. The field is indexed to speed up lookups. The view_restricted_document permission is what will be assigned to groups that can view the document.

Admin Django Guardian provides admin configuration that will add views for setting permissions for the each document. We can add class GuardedModelAdmin the base document admin. Add restricted to the list filters and list display.

FilteredDocumentListing Views This is the base listing view that is used on most documet types. DJango guardian provides a get_objects_for_user method that accepts a list of permissions and returns the objects that the user is allowed to view. Objects returned by this method can be added to the default queryset to show all documents that the current user is allowed to view

BaseDocumentDetailView In the document detail view, we check if the document is restricted and then check if the user is allowed access to that document using the has_perm method and passing in the view_restricted_document permission and the document instance. If the user fails the check, we can return a 404 response if the user doesn't have permissions. We could also redirect to a login page, or show a 403 response page.

Search We need to restrict the documents shown in search results. Add the restricted field to the Elasticsearch index and filter use this to filter out all restricted documents from search results.

Robots.txt When a document is marked as restricted, it needs to be added to the robots.txt disallow list. When an object is marked as restricted, also check the disallow robots field by default.

My Groups Page and Restricted Documents Page

Create a new My Groups page. Here users should be able to see what groups they belong to. Add a link to this page on the header dropdown. For each group, there should be a restricted documents page which only lists the restricted documents that the group is allowed access to. This is a standard listing page with filters against different document types.

Allowed groups Not all groups should allowed to be public, eg. editor groups. We can make this confgurable via an admin setting. This will allow us to select which groups can be shown on the my groups page.

longhotsummer commented 2 hours ago

Great start. Some thoughts:

  1. how do we manage document permissions in bulk? If there are 50 documents that need to be restricted to a certain group, how do I do that without having to do each one individually?
  2. are restricted documents hidden in lists of incoming citations? (restricted doc X cites public doc Y)
  3. another option is to show documents in listing views and search results, but then show a permission denied on the document detail page. This way we're not trying to hide the existence of a document, but the detail. This would be significantly easier to implement.
  4. does the user's "my groups" page show all permission groups? Even internal ones? Or do we need the concept of a "subscription group" which allows us to separate out internal permission groups from content-oriented ones?