Skip to content

Commit aa9869c

Browse files
authored
✨ Implement Tracking Word Conversions (#105)
- Convert Hash to Words - Convert Words to Hash - Create Postman tests for examples
1 parent 4850dd6 commit aa9869c

File tree

5 files changed

+138
-12
lines changed

5 files changed

+138
-12
lines changed

app/api/v1/mediator/routes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
from . import election
44
from . import key
55
from . import tally
6+
from . import tracker
67

78
router = APIRouter()
89

910
router.include_router(election.router, prefix="/election")
1011
router.include_router(key.router, prefix="/key")
1112
router.include_router(ballot.router, prefix="/ballot")
1213
router.include_router(tally.router, prefix="/tally")
14+
router.include_router(tracker.router, prefix="/tracker")

app/api/v1/mediator/tracker.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from typing import Any
2+
from electionguard.group import ElementModQ
3+
from electionguard.serializable import read_json_object
4+
from electionguard.tracker import tracker_hash_to_words, tracker_words_to_hash
5+
from fastapi import APIRouter, Body
6+
7+
from ..models import (
8+
TrackerHash,
9+
TrackerHashRequest,
10+
TrackerWords,
11+
TrackerWordsRequest,
12+
)
13+
from ..tags import UTILITY
14+
15+
router = APIRouter()
16+
17+
18+
@router.post("/hash", tags=[UTILITY])
19+
def convert_tracker_to_hash(request: TrackerHashRequest = Body(...)) -> Any:
20+
"""
21+
Convert tracker from human readable / friendly words to hash
22+
"""
23+
24+
tracker_hash = tracker_words_to_hash(request.tracker_words, request.seperator)
25+
return TrackerHash(tracker_hash=str(tracker_hash))
26+
27+
28+
@router.post("/words", tags=[UTILITY])
29+
def convert_tracker_to_words(request: TrackerWordsRequest = Body(...)) -> Any:
30+
"""
31+
Convert tracker from hash to human readable / friendly words
32+
"""
33+
34+
tracker_hash = read_json_object(request.tracker_hash, ElementModQ)
35+
tracker_words = tracker_hash_to_words(tracker_hash, request.seperator)
36+
return TrackerWords(tracker_words=tracker_words)

app/api/v1/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
from .guardian import *
55
from .key import *
66
from .tally import *
7+
from .tracker import *

app/api/v1/models/tracker.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from electionguard.tracker import DEFAULT_SEPERATOR
2+
from .base import Base
3+
4+
__all__ = [
5+
"TrackerWordsRequest",
6+
"TrackerWords",
7+
"TrackerHashRequest",
8+
"TrackerHash",
9+
]
10+
11+
12+
class TrackerWordsRequest(Base):
13+
tracker_hash: str
14+
seperator: str = DEFAULT_SEPERATOR
15+
16+
17+
class TrackerWords(Base):
18+
tracker_words: str
19+
20+
21+
class TrackerHashRequest(Base):
22+
tracker_words: str
23+
seperator: str = DEFAULT_SEPERATOR
24+
25+
26+
class TrackerHash(Base):
27+
tracker_hash: str

tests/postman/ElectionGuard Web Api.postman_collection.json

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"info": {
3-
"_postman_id": "b6c83d85-3899-4ebb-ba68-679bec81bd52",
3+
"_postman_id": "81086475-1eea-4021-b602-b7441a7e86e6",
44
"name": "ElectionGuard Web Api",
55
"description": "A collection of API calls for ElectionGuard Web Api",
66
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
@@ -111,7 +111,7 @@
111111
{
112112
"listen": "test",
113113
"script": {
114-
"id": "44698cce-1da1-4296-b616-18dc0eae8a53",
114+
"id": "861b0dd4-0835-4f65-8f07-155ec5fb487e",
115115
"exec": [
116116
"pm.test(\"Ballots are returned in the same order as the request\", function () {",
117117
" const requestJson = JSON.parse(pm.request.body.toString())",
@@ -183,7 +183,7 @@
183183
{
184184
"listen": "test",
185185
"script": {
186-
"id": "7bc63d84-ffdb-4401-a1ba-dd94aa8066fa",
186+
"id": "9072fd9f-9ed4-47e3-86eb-9e31275131a0",
187187
"exec": [
188188
"pm.test(\"Ballots are returned in the same order as the request\", function () {",
189189
" const requestJson = JSON.parse(pm.request.body.toString())",
@@ -244,7 +244,7 @@
244244
{
245245
"listen": "prerequest",
246246
"script": {
247-
"id": "e6bc2390-9e1b-4acf-a7b4-76f961241303",
247+
"id": "df799c09-3a81-417c-bf1c-a2eac2ffab2a",
248248
"type": "text/javascript",
249249
"exec": [
250250
""
@@ -254,7 +254,7 @@
254254
{
255255
"listen": "test",
256256
"script": {
257-
"id": "e8558e10-d6d4-4a3f-804e-c3ff2ce9f4d1",
257+
"id": "d4204e33-758b-4476-b71e-e75c789f8e00",
258258
"type": "text/javascript",
259259
"exec": [
260260
""
@@ -477,13 +477,73 @@
477477
}
478478
},
479479
"response": []
480+
},
481+
{
482+
"name": "Tracker hash to words",
483+
"request": {
484+
"method": "POST",
485+
"header": [],
486+
"body": {
487+
"mode": "raw",
488+
"raw": "{\n \"tracker_hash\":\"82295779859697986364440242162484040502484343758343249767620990301560940975228\"\n}",
489+
"options": {
490+
"raw": {
491+
"language": "json"
492+
}
493+
}
494+
},
495+
"url": {
496+
"raw": "{{mediator-url}}/api/{{version}}/tracker/words",
497+
"host": [
498+
"{{mediator-url}}"
499+
],
500+
"path": [
501+
"api",
502+
"{{version}}",
503+
"tracker",
504+
"words"
505+
]
506+
},
507+
"description": "Get a readable / friendly word tracker from the hash"
508+
},
509+
"response": []
510+
},
511+
{
512+
"name": "Tracker words to hash",
513+
"request": {
514+
"method": "POST",
515+
"header": [],
516+
"body": {
517+
"mode": "raw",
518+
"raw": "{\n \"tracker_words\": \"abacus-abacus-amazement-arithmetic-assist-adjustment-assembly-alligator-antique-age-arena-airport-acquaintance-accomplishment-accord-apparel-airline-abacus-artist-adjective-assumption-aim-analogue-album-accelerant-advice-allergist-antibody-article-agent-appreciation-approach-assembly-appeal\"\n}",
519+
"options": {
520+
"raw": {
521+
"language": "json"
522+
}
523+
}
524+
},
525+
"url": {
526+
"raw": "{{mediator-url}}/api/{{version}}/tracker/hash",
527+
"host": [
528+
"{{mediator-url}}"
529+
],
530+
"path": [
531+
"api",
532+
"{{version}}",
533+
"tracker",
534+
"hash"
535+
]
536+
},
537+
"description": "Get a readable / friendly word tracker from the hash"
538+
},
539+
"response": []
480540
}
481541
],
482542
"event": [
483543
{
484544
"listen": "prerequest",
485545
"script": {
486-
"id": "93000645-0e5d-4d68-9b76-bc2fc8fb6e8a",
546+
"id": "2a3c6fcf-7c49-4a51-aa97-26aaa2544240",
487547
"type": "text/javascript",
488548
"exec": [
489549
""
@@ -493,7 +553,7 @@
493553
{
494554
"listen": "test",
495555
"script": {
496-
"id": "c68bbfaf-adac-418f-87f7-f2b6f81e6fd1",
556+
"id": "d7ef01db-6909-464c-b70e-8748b93d9631",
497557
"type": "text/javascript",
498558
"exec": [
499559
""
@@ -754,7 +814,7 @@
754814
{
755815
"listen": "test",
756816
"script": {
757-
"id": "74f0deec-8658-42ed-af3e-77287ee6c656",
817+
"id": "0a8fc220-b377-479b-9b3a-70fe85ee1660",
758818
"exec": [
759819
"pm.test(\"Ballot shares are returned in the same order as the request\", function () {",
760820
" const requestJson = JSON.parse(pm.request.body.toString())",
@@ -841,7 +901,7 @@
841901
{
842902
"listen": "prerequest",
843903
"script": {
844-
"id": "7690e768-e219-435e-988b-705406e4713b",
904+
"id": "9539fa67-e461-4138-b3b9-691dc8e5284a",
845905
"type": "text/javascript",
846906
"exec": [
847907
""
@@ -851,7 +911,7 @@
851911
{
852912
"listen": "test",
853913
"script": {
854-
"id": "072f942b-08c3-42d8-877b-16428077c390",
914+
"id": "724d61c2-5cf6-43ee-8994-0c9d596c1fea",
855915
"type": "text/javascript",
856916
"exec": [
857917
""
@@ -870,7 +930,7 @@
870930
{
871931
"listen": "prerequest",
872932
"script": {
873-
"id": "8b52952d-726b-48cb-b3eb-7f19bfa44c61",
933+
"id": "3109002d-bdb4-4cf2-8ad8-d507c48afd57",
874934
"type": "text/javascript",
875935
"exec": [
876936
""
@@ -880,7 +940,7 @@
880940
{
881941
"listen": "test",
882942
"script": {
883-
"id": "a0dc5753-cb73-44ad-9b75-4efe6c78ed79",
943+
"id": "8d5bbb95-fad8-4ee4-b727-4cbb6b39fc3f",
884944
"type": "text/javascript",
885945
"exec": [
886946
"pm.test(\"Status code is 200\", () => {",

0 commit comments

Comments
 (0)