diff --git a/CHANGELOG.md b/CHANGELOG.md
index 312f1307..af1e3e30 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ and this project adheres to
- 🌐(frontend) add localization to editor #268
- ✨Public and restricted doc editable #357
- ✨(frontend) Add full name if available #380
+- ✨(backend) Add view accesses ability #376
## Fixed
diff --git a/src/backend/core/models.py b/src/backend/core/models.py
index 6be54d64..9e5f02a7 100644
--- a/src/backend/core/models.py
+++ b/src/backend/core/models.py
@@ -496,7 +496,8 @@ class Document(BaseModel):
# Compute version roles before adding link roles because we don't
# want anonymous users to access versions (we wouldn't know from
# which date to allow them anyway)
- can_get_versions = bool(roles)
+ # Anonymous users should also not see document accesses
+ has_role = bool(roles)
# Add role provided by the document link
if self.link_reach == LinkReachChoices.PUBLIC or (
@@ -511,19 +512,20 @@ class Document(BaseModel):
can_get = bool(roles)
return {
+ "accesses_manage": is_owner_or_admin,
+ "accesses_view": has_role,
"ai_transform": is_owner_or_admin or is_editor,
"ai_translate": is_owner_or_admin or is_editor,
"attachment_upload": is_owner_or_admin or is_editor,
"destroy": RoleChoices.OWNER in roles,
"link_configuration": is_owner_or_admin,
- "manage_accesses": is_owner_or_admin,
"invite_owner": RoleChoices.OWNER in roles,
"partial_update": is_owner_or_admin or is_editor,
"retrieve": can_get,
"update": is_owner_or_admin or is_editor,
"versions_destroy": is_owner_or_admin,
- "versions_list": can_get_versions,
- "versions_retrieve": can_get_versions,
+ "versions_list": has_role,
+ "versions_retrieve": has_role,
}
def email_invitation(self, language, email, role, sender):
@@ -679,7 +681,7 @@ class Template(BaseModel):
return {
"destroy": RoleChoices.OWNER in roles,
"generate_document": can_get,
- "manage_accesses": is_owner_or_admin,
+ "accesses_manage": is_owner_or_admin,
"update": is_owner_or_admin or is_editor,
"partial_update": is_owner_or_admin or is_editor,
"retrieve": can_get,
diff --git a/src/backend/core/tests/documents/test_api_documents_retrieve.py b/src/backend/core/tests/documents/test_api_documents_retrieve.py
index 220b5213..c7a76032 100644
--- a/src/backend/core/tests/documents/test_api_documents_retrieve.py
+++ b/src/backend/core/tests/documents/test_api_documents_retrieve.py
@@ -21,13 +21,14 @@ def test_api_documents_retrieve_anonymous_public():
assert response.json() == {
"id": str(document.id),
"abilities": {
+ "accesses_manage": False,
+ "accesses_view": False,
"ai_transform": document.link_role == "editor",
"ai_translate": document.link_role == "editor",
"attachment_upload": document.link_role == "editor",
"destroy": False,
"invite_owner": False,
"link_configuration": False,
- "manage_accesses": False,
"partial_update": document.link_role == "editor",
"retrieve": True,
"update": document.link_role == "editor",
@@ -78,13 +79,14 @@ def test_api_documents_retrieve_authenticated_unrelated_public_or_authenticated(
assert response.json() == {
"id": str(document.id),
"abilities": {
+ "accesses_manage": False,
+ "accesses_view": False,
"ai_transform": document.link_role == "editor",
"ai_translate": document.link_role == "editor",
"attachment_upload": document.link_role == "editor",
"link_configuration": False,
"destroy": False,
"invite_owner": False,
- "manage_accesses": False,
"partial_update": document.link_role == "editor",
"retrieve": True,
"update": document.link_role == "editor",
diff --git a/src/backend/core/tests/templates/test_api_templates_retrieve.py b/src/backend/core/tests/templates/test_api_templates_retrieve.py
index 7af1fbaf..e3466ab2 100644
--- a/src/backend/core/tests/templates/test_api_templates_retrieve.py
+++ b/src/backend/core/tests/templates/test_api_templates_retrieve.py
@@ -22,7 +22,7 @@ def test_api_templates_retrieve_anonymous_public():
"abilities": {
"destroy": False,
"generate_document": True,
- "manage_accesses": False,
+ "accesses_manage": False,
"partial_update": False,
"retrieve": True,
"update": False,
@@ -68,7 +68,7 @@ def test_api_templates_retrieve_authenticated_unrelated_public():
"abilities": {
"destroy": False,
"generate_document": True,
- "manage_accesses": False,
+ "accesses_manage": False,
"partial_update": False,
"retrieve": True,
"update": False,
diff --git a/src/backend/core/tests/test_models_documents.py b/src/backend/core/tests/test_models_documents.py
index d034f011..0859db69 100644
--- a/src/backend/core/tests/test_models_documents.py
+++ b/src/backend/core/tests/test_models_documents.py
@@ -83,13 +83,14 @@ def test_models_documents_get_abilities_forbidden(is_authenticated, reach, role)
user = factories.UserFactory() if is_authenticated else AnonymousUser()
abilities = document.get_abilities(user)
assert abilities == {
+ "accesses_manage": False,
+ "accesses_view": False,
"ai_transform": False,
"ai_translate": False,
"attachment_upload": False,
"link_configuration": False,
"destroy": False,
"invite_owner": False,
- "manage_accesses": False,
"partial_update": False,
"retrieve": False,
"update": False,
@@ -116,13 +117,14 @@ def test_models_documents_get_abilities_reader(is_authenticated, reach):
user = factories.UserFactory() if is_authenticated else AnonymousUser()
abilities = document.get_abilities(user)
assert abilities == {
+ "accesses_manage": False,
+ "accesses_view": False,
"ai_transform": False,
"ai_translate": False,
"attachment_upload": False,
"destroy": False,
"link_configuration": False,
"invite_owner": False,
- "manage_accesses": False,
"partial_update": False,
"retrieve": True,
"update": False,
@@ -149,13 +151,14 @@ def test_models_documents_get_abilities_editor(is_authenticated, reach):
user = factories.UserFactory() if is_authenticated else AnonymousUser()
abilities = document.get_abilities(user)
assert abilities == {
+ "accesses_manage": False,
+ "accesses_view": False,
"ai_transform": True,
"ai_translate": True,
"attachment_upload": True,
"destroy": False,
"link_configuration": False,
"invite_owner": False,
- "manage_accesses": False,
"partial_update": True,
"retrieve": True,
"update": True,
@@ -171,13 +174,14 @@ def test_models_documents_get_abilities_owner():
access = factories.UserDocumentAccessFactory(role="owner", user=user)
abilities = access.document.get_abilities(access.user)
assert abilities == {
+ "accesses_manage": True,
+ "accesses_view": True,
"ai_transform": True,
"ai_translate": True,
"attachment_upload": True,
"destroy": True,
"link_configuration": True,
"invite_owner": True,
- "manage_accesses": True,
"partial_update": True,
"retrieve": True,
"update": True,
@@ -192,13 +196,14 @@ def test_models_documents_get_abilities_administrator():
access = factories.UserDocumentAccessFactory(role="administrator")
abilities = access.document.get_abilities(access.user)
assert abilities == {
+ "accesses_manage": True,
+ "accesses_view": True,
"ai_transform": True,
"ai_translate": True,
"attachment_upload": True,
"destroy": False,
"link_configuration": True,
"invite_owner": False,
- "manage_accesses": True,
"partial_update": True,
"retrieve": True,
"update": True,
@@ -216,13 +221,14 @@ def test_models_documents_get_abilities_editor_user(django_assert_num_queries):
abilities = access.document.get_abilities(access.user)
assert abilities == {
+ "accesses_manage": False,
+ "accesses_view": True,
"ai_transform": True,
"ai_translate": True,
"attachment_upload": True,
"destroy": False,
"link_configuration": False,
"invite_owner": False,
- "manage_accesses": False,
"partial_update": True,
"retrieve": True,
"update": True,
@@ -242,13 +248,14 @@ def test_models_documents_get_abilities_reader_user(django_assert_num_queries):
abilities = access.document.get_abilities(access.user)
assert abilities == {
+ "accesses_manage": False,
+ "accesses_view": True,
"ai_transform": False,
"ai_translate": False,
"attachment_upload": False,
"destroy": False,
"link_configuration": False,
"invite_owner": False,
- "manage_accesses": False,
"partial_update": False,
"retrieve": True,
"update": False,
@@ -269,13 +276,14 @@ def test_models_documents_get_abilities_preset_role(django_assert_num_queries):
abilities = access.document.get_abilities(access.user)
assert abilities == {
+ "accesses_manage": False,
+ "accesses_view": True,
"ai_transform": False,
"ai_translate": False,
"attachment_upload": False,
"destroy": False,
"link_configuration": False,
"invite_owner": False,
- "manage_accesses": False,
"partial_update": False,
"retrieve": True,
"update": False,
diff --git a/src/backend/core/tests/test_models_templates.py b/src/backend/core/tests/test_models_templates.py
index d38fcea9..6e7cba2c 100644
--- a/src/backend/core/tests/test_models_templates.py
+++ b/src/backend/core/tests/test_models_templates.py
@@ -62,7 +62,7 @@ def test_models_templates_get_abilities_anonymous_public():
"destroy": False,
"retrieve": True,
"update": False,
- "manage_accesses": False,
+ "accesses_manage": False,
"partial_update": False,
"generate_document": True,
}
@@ -76,7 +76,7 @@ def test_models_templates_get_abilities_anonymous_not_public():
"destroy": False,
"retrieve": False,
"update": False,
- "manage_accesses": False,
+ "accesses_manage": False,
"partial_update": False,
"generate_document": False,
}
@@ -90,7 +90,7 @@ def test_models_templates_get_abilities_authenticated_public():
"destroy": False,
"retrieve": True,
"update": False,
- "manage_accesses": False,
+ "accesses_manage": False,
"partial_update": False,
"generate_document": True,
}
@@ -104,7 +104,7 @@ def test_models_templates_get_abilities_authenticated_not_public():
"destroy": False,
"retrieve": False,
"update": False,
- "manage_accesses": False,
+ "accesses_manage": False,
"partial_update": False,
"generate_document": False,
}
@@ -119,7 +119,7 @@ def test_models_templates_get_abilities_owner():
"destroy": True,
"retrieve": True,
"update": True,
- "manage_accesses": True,
+ "accesses_manage": True,
"partial_update": True,
"generate_document": True,
}
@@ -133,7 +133,7 @@ def test_models_templates_get_abilities_administrator():
"destroy": False,
"retrieve": True,
"update": True,
- "manage_accesses": True,
+ "accesses_manage": True,
"partial_update": True,
"generate_document": True,
}
@@ -150,7 +150,7 @@ def test_models_templates_get_abilities_editor_user(django_assert_num_queries):
"destroy": False,
"retrieve": True,
"update": True,
- "manage_accesses": False,
+ "accesses_manage": False,
"partial_update": True,
"generate_document": True,
}
@@ -167,7 +167,7 @@ def test_models_templates_get_abilities_reader_user(django_assert_num_queries):
"destroy": False,
"retrieve": True,
"update": False,
- "manage_accesses": False,
+ "accesses_manage": False,
"partial_update": False,
"generate_document": True,
}
@@ -185,7 +185,7 @@ def test_models_templates_get_abilities_preset_role(django_assert_num_queries):
"destroy": False,
"retrieve": True,
"update": False,
- "manage_accesses": False,
+ "accesses_manage": False,
"partial_update": False,
"generate_document": True,
}
diff --git a/src/frontend/apps/e2e/__tests__/app-impress/common.ts b/src/frontend/apps/e2e/__tests__/app-impress/common.ts
index 2c52eeee..900d3265 100644
--- a/src/frontend/apps/e2e/__tests__/app-impress/common.ts
+++ b/src/frontend/apps/e2e/__tests__/app-impress/common.ts
@@ -144,7 +144,7 @@ export const mockedDocument = async (page: Page, json: object) => {
versions_destroy: false,
versions_list: true,
versions_retrieve: true,
- manage_accesses: false, // Means not admin
+ accesses_manage: false, // Means not admin
update: false,
partial_update: false, // Means not editor
retrieve: true,
diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts
index bd5c7f62..d41660a5 100644
--- a/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts
+++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts
@@ -215,7 +215,7 @@ test.describe('Doc Editor', () => {
versions_destroy: false,
versions_list: true,
versions_retrieve: true,
- manage_accesses: false, // Means not admin
+ accesses_manage: false, // Means not admin
update: false,
partial_update: false, // Means not editor
retrieve: true,
diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-grid.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-grid.spec.ts
index 6807647e..54febf83 100644
--- a/src/frontend/apps/e2e/__tests__/app-impress/doc-grid.spec.ts
+++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-grid.spec.ts
@@ -303,7 +303,7 @@ test.describe('Documents Grid mobile', () => {
attachment_upload: true,
destroy: true,
link_configuration: true,
- manage_accesses: true,
+ accesses_manage: true,
partial_update: true,
retrieve: true,
update: true,
diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts
index 5bb9aa6d..cd5e2efa 100644
--- a/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts
+++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts
@@ -45,7 +45,7 @@ test.describe('Doc Header', () => {
versions_destroy: true,
versions_list: true,
versions_retrieve: true,
- manage_accesses: true,
+ accesses_manage: true,
update: true,
partial_update: true,
retrieve: true,
@@ -182,7 +182,7 @@ test.describe('Doc Header', () => {
versions_destroy: true,
versions_list: true,
versions_retrieve: true,
- manage_accesses: true, // Means admin
+ accesses_manage: true, // Means admin
update: true,
partial_update: true,
retrieve: true,
@@ -252,7 +252,7 @@ test.describe('Doc Header', () => {
versions_destroy: true,
versions_list: true,
versions_retrieve: true,
- manage_accesses: false, // Means not admin
+ accesses_manage: false, // Means not admin
update: true,
partial_update: true, // Means editor
retrieve: true,
@@ -329,7 +329,7 @@ test.describe('Doc Header', () => {
versions_destroy: false,
versions_list: true,
versions_retrieve: true,
- manage_accesses: false, // Means not admin
+ accesses_manage: false, // Means not admin
update: false,
partial_update: false, // Means not editor
retrieve: true,
@@ -489,7 +489,7 @@ test.describe('Documents Header mobile', () => {
versions_destroy: true,
versions_list: true,
versions_retrieve: true,
- manage_accesses: true,
+ accesses_manage: true,
update: true,
partial_update: true,
retrieve: true,
diff --git a/src/frontend/apps/impress/src/features/docs/doc-header/types.ts b/src/frontend/apps/impress/src/features/docs/doc-header/types.ts
index 8a81c870..70b62e56 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-header/types.ts
+++ b/src/frontend/apps/impress/src/features/docs/doc-header/types.ts
@@ -5,7 +5,7 @@ export interface Template {
abilities: {
destroy: boolean;
generate_document: boolean;
- manage_accesses: boolean;
+ accesses_manage: boolean;
retrieve: boolean;
update: boolean;
partial_update: boolean;
diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalShare.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalShare.tsx
index 3c8807bc..7361ec54 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalShare.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalShare.tsx
@@ -115,7 +115,7 @@ export const ModalShare = ({ onClose, doc }: ModalShareProps) => {
- {doc.abilities.manage_accesses && (
+ {doc.abilities.accesses_manage && (
{
return abilities.destroy
? Role.OWNER
- : abilities.manage_accesses
+ : abilities.accesses_manage
? Role.ADMIN
: abilities.partial_update
? Role.EDITOR
diff --git a/src/frontend/apps/impress/src/features/docs/members/invitation-list/components/InvitationItem.tsx b/src/frontend/apps/impress/src/features/docs/members/invitation-list/components/InvitationItem.tsx
index e92358c8..9de0e8db 100644
--- a/src/frontend/apps/impress/src/features/docs/members/invitation-list/components/InvitationItem.tsx
+++ b/src/frontend/apps/impress/src/features/docs/members/invitation-list/components/InvitationItem.tsx
@@ -112,7 +112,7 @@ export const InvitationItem = ({
}}
/>
- {doc.abilities.manage_accesses && (
+ {doc.abilities.accesses_manage && (
@@ -189,7 +189,7 @@ export const AddMembers = ({ currentRole, doc }: ModalAddMembersProps) => {
!selectedUsers.length ||
isPending ||
!selectedRole ||
- !doc.abilities.manage_accesses
+ !doc.abilities.accesses_manage
}
onClick={() => void handleValidate()}
style={{ height: '100%', maxHeight: '55px' }}
diff --git a/src/frontend/apps/impress/src/features/docs/members/members-list/components/MemberItem.tsx b/src/frontend/apps/impress/src/features/docs/members/members-list/components/MemberItem.tsx
index 1c24a0d4..34fc476d 100644
--- a/src/frontend/apps/impress/src/features/docs/members/members-list/components/MemberItem.tsx
+++ b/src/frontend/apps/impress/src/features/docs/members/members-list/components/MemberItem.tsx
@@ -61,7 +61,7 @@ export const MemberItem = ({
});
const isNotAllowed =
- isOtherOwner || isLastOwner || !doc.abilities.manage_accesses;
+ isOtherOwner || isLastOwner || !doc.abilities.accesses_manage;
if (!access.user) {
return (
@@ -112,7 +112,7 @@ export const MemberItem = ({
}}
/>
- {doc.abilities.manage_accesses && (
+ {doc.abilities.accesses_manage && (
)}
- {(isLastOwner || isOtherOwner) && doc.abilities.manage_accesses && (
+ {(isLastOwner || isOtherOwner) && doc.abilities.accesses_manage && (