Add poll workflow and signed participation support
This commit is contained in:
@@ -9,6 +9,9 @@ from govoplan_poll.backend.manifest import READ_SCOPE, RESPOND_SCOPE, WRITE_SCOP
|
||||
from govoplan_poll.backend.schemas import (
|
||||
PollCreateRequest,
|
||||
PollDecisionRequest,
|
||||
PollInvitationCreateRequest,
|
||||
PollInvitationListResponse,
|
||||
PollInvitationResponse,
|
||||
PollListResponse,
|
||||
PollResponse,
|
||||
PollResponseItem,
|
||||
@@ -21,16 +24,22 @@ from govoplan_poll.backend.schemas import (
|
||||
from govoplan_poll.backend.service import (
|
||||
PollError,
|
||||
close_poll,
|
||||
create_poll_invitation,
|
||||
create_poll,
|
||||
decide_poll,
|
||||
get_poll_by_invitation_token,
|
||||
get_poll,
|
||||
list_poll_responses,
|
||||
list_poll_invitations,
|
||||
list_polls,
|
||||
open_poll,
|
||||
poll_invitation_response,
|
||||
poll_response,
|
||||
poll_response_item,
|
||||
poll_result_summary_by_id,
|
||||
revoke_poll_invitation,
|
||||
submit_poll_response,
|
||||
submit_poll_response_with_token,
|
||||
update_poll,
|
||||
)
|
||||
|
||||
@@ -46,6 +55,8 @@ def _require_scope(principal: ApiPrincipal, scope: str) -> None:
|
||||
def _poll_http_error(exc: PollError) -> HTTPException:
|
||||
if str(exc) == "Poll not found":
|
||||
return HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc))
|
||||
if str(exc) == "Poll invitation not found":
|
||||
return HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc))
|
||||
return HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc))
|
||||
|
||||
|
||||
@@ -189,3 +200,78 @@ def api_poll_summary(
|
||||
return PollResultSummaryResponse.model_validate(poll_result_summary_by_id(session, tenant_id=principal.tenant_id, poll_id=poll_id))
|
||||
except PollError as exc:
|
||||
raise _poll_http_error(exc) from exc
|
||||
|
||||
|
||||
@router.post("/polls/{poll_id}/invitations", response_model=PollInvitationResponse, status_code=status.HTTP_201_CREATED)
|
||||
def api_create_poll_invitation(
|
||||
poll_id: str,
|
||||
payload: PollInvitationCreateRequest,
|
||||
session: Session = Depends(get_session),
|
||||
principal: ApiPrincipal = Depends(get_api_principal),
|
||||
) -> PollInvitationResponse:
|
||||
_require_scope(principal, WRITE_SCOPE)
|
||||
try:
|
||||
invitation, token = create_poll_invitation(session, tenant_id=principal.tenant_id, poll_id=poll_id, payload=payload)
|
||||
except PollError as exc:
|
||||
raise _poll_http_error(exc) from exc
|
||||
return PollInvitationResponse.model_validate(poll_invitation_response(invitation, token=token))
|
||||
|
||||
|
||||
@router.get("/polls/{poll_id}/invitations", response_model=PollInvitationListResponse)
|
||||
def api_list_poll_invitations(
|
||||
poll_id: str,
|
||||
session: Session = Depends(get_session),
|
||||
principal: ApiPrincipal = Depends(get_api_principal),
|
||||
) -> PollInvitationListResponse:
|
||||
_require_scope(principal, READ_SCOPE)
|
||||
try:
|
||||
invitations = list_poll_invitations(session, tenant_id=principal.tenant_id, poll_id=poll_id)
|
||||
except PollError as exc:
|
||||
raise _poll_http_error(exc) from exc
|
||||
return PollInvitationListResponse(
|
||||
invitations=[PollInvitationResponse.model_validate(poll_invitation_response(invitation)) for invitation in invitations]
|
||||
)
|
||||
|
||||
|
||||
@router.delete("/polls/{poll_id}/invitations/{invitation_id}", response_model=PollInvitationResponse)
|
||||
def api_revoke_poll_invitation(
|
||||
poll_id: str,
|
||||
invitation_id: str,
|
||||
session: Session = Depends(get_session),
|
||||
principal: ApiPrincipal = Depends(get_api_principal),
|
||||
) -> PollInvitationResponse:
|
||||
_require_scope(principal, WRITE_SCOPE)
|
||||
try:
|
||||
invitation = revoke_poll_invitation(
|
||||
session,
|
||||
tenant_id=principal.tenant_id,
|
||||
poll_id=poll_id,
|
||||
invitation_id=invitation_id,
|
||||
)
|
||||
except PollError as exc:
|
||||
raise _poll_http_error(exc) from exc
|
||||
return PollInvitationResponse.model_validate(poll_invitation_response(invitation))
|
||||
|
||||
|
||||
@router.get("/public/{token}", response_model=PollResponse)
|
||||
def api_get_public_poll(
|
||||
token: str,
|
||||
session: Session = Depends(get_session),
|
||||
) -> PollResponse:
|
||||
try:
|
||||
return _poll_response(get_poll_by_invitation_token(session, token=token))
|
||||
except PollError as exc:
|
||||
raise _poll_http_error(exc) from exc
|
||||
|
||||
|
||||
@router.post("/public/{token}/responses", response_model=PollResponseItem, status_code=status.HTTP_201_CREATED)
|
||||
def api_submit_public_poll_response(
|
||||
token: str,
|
||||
payload: PollSubmitResponseRequest,
|
||||
session: Session = Depends(get_session),
|
||||
) -> PollResponseItem:
|
||||
try:
|
||||
response = submit_poll_response_with_token(session, token=token, payload=payload)
|
||||
except PollError as exc:
|
||||
raise _poll_http_error(exc) from exc
|
||||
return PollResponseItem.model_validate(poll_response_item(response))
|
||||
|
||||
Reference in New Issue
Block a user