Skip to content

Commit 43c5ab6

Browse files
committed
✨(backend) add unresolve action to ThreadViewSet
We have now the possibility to unresolve a thread from the frontend. We need to add the unresolve action to the ThreadViewSet.
1 parent 0bacca3 commit 43c5ab6

5 files changed

Lines changed: 93 additions & 35 deletions

File tree

src/backend/core/api/viewsets.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2972,6 +2972,17 @@ def resolve(self, request, *args, **kwargs):
29722972
thread.save(update_fields=["resolved", "resolved_at", "resolved_by"])
29732973
return drf.response.Response(status=status.HTTP_204_NO_CONTENT)
29742974

2975+
@drf.decorators.action(detail=True, methods=["post"], url_path="unresolve")
2976+
def unresolve(self, request, *args, **kwargs):
2977+
"""Unresolve a thread."""
2978+
thread = self.get_object()
2979+
if thread.resolved:
2980+
thread.resolved = False
2981+
thread.resolved_at = None
2982+
thread.resolved_by = None
2983+
thread.save(update_fields=["resolved", "resolved_at", "resolved_by"])
2984+
return drf.response.Response(status=status.HTTP_204_NO_CONTENT)
2985+
29752986

29762987
class CommentViewSet(
29772988
CommentViewSetMixin,

src/backend/core/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,6 +1851,7 @@ def get_abilities(self, user):
18511851
"update": write_access,
18521852
"partial_update": write_access,
18531853
"resolve": write_access,
1854+
"unresolve": write_access,
18541855
"retrieve": read_access,
18551856
}
18561857

src/backend/core/tests/documents/test_api_documents_threads.py

