The frontend needs to know what to display on an access. The maximum
role between the access role and the role equivalent to all accesses
on the document's ancestors should be computed on the backend.
The frontend requires this information about the ancestor document
to which each access is related. We make sure it does not generate
more db queries and does not fetch useless and heavy fields from
the document like "excerpt".
If root documents are guaranteed to have a owner, non-root documents
will automatically have them as owner by inheritance. We should not
require non-root documents to have their own direct owner because
this will make it difficult to manage access rights when we move
documents around or when we want to remove access rights for someone
on a document subtree... There should be as few overrides as possible.
This field is set only on the list view when all accesses for a given
document and all its ancestors are listed. It gives the highest role
among all accesses related to each document.
The latest refactoring in a445278 kept some factorizations that are
not legit anymore after the refactoring.
It is also cleaner to not make serializer choice in the list view if
the reason for this choice is related to something else b/c other
views would then use the wrong serializer and that would be a
security leak.
This commit also fixes a bug in the access rights inheritance: if a
user is allowed to see accesses on a document, he should see all
acesses related to ancestors, even the ancestors that he can not
read. This is because the access that was granted on all ancestors
also apply on the current document... so it must be displayed.
Lastly, we optimize database queries because the number of accesses
we fetch is going up with multi-pages and we were generating a lot
of useless queries.
On a document, we need to display the status of the link (reach and
role) taking into account the ancestors link reach/role as well as
the current document.
We were returning the list of roles a user has on a document (direct
and inherited). Now that we introduced priority on roles, we are able
to determine what is the max role and return only this one.
This commit also changes the role that is returned for the restricted
reach: we now return None because the role is not relevant in this
case.
We are going to need to compare choices to materialize the fact that
choices are ordered. For example an admin role is higer than an
editor role but lower than an owner role.
We will need this to compute the reach and role resulting from all
the document accesses (resp. link accesses) assigned on a document's
ancestors.
The document accesses a user have on a document's ancestors also apply
to this document. The frontend needs to list them as "inherited" so we
need to add them to the list.
Adding a "document_id" field on the output will allow the frontend to
differentiate between inherited and direct accesses on a document.
The document viewset was overriding the get_queryset method from its
own mixin. This was a sign that the mixin was not optimal anymore.
In the next commit I will need to complexify it further so it's time
to refactor the mixin.
An already existing feature flag
COLLABORATION_WS_NOT_CONNECTED_READY_ONLY was used bu the frontend
application to disable or not the edition for a user not connected to
the websocket. We want to reuse it in the backend application to disable
or not the no websocket feature.
The endpoint can_edit is added to the DocumentViewset, it will give the
information to the frontend application id the current user can edit the
Docs based on the no-websocket rules.
When a document is updated, users not connected to the collaboration
server can override work made by other people connected to the
collaboration server. To avoid this, the priority is given to user
connected to the collaboration server. If the websocket property in the
request payload is missing or set to False, the backend fetch the
collaboration server to now if the user can save or not. If users are
already connected, the user can't save. Also, only one user without
websocket can save a connect, the first user saving acquire a lock and
all other users can't save.
To implement this behavior, we need to track all users, connected and
not, so a session is created for every user in the
ForceSessionMiddleware.
Renamed the `convert_markdown` method to `convert` to prepare for an
all-purpose conversion endpoint, enabling support for multiple formats
and simplifying future extension.
Signed-off-by: Stephan Meijer <me@stephanmeijer.com>
Add the action accepting a request to access a document. It is possible
to override the role from the request and also update an existing
DocumentAccess
We introduce a new model for user wanted to access a document or upgrade
their role if they already have access.
The viewsets does not implement PUT and PATCH, we don't need it for now.
We want to protect all requests from django with content security
policy header. We use the djang-csp library and configure it with
default values.
Fixes#1000
We added the possibility to scan all uploaded files with an anti malware
solution. Depending the backend used, we want to give the possibility to
check the file mimtype to determine if this one is tagged as unsafe or
not. To this you can set the environment variable
DOCUMENT_ATTACHMENT_CHECK_UNSAFE_MIME_TYPES_ENABLED to False. The
default value is True.
If users were not connected to the collaboration
server, they were not be able to edit documents.
We decided to add a feature flag on this feature
as it can be quite restrictive.
We can now enable or disable this feature at runtime
thanks to the env variable
"COLLABORATION_WS_NOT_CONNECTED_READY_ONLY".
We want to have the media-check url returned on the attachment-upload
response instead of the media url directly. The front will know the
endpoint to use to check the media status.
With the usage of a malware detection system, we need a way to know the
file status. The front will use it to display a loader while the analyse
is not ended.
We want to customize the theme by using a configuration file. This
configuration file path can be defined using the settings
THEME_CUSTOMIZATION_FILE_PATH. If this file does not exists or is an
invalid json, an empty json object will be added in the config endpoint.
In the attachment_upload method, the status in the file metadata to
processing and the malware_detection backend is called. We check in the
media_auth if the status is ready in order to accept the request.
When 2 docs are created almost at the same time,
the second one will fail because the first one.
We get a unicity error on the path key already
used ("impress_document_path_key").
To fix this issue, we will lock the table the
time to create the document, the next query will
wait for the lock to be released.
This should work in both cases:
- search for "vélo" when the document title contains "velo"
- search for "velo" when the document title contains "vélo"
We added the `FRONTEND_URL_JSON_FOOTER` environment
variable. It will give the possibility to generate
your own footer content in the frontend.
If the variable is not set, the footer will not
be displayed.
Added a feature flag check to ensure the AIGroupButton is only rendered
when AI_FEATURE_ENABLED is explicitly set to "true". This prevents the
AI button from appearing when the feature is not configured or disabled.
Fixes#782
Signed-off-by: Matthias <matthias@universum.com>
We recently extract images url in the content. For this, we assume that
the document content is always in base64. We enforce this assumption by
checking if it's a valide base64 in the serializer.
Every user having an access to a document, no matter its role have
access to the entire accesses list with all the user details. Only
owner or admin should be able to have the entire list, for the other
roles, they have access to the list containing only owner and
administrator with less information on the username. The email and its
id is removed
The refactor made in the tree view caching the ancestors_links to not
compute them again in the document.get_abilities method lead to a bug.
If the get_abilities method is called without ancestors_links, then they
are computed on all the ancestors but not from the highest readable
ancestor for the current user. We have to compute them with this
constraint.
We can't prevent document editors from copy/pasting content to from one
document to another. The problem is that copying content, will copy the
urls pointing to attachments but if we don't do anything, the reader of
the document to which the content is being pasted, may not be allowed to
access the attachment files from the original document.
Using the work from the previous commit, we can grant access to the readers
of the target document by extracting the attachment keys from the content and
adding themto the target document's "attachments" field. Before doing this,
we check that the current user can indeed access the attachment files extracted
from the content and that they are allowed to edit the current document.
We took this opportunity to refactor the way access is controlled on
media attachments. We now add the media key to a list on the document
instance each time a media is uploaded to a document. This list is
passed along when a document is duplicated, allowing us to grant
access to readers on the new document, even if they don't have or
lost access to the original document.
We also propose an option to reproduce the same access rights on the
duplicate document as what was in place on the original document.
This can be requested by passing the "with_accesses=true" option in
the query string.
The tricky point is that we need to extract attachment keys from the
existing documents and set them on the new "attachments" field that is
now used to track access rights on media files.
These 2 actions had factorized code but a few iterations lead to
spaghetti code where factorized code includes "if" clauses.
Refactor abstractions so that code factorization really works.
Some providers with S3-compatible APIs have slightly different
implementations. In this case, Scaleway didn't accept version_id=""
and has a different version ID scheme. This was tested successfully
and should remain compatible with any other provider.
The user list endpoint is throttle to avoid users discovery. The
throttle is set to 500 requests per day. This can be changed using the
settings API_USERS_LIST_THROTTLE_RATE.
The user list endpoint does not use anymore a pagination, the results is
directly return in a list and the max results returned is limited to 5.
In order to modify this limit the settings API_USERS_LIST_LIMIT is
used.