Skip to content

Commit 13c37a3

Browse files
committed
move to PUT endpoint to set feedback status
Signed-off-by: Jordan Dubrick <[email protected]>
1 parent e2e9dd8 commit 13c37a3

File tree

5 files changed

+131
-85
lines changed

5 files changed

+131
-85
lines changed

docs/openapi.json

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -386,21 +386,19 @@
386386
}
387387
}
388388
}
389-
}
390-
},
391-
"/v1/feedback/toggle": {
392-
"post": {
389+
},
390+
"put": {
393391
"tags": [
394392
"feedback"
395393
],
396-
"summary": "Feedback Toggle",
397-
"description": "Handle feedback toggle requests.\n\nReturns the current enbaled status of the feedback functionality after it has been\nupdated to the desired value from the request.\n\nReturns:\n StatusResponse: Indicates whether feedback is enabled.",
398-
"operationId": "feedback_toggle_v1_feedback_toggle_post",
394+
"summary": "Update Feedback Status",
395+
"description": "Handle feedback status update requests.\n\nTakes a request with the desired state of the feedback status.\nReturns the updated state of the feedback status based on the request's value.\n\nReturns:\n StatusResponse: Indicates whether feedback is enabled.",
396+
"operationId": "update_feedback_status_v1_feedback_status_put",
399397
"requestBody": {
400398
"content": {
401399
"application/json": {
402400
"schema": {
403-
"$ref": "#/components/schemas/FeedbackToggleRequest"
401+
"$ref": "#/components/schemas/FeedbackStatusUpdateRequest"
404402
}
405403
}
406404
},
@@ -412,7 +410,7 @@
412410
"content": {
413411
"application/json": {
414412
"schema": {
415-
"$ref": "#/components/schemas/StatusResponse"
413+
"$ref": "#/components/schemas/FeedbackStatusUpdateResponse"
416414
}
417415
}
418416
}
@@ -1488,7 +1486,7 @@
14881486
}
14891487
]
14901488
},
1491-
"FeedbackToggleRequest": {
1489+
"FeedbackStatusUpdateRequest": {
14921490
"properties": {
14931491
"status": {
14941492
"type": "boolean",
@@ -1502,8 +1500,32 @@
15021500
}
15031501
},
15041502
"type": "object",
1505-
"title": "FeedbackToggleRequest",
1506-
"description": "Model representing a feedback toggle request.\n\nAttributes:\n status: Boolean controlling what the Feedback status should be.\n\nExample:\n ```python\n feedback_request = FeedbackRequest(\n status=false\n )\n ```"
1503+
"title": "FeedbackStatusUpdateRequest",
1504+
"description": "Model representing a feedback status update request.\n\nAttributes:\n status: Value of the desired feedback enabled state.\n\nExample:\n ```python\n feedback_request = FeedbackRequest(\n status=false\n )\n ```"
1505+
},
1506+
"FeedbackStatusUpdateResponse": {
1507+
"properties": {
1508+
"status": {
1509+
"additionalProperties": true,
1510+
"type": "object",
1511+
"title": "Status"
1512+
}
1513+
},
1514+
"type": "object",
1515+
"required": [
1516+
"status"
1517+
],
1518+
"title": "FeedbackStatusUpdateResponse",
1519+
"description": "Model representing a response to a feedback status update request.\n\nAttributes:\n status: The previous and current status of the service and who updated it.\n\nExample:\n ```python\n status_response = StatusResponse(\n status={\n \"previous_status\": true,\n \"updated_status\": false,\n \"updated_by\": \"user/test\"\n },\n )\n ```",
1520+
"examples": [
1521+
{
1522+
"status": {
1523+
"previous_status": true,
1524+
"updated_by": "user/test",
1525+
"updated_status": false
1526+
}
1527+
}
1528+
]
15071529
},
15081530
"ForbiddenResponse": {
15091531
"properties": {

src/app/endpoints/feedback.py

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Handler for REST API endpoint for user feedback."""
22

33
import logging
4+
import threading
45
from typing import Annotated, Any
56
from pathlib import Path
67
import json
@@ -12,20 +13,21 @@
1213
from authorization.middleware import authorize
1314
from configuration import configuration
1415
from models.config import Action
15-
from models.requests import FeedbackRequest
16+
from models.requests import FeedbackRequest, FeedbackStatusUpdateRequest
1617
from models.responses import (
1718
ErrorResponse,
1819
FeedbackResponse,
20+
FeedbackStatusUpdateResponse,
1921
StatusResponse,
2022
UnauthorizedResponse,
2123
ForbiddenResponse,
2224
)
23-
from models.requests import FeedbackToggleRequest
2425
from utils.suid import get_suid
2526

2627
logger = logging.getLogger(__name__)
2728
router = APIRouter(prefix="/feedback", tags=["feedback"])
2829
auth_dependency = get_auth_dependency()
30+
feedback_status_lock = threading.Lock()
2931

3032
# Response for the feedback endpoint
3133
feedback_response: dict[int | str, dict[str, Any]] = {
@@ -177,33 +179,39 @@ def feedback_status() -> StatusResponse:
177179
)
178180

179181

180-
@router.post("/toggle")
181-
def feedback_toggle(feedback_toggle_request: FeedbackToggleRequest) -> StatusResponse:
182+
@router.put("/status")
183+
@authorize(Action.ADMIN)
184+
async def update_feedback_status(
185+
feedback_update_request: FeedbackStatusUpdateRequest,
186+
auth: Annotated[AuthTuple, Depends(auth_dependency)],
187+
) -> FeedbackStatusUpdateResponse:
182188
"""
183-
Handle feedback toggle requests.
189+
Handle feedback status update requests.
184190
185-
Returns the current enbaled status of the feedback functionality after it has been
186-
updated to the desired value from the request.
191+
Takes a request with the desired state of the feedback status.
192+
Returns the updated state of the feedback status based on the request's value.
187193
188194
Returns:
189195
StatusResponse: Indicates whether feedback is enabled.
190196
"""
191-
fetched_status = toggle_feedback_status(feedback_toggle_request)
192-
return StatusResponse(functionality="feedback", status={"enabled": fetched_status})
193-
194-
195-
def toggle_feedback_status(req: FeedbackToggleRequest) -> bool:
196-
"""
197-
Toggles the feedback boolean stored in the configuration.
198-
199-
This toggling is temporary until the service is interrupted as it will not edit
200-
any configuration files.
197+
user_id, _, _ = auth
198+
requested_status = feedback_update_request.get_value()
201199

202-
Parameters:
203-
req (FeedbackToggleRequest): The request received with a boolean for the new value.
200+
with feedback_status_lock:
201+
previous_status = (
202+
configuration.user_data_collection_configuration.feedback_enabled
203+
)
204+
configuration.user_data_collection_configuration.feedback_enabled = (
205+
requested_status
206+
)
207+
updated_status = (
208+
configuration.user_data_collection_configuration.feedback_enabled
209+
)
204210

205-
Returns:
206-
bool: The current enabled status of feedback.
207-
"""
208-
configuration.user_data_collection_configuration.feedback_enabled = req.get_value()
209-
return is_feedback_enabled()
211+
return FeedbackStatusUpdateResponse(
212+
status={
213+
"previous_status": previous_status,
214+
"updated_status": updated_status,
215+
"updated_by": user_id,
216+
}
217+
)

src/models/requests.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,11 +382,11 @@ def check_feedback_provided(self) -> Self:
382382
return self
383383

384384

385-
class FeedbackToggleRequest(BaseModel):
386-
"""Model representing a feedback toggle request.
385+
class FeedbackStatusUpdateRequest(BaseModel):
386+
"""Model representing a feedback status update request.
387387
388388
Attributes:
389-
status: Boolean controlling what the Feedback status should be.
389+
status: Value of the desired feedback enabled state.
390390
391391
Example:
392392
```python

src/models/responses.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,3 +570,39 @@ class ErrorResponse(BaseModel):
570570
]
571571
}
572572
}
573+
574+
575+
class FeedbackStatusUpdateResponse(BaseModel):
576+
"""Model representing a response to a feedback status update request.
577+
578+
Attributes:
579+
status: The previous and current status of the service and who updated it.
580+
581+
Example:
582+
```python
583+
status_response = StatusResponse(
584+
status={
585+
"previous_status": true,
586+
"updated_status": false,
587+
"updated_by": "user/test"
588+
},
589+
)
590+
```
591+
"""
592+
593+
status: dict
594+
595+
# provides examples for /docs endpoint
596+
model_config = {
597+
"json_schema_extra": {
598+
"examples": [
599+
{
600+
"status": {
601+
"previous_status": True,
602+
"updated_status": False,
603+
"updated_by": "user/test",
604+
},
605+
}
606+
]
607+
}
608+
}

tests/unit/app/endpoints/test_feedback.py

Lines changed: 26 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99
assert_feedback_enabled,
1010
feedback_endpoint_handler,
1111
store_feedback,
12-
feedback_status,
13-
feedback_toggle,
12+
update_feedback_status,
1413
)
15-
from models.requests import FeedbackToggleRequest
14+
from models.requests import FeedbackStatusUpdateRequest
1615
from tests.unit.utils.auth_helpers import mock_authorization_resolvers
1716

1817

@@ -198,52 +197,33 @@ def test_store_feedback_on_io_error(mocker, feedback_request_data):
198197
store_feedback(user_id, feedback_request_data)
199198

200199

201-
def test_feedback_status():
202-
"""Test that feedback_status returns the correct status response."""
200+
async def test_update_feedback_status_different():
201+
"""Test that update_feedback_status returns the correct status with an update."""
203202
configuration.user_data_collection_configuration.feedback_enabled = True
204203

205-
response = feedback_status()
206-
assert response.functionality == "feedback"
207-
assert response.status == {"enabled": True}
208-
209-
210-
def test_feedback_toggle_enabled():
211-
"""Test that feedback_toggle processes feedback toggle for disabled status payloads."""
212-
213-
configuration.user_data_collection_configuration.feedback_enabled = True
214-
215-
feedback_toggle_request = FeedbackToggleRequest(status=False)
216-
217-
response = feedback_toggle(feedback_toggle_request=feedback_toggle_request)
218-
219-
assert response.functionality == "feedback"
220-
assert response.status == {"enabled": False}
221-
222-
223-
def test_feedback_toggle_disabled():
224-
"""Test that feedback_toggle processes feedback toggle for enabled status payloads."""
225-
226-
configuration.user_data_collection_configuration.feedback_enabled = False
227-
228-
feedback_toggle_request = FeedbackToggleRequest(status=True)
229-
230-
response = feedback_toggle(feedback_toggle_request=feedback_toggle_request)
231-
232-
assert response.functionality == "feedback"
233-
assert response.status == {"enabled": True}
234-
204+
req = FeedbackStatusUpdateRequest(status=False)
205+
resp = await update_feedback_status(
206+
req,
207+
auth=("test_user_id", "test_username", "test_token"),
208+
)
209+
assert resp.status == {
210+
"previous_status": True,
211+
"updated_status": False,
212+
"updated_by": "test_user_id",
213+
}
235214

236-
def test_feedback_toggle_equivalent():
237-
"""
238-
Test that feedback_toggle processes feedback toggle for status payloads with the same value
239-
as what is presently set.
240-
"""
241215

216+
async def test_update_feedback_status_no_change():
217+
"""Test that update_feedback_status returns the correct status with no update."""
242218
configuration.user_data_collection_configuration.feedback_enabled = True
243219

244-
feedback_toggle_request = FeedbackToggleRequest(status=True)
245-
246-
response = feedback_toggle(feedback_toggle_request=feedback_toggle_request)
247-
248-
assert response.functionality == "feedback"
249-
assert response.status == {"enabled": True}
220+
req = FeedbackStatusUpdateRequest(status=True)
221+
resp = await update_feedback_status(
222+
req,
223+
auth=("test_user_id", "test_username", "test_token"),
224+
)
225+
assert resp.status == {
226+
"previous_status": True,
227+
"updated_status": True,
228+
"updated_by": "test_user_id",
229+
}

0 commit comments

Comments
 (0)