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.
[ ] can mark any document as restricted during upload or editing
[ ] can select multiple user groups who should have access to a restricted document
[ ] can view and modify restriction settings for existing documents
[ ] can see which documents are restricted in the admin interface
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.
[ ] cannot see restricted documents in any listing pages
[ ] cannot see restricted documents in search results
[ ] receive a 404 error when attempting to access restricted document URLs
[ ] can see a login prompt when attempting to access restricted content
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.
[ ] can see all public documents
[ ] can see restricted documents for groups I belong to
[ ] can access my groups page showing my group memberships
[ ] can view group-specific document collections
[ ] cannot see or access documents restricted to groups I don't belong to
My Groups Page
Authenticated users will have access to a My groups Page. This page lists all the groups that the user belongs to e.g National Prosecutors. This opens a Group Documents listing page, which lists all documents that members of that group are able to view, grouped by document type.
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.
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?
are restricted documents hidden in lists of incoming citations? (restricted doc X cites public doc Y)
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.
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?
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.
[ ] cannot see or access documents restricted to groups I don't belong to
My Groups Page Authenticated users will have access to a
My groups
Page. This page lists all the groups that the user belongs to e.gNational Prosecutors
. This opens a Group Documents listing page, which lists all documents that members of that group are able to view, grouped by document type.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.
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. Addrestricted
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 viewBaseDocumentDetailView 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 theview_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.