Lines changed: 80 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,12 +1019,13 @@ def test_api_documents_threads_destroy_restricted_document_privileged_roles(role
10191019
assert not models.Thread.objects.filter(id=thread.id).exists()
10201020

10211021

1022-
# Resolve
1022+
# Resolve / Unresolve
10231023

10241024

1025-
def test_api_documents_threads_resolve_public_document_anonymous_user():
1025+
@pytest.mark.parametrize("action", ["resolve", "unresolve"])
1026+
def test_api_documents_threads_resolve_unresolve_public_document_anonymous_user(action):
10261027
"""
1027-
Anonymous users should not be allowed to resolve threads on public documents.
1028+
Anonymous users should not be allowed to resolve or unresolve threads on public documents.
10281029
"""
10291030
document = factories.DocumentFactory(
10301031
link_reach="public",
@@ -1036,14 +1037,17 @@ def test_api_documents_threads_resolve_public_document_anonymous_user():
10361037

10371038
client = APIClient()
10381039
response = client.post(
1039-
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/resolve/",
1040+
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/{action}/",
10401041
)
10411042
assert response.status_code == 401
10421043

10431044

1044-
def test_api_documents_threads_resolve_public_document_authenticated_user():
1045+
@pytest.mark.parametrize("action", ["resolve", "unresolve"])
1046+
def test_api_documents_threads_resolve_unresolve_public_document_authenticated_user(
1047+
action,
1048+
):
10451049
"""
1046-
Authenticated users should not be allowed to resolve threads on public documents.
1050+
Authenticated users should not be allowed to resolve or unresolve threads on public documents.
10471051
"""
10481052
user = factories.UserFactory()
10491053
document = factories.DocumentFactory(
@@ -1057,14 +1061,18 @@ def test_api_documents_threads_resolve_public_document_authenticated_user():
10571061
client = APIClient()
10581062
client.force_login(user)
10591063
response = client.post(
1060-
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/resolve/",
1064+
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/{action}/",
10611065
)
10621066
assert response.status_code == 403
10631067

10641068

1065-
def test_api_documents_threads_resolve_authenticated_document_anonymous_user():
1069+
@pytest.mark.parametrize("action", ["resolve", "unresolve"])
1070+
def test_api_documents_threads_resolve_unresolve_authenticated_document_anonymous_user(
1071+
action,
1072+
):
10661073
"""
1067-
Anonymous users should not be allowed to resolve threads on authenticated documents.
1074+
Anonymous users should not be allowed to resolve or unresolve threads on authenticated
1075+
documents.
10681076
"""
10691077
document = factories.DocumentFactory(
10701078
link_reach="authenticated",
@@ -1076,14 +1084,17 @@ def test_api_documents_threads_resolve_authenticated_document_anonymous_user():
10761084

10771085
client = APIClient()
10781086
response = client.post(
1079-
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/resolve/",
1087+
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/{action}/",
10801088
)
10811089
assert response.status_code == 401
10821090

10831091

1084-
def test_api_documents_threads_resolve_authenticated_document_reader_role():
1092+
@pytest.mark.parametrize("action", ["resolve", "unresolve"])
1093+
def test_api_documents_threads_resolve_unresolve_authenticated_document_reader_role(
1094+
action,
1095+
):
10851096
"""
1086-
Authenticated users should not be allowed to resolve threads on authenticated
1097+
Authenticated users should not be allowed to resolve or unresolve threads on authenticated
10871098
documents with reader link_role.
10881099
"""
10891100
user = factories.UserFactory()
@@ -1098,18 +1109,21 @@ def test_api_documents_threads_resolve_authenticated_document_reader_role():
10981109
client = APIClient()
10991110
client.force_login(user)
11001111
response = client.post(
1101-
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/resolve/",
1112+
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/{action}/",
11021113
)
11031114
assert response.status_code == 403
11041115

11051116

1117+
@pytest.mark.parametrize("action", ["resolve", "unresolve"])
11061118
@pytest.mark.parametrize(
11071119
"link_role", [models.LinkRoleChoices.COMMENTER, models.LinkRoleChoices.EDITOR]
11081120
)
1109-
def test_api_documents_threads_resolve_authenticated_document(link_role):
1121+
def test_api_documents_threads_resolve_unresolve_authenticated_document(
1122+
link_role, action
1123+
):
11101124
"""
1111-
Authenticated users should not be allowed to resolve threads on authenticated documents with
1112-
commenter or editor link_role.
1125+
Authenticated users should not be allowed to resolve or unresolve threads on authenticated
1126+
documents with commenter or editor link_role.
11131127
"""
11141128
user = factories.UserFactory()
11151129
document = factories.DocumentFactory(
@@ -1123,14 +1137,17 @@ def test_api_documents_threads_resolve_authenticated_document(link_role):
11231137
client = APIClient()
11241138
client.force_login(user)
11251139
response = client.post(
1126-
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/resolve/",
1140+
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/{action}/",
11271141
)
11281142
assert response.status_code == 403
11291143

11301144

1131-
def test_api_documents_threads_resolve_restricted_document_anonymous_user():
1145+
@pytest.mark.parametrize("action", ["resolve", "unresolve"])
1146+
def test_api_documents_threads_resolve_unresolve_restricted_document_anonymous_user(
1147+
action,
1148+
):
11321149
"""
1133-
Anonymous users should not be allowed to resolve threads on restricted documents.
1150+
Anonymous users should not be allowed to resolve or unresolve threads on restricted documents.
11341151
"""
11351152
document = factories.DocumentFactory(
11361153
link_reach="restricted",
@@ -1142,15 +1159,18 @@ def test_api_documents_threads_resolve_restricted_document_anonymous_user():
11421159

11431160
client = APIClient()
11441161
response = client.post(
1145-
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/resolve/",
1162+
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/{action}/",
11461163
)
11471164
assert response.status_code == 401
11481165

11491166

1150-
def test_api_documents_threads_resolve_restricted_document_reader_role():
1167+
@pytest.mark.parametrize("action", ["resolve", "unresolve"])
1168+
def test_api_documents_threads_resolve_unresolve_restricted_document_reader_role(
1169+
action,
1170+
):
11511171
"""
1152-
Authenticated users should not be allowed to resolve threads on restricted documents with
1153-
reader roles.
1172+
Authenticated users should not be allowed to resolve or unresolve threads on restricted
1173+
documents with reader roles.
11541174
"""
11551175
user = factories.UserFactory()
11561176
document = factories.DocumentFactory(
@@ -1165,18 +1185,21 @@ def test_api_documents_threads_resolve_restricted_document_reader_role():
11651185
client = APIClient()
11661186
client.force_login(user)
11671187
response = client.post(
1168-
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/resolve/",
1188+
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/{action}/",
11691189
)
11701190
assert response.status_code == 403
11711191

11721192

1193+
@pytest.mark.parametrize("action", ["resolve", "unresolve"])
11731194
@pytest.mark.parametrize(
11741195
"role", [models.RoleChoices.COMMENTER, models.RoleChoices.EDITOR]
11751196
)
1176-
def test_api_documents_threads_resolve_restricted_document_editor(role):
1197+
def test_api_documents_threads_resolve_unresolve_restricted_document_editor(
1198+
role, action
1199+
):
11771200
"""
1178-
Authenticated users should not be allowed to resolve threads on restricted documents with
1179-
editor roles.
1201+
Authenticated users should not be allowed to resolve or unresolve threads on restricted
1202+
documents with commenter or editor roles.
11801203
"""
11811204
user = factories.UserFactory()
11821205
document = factories.DocumentFactory(
@@ -1191,7 +1214,7 @@ def test_api_documents_threads_resolve_restricted_document_editor(role):
11911214
client = APIClient()
11921215
client.force_login(user)
11931216
response = client.post(
1194-
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/resolve/",
1217+
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/{action}/",
11951218
)
11961219
assert response.status_code == 403
11971220

@@ -1219,8 +1242,36 @@ def test_api_documents_threads_resolve_restricted_document_privileged_roles(role
12191242
)
12201243
assert response.status_code == 204
12211244

1222-
# Verify thread is resolved
12231245
thread.refresh_from_db()
12241246
assert thread.resolved is True
12251247
assert thread.resolved_at is not None
12261248
assert thread.resolved_by == user
1249+
1250+
1251+
@pytest.mark.parametrize("role", [models.RoleChoices.ADMIN, models.RoleChoices.OWNER])
1252+
def test_api_documents_threads_unresolve_restricted_document_privileged_roles(role):
1253+
"""
1254+
Authenticated users with privileged roles should be allowed to unresolve threads on
1255+
restricted documents.
1256+
"""
1257+
user = factories.UserFactory()
1258+
document = factories.DocumentFactory(
1259+
link_reach="restricted",
1260+
link_role=models.LinkRoleChoices.EDITOR,
1261+
users=[(user, role)],
1262+
)
1263+
1264+
thread = factories.ThreadFactory(document=document, creator=None, resolved=True)
1265+
factories.CommentFactory(thread=thread, user=None)
1266+
1267+
client = APIClient()
1268+
client.force_login(user)
1269+
response = client.post(
1270+
f"/api/v1.0/documents/{document.id!s}/threads/{thread.id!s}/unresolve/",
1271+
)
1272+
assert response.status_code == 204
1273+
1274+
thread.refresh_from_db()
1275+
assert thread.resolved is False
1276+
assert thread.resolved_at is None
1277+
assert thread.resolved_by is None

src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/DocsThreadStore.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -534,11 +534,6 @@ export class DocsThreadStore extends ThreadStore {
534534
this.ping(threadId);
535535
};
536536

537-
/**
538-
* Todo: Not implemented backend side
539-
* @returns
540-
* @throws
541-
*/
542537
public unresolveThread = async (_options: { threadId: string }) => {
543538
const response = await fetchAPI(
544539
`documents/${this.docId}/threads/${_options.threadId}/unresolve/`,

src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/DocsThreadStoreAuth.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export class DocsThreadStoreAuth extends ThreadStoreAuth {
5959
* @returns
6060
*/
6161
canUnresolveThread(_thread: ClientThreadData): boolean {
62-
return false;
62+
return true;
6363
}
6464

6565
canAddReaction(comment: ClientCommentData, emoji?: string): boolean {

0 commit comments

Comments
 (0)