Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 50 additions & 3 deletions app/api/v1/mediator/election.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
from os.path import realpath, join
from typing import Any
from typing import Any, Optional
from electionguard.election import (
ElectionDescription,
ElectionConstants,
make_ciphertext_election_context,
)
from electionguard.group import ElementModP
from electionguard.schema import validate_json_schema
from electionguard.serializable import read_json_object, write_json_object
from fastapi import APIRouter, Body

from ..models import ElectionContextRequest
from fastapi import APIRouter, Body, Depends

from app.core.schema import get_description_schema
from ..models import (
ElectionContextRequest,
ValidationResponse,
ValidateElectionDescriptionRequest,
)
from ..tags import CONFIGURE_ELECTION

router = APIRouter()
Expand Down Expand Up @@ -47,3 +54,43 @@ def build_election_context(request: ElectionContextRequest = Body(...)) -> Any:
)

return write_json_object(context)


@router.post("/validate/description", tags=[CONFIGURE_ELECTION])
def validate_election_description(
request: ValidateElectionDescriptionRequest = Body(...),
schema: Any = Depends(get_description_schema),
) -> Any:
"""
Validate an Election description or manifest for a given election
"""

success = True
message = "Election description successfully validated"
details = ""

# Check schema
schema = request.schema_override if request.schema_override else schema
(schema_success, error_details) = validate_json_schema(request.description, schema)
if not schema_success:
success = schema_success
message = "Election description did not match schema"
details = error_details

# Check object parse
description: Optional[ElectionDescription] = None
if success:
try:
description = ElectionDescription.from_json_object(request.description)
except Exception: # pylint: disable=broad-except
success = False
message = "Election description could not be read from JSON"

if success:
if description:
valid_success = description.is_valid()
if not valid_success:
message = "Election description was not valid well formed data"

# Check
return ValidationResponse(success=success, message=message, details=details)
1 change: 1 addition & 0 deletions app/api/v1/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
from .key import *
from .tally import *
from .tracker import *
from .validation import *
18 changes: 17 additions & 1 deletion app/api/v1/models/election.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
from typing import Any

from .base import Base
from .validation import BaseValidationRequest


__all__ = ["CiphertextElectionContext", "ElectionContextRequest", "ElectionDescription"]
__all__ = [
"CiphertextElectionContext",
"ElectionContextRequest",
"ElectionDescription",
"ValidateElectionDescriptionRequest",
]

ElectionDescription = Any

Expand All @@ -17,3 +25,11 @@ class ElectionContextRequest(Base):
elgamal_public_key: str
number_of_guardians: int
quorum: int


class ValidateElectionDescriptionRequest(BaseValidationRequest):
"""
A request to validate an Election Description
"""

description: ElectionDescription
20 changes: 20 additions & 0 deletions app/api/v1/models/validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from typing import Any, Optional
from .base import Base

__all__ = ["BaseValidationRequest", "ValidationResponse", "Schema"]

Schema = Any


class BaseValidationRequest(Base):
"""Base validation request"""

schema_override: Optional[Schema] = None


class ValidationResponse(Base):
"""Response for validating models"""

success: bool
message: str
details: str = ""
10 changes: 10 additions & 0 deletions app/core/schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from functools import lru_cache
from typing import Any
from electionguard.schema import get_election_description_schema

__all__ = ["get_description_schema"]


@lru_cache
def get_description_schema() -> Any:
return get_election_description_schema()
42 changes: 38 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 42 additions & 12 deletions tests/postman/ElectionGuard Web Api.postman_collection.json

Large diffs are not rendered by default.