Π·Π΅ΡΠΊΠ°Π»ΠΎ ΠΈΠ· https://github.com/microsoft/electionguard-api-python.git
* Fixes the 404 errors for Fetch Guardian and Fetch Public Keys * Log stack traces on error * Remove the memory repository, it didn't work * Notify client if there are duplicate guardians * typo * Show stack trace if errors occur retrieving guardians * Debugging should default to local storage for simplicity * Debug windows documentation * Fix linting * Minor cleanup to postman
This commit is contained in:
Π ΠΎΠ΄ΠΈΡΠ΅Π»Ρ
ff32ddfc18
ΠΠΎΠΌΠΌΠΈΡ
cbc7cc57b4
|
@ -15,7 +15,7 @@
|
|||
"PYTHONPATH": "${workspaceRoot}",
|
||||
"API_MODE": "guardian",
|
||||
"QUEUE_MODE": "remote",
|
||||
"STORAGE_MODE": "mongo"
|
||||
"STORAGE_MODE": "local_storage"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -32,7 +32,7 @@
|
|||
"PYTHONPATH": "${workspaceRoot}",
|
||||
"API_MODE": "mediator",
|
||||
"QUEUE_MODE": "remote",
|
||||
"STORAGE_MODE": "mongo"
|
||||
"STORAGE_MODE": "local_storage"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
13
README.md
13
README.md
|
@ -86,7 +86,7 @@ Developing with Python provides the fastest developer inner loop (speed from cod
|
|||
|
||||
### β
3.1. Windows Prerequisites
|
||||
|
||||
On Windows you can use an IDE of your choice in Windows, and run the make and Python commands in WSL which will expose API's in Windows. However, developing with Python on Windows involves additional setup that is not required for Linux or Mac.
|
||||
On Windows you can use an IDE of your choice in Windows, and run the make and Python commands in WSL which will expose API's in Windows. Developing with Python on Windows involves the following additional setup that is not required for Linux or Mac.
|
||||
|
||||
1. Install [WSL 2](https://docs.microsoft.com/en-us/windows/wsl/install)
|
||||
2. Install [Ubuntu](https://www.microsoft.com/en-us/p/ubuntu/9nblggh4msv6?ocid=9nblggh4msv6_ORSEARCH_Bing&rtc=1&activetab=pivot:overviewtab) (other Linux distributions should also work with minor modifications to the instructions below)
|
||||
|
@ -149,12 +149,21 @@ OR as guardian
|
|||
make start API_MODE=guardian
|
||||
```
|
||||
|
||||
### Debugging
|
||||
### Debugging Mac/Linux
|
||||
|
||||
For local debugging with Visual Studio Code, choose the `Guardian Web API` or `Mediator Web API` options from the dropdown in the Run menu. Once the server is up, you can easily hit your breakpoints.
|
||||
|
||||
If the code fails to run, [make sure your Python interpreter is set](https://code.visualstudio.com/docs/python/environments) to use your poetry environment.
|
||||
|
||||
### Debugging Windows
|
||||
|
||||
With Visual Studio Code:
|
||||
|
||||
1. Install the [Remote WSL](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl) extension
|
||||
2. In the bottom left click the Green Icon and "New WSL Window using Distro", select Ubuntu
|
||||
3. F5
|
||||
4. Choose either `Guardian Web API` or `Mediator Web API`
|
||||
|
||||
## π§ͺ Testing
|
||||
|
||||
End-to-end integration tests can be found in the [`/tests/integration`](/tests/integration) folder. To see them in action, run:
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import traceback
|
||||
import sys
|
||||
from typing import Dict, List
|
||||
from fastapi import APIRouter, Body, status, HTTPException, Request
|
||||
|
@ -120,8 +121,10 @@ def create_guardian(
|
|||
status_code=status.HTTP_409_CONFLICT,
|
||||
detail=f"Already exists {data.guardian_id}",
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as error:
|
||||
print(sys.exc_info())
|
||||
traceback.print_exc()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail="Submit guardian failed",
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import traceback
|
||||
from typing import List
|
||||
import sys
|
||||
from fastapi import APIRouter, Body, HTTPException, Request, status
|
||||
|
@ -37,7 +38,7 @@ def create_key_ceremony_guardian(
|
|||
"""
|
||||
Create a Key Ceremony Guardian.
|
||||
|
||||
In order for a guardian to participate they must be assiciated with the key ceremony first.
|
||||
In order for a guardian to participate they must be associated with the key ceremony first.
|
||||
"""
|
||||
try:
|
||||
with get_repository(
|
||||
|
@ -54,6 +55,7 @@ def create_key_ceremony_guardian(
|
|||
detail=f"Already exists {data.guardian_id}",
|
||||
)
|
||||
except Exception as error:
|
||||
traceback.print_exc()
|
||||
print(sys.exc_info())
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import traceback
|
||||
from typing import Any
|
||||
import sys
|
||||
from fastapi import HTTPException, status
|
||||
|
@ -22,6 +23,7 @@ __all__ = [
|
|||
def guardian_from_query(query_result: Any) -> Guardian:
|
||||
return Guardian(
|
||||
guardian_id=query_result["guardian_id"],
|
||||
name=query_result["name"],
|
||||
sequence_order=query_result["sequence_order"],
|
||||
number_of_guardians=query_result["number_of_guardians"],
|
||||
quorum=query_result["quorum"],
|
||||
|
@ -49,6 +51,7 @@ def get_guardian(guardian_id: str, settings: Settings = Settings()) -> Guardian:
|
|||
guardian = guardian_from_query(query_result)
|
||||
return guardian
|
||||
except Exception as error:
|
||||
traceback.print_exc()
|
||||
print(sys.exc_info())
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Dict, Any, List, Union
|
||||
from typing import Any, List, Union
|
||||
from collections.abc import MutableMapping
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
@ -17,7 +17,6 @@ from .settings import Settings, StorageMode
|
|||
__all__ = [
|
||||
"IRepository",
|
||||
"LocalRepository",
|
||||
"MemoryRepository",
|
||||
"MongoRepository",
|
||||
"get_repository",
|
||||
]
|
||||
|
@ -145,42 +144,6 @@ class LocalRepository(IRepository):
|
|||
pass
|
||||
|
||||
|
||||
class MemoryRepository(IRepository):
|
||||
def __init__(
|
||||
self,
|
||||
container: str,
|
||||
collection: str,
|
||||
):
|
||||
super().__init__()
|
||||
self._id = 0
|
||||
self._container = container
|
||||
self._collection = collection
|
||||
self.storage: Dict[int, Any] = {}
|
||||
|
||||
def __enter__(self) -> Any:
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type: Any, exc_value: Any, exc_traceback: Any) -> None:
|
||||
pass
|
||||
|
||||
def find(self, filter: MutableMapping, skip: int = 0, limit: int = 0) -> Any:
|
||||
pass
|
||||
|
||||
def get(self, filter: MutableMapping) -> Any:
|
||||
for item in self.storage.items():
|
||||
if item[filter[0]] == filter[1]:
|
||||
return item
|
||||
return None
|
||||
|
||||
def set(self, value: DOCUMENT_VALUE_TYPE) -> Any:
|
||||
self._id += 1
|
||||
self.storage[self._id] = value
|
||||
return str(self._id)
|
||||
|
||||
def update(self, filter: MutableMapping, value: DOCUMENT_VALUE_TYPE) -> Any:
|
||||
pass
|
||||
|
||||
|
||||
class MongoRepository(IRepository):
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -234,4 +197,4 @@ def get_repository(
|
|||
if settings.STORAGE_MODE == StorageMode.LOCAL_STORAGE:
|
||||
return LocalRepository(container, collection)
|
||||
|
||||
return MemoryRepository(container, collection)
|
||||
raise ValueError("Unsupported storage mode: " + settings.STORAGE_MODE)
|
||||
|
|
|
@ -23,7 +23,6 @@ class QueueMode(str, Enum):
|
|||
|
||||
class StorageMode(str, Enum):
|
||||
LOCAL_STORAGE = "local_storage"
|
||||
MEMORY = "memory"
|
||||
MONGO = "mongo"
|
||||
|
||||
|
||||
|
@ -31,7 +30,7 @@ class StorageMode(str, Enum):
|
|||
class Settings(BaseSettings):
|
||||
API_MODE: ApiMode = ApiMode.MEDIATOR
|
||||
QUEUE_MODE: QueueMode = QueueMode.LOCAL
|
||||
STORAGE_MODE: StorageMode = StorageMode.MEMORY
|
||||
STORAGE_MODE: StorageMode = StorageMode.LOCAL_STORAGE
|
||||
|
||||
API_V1_STR: str = "/api/v1"
|
||||
BACKEND_CORS_ORIGINS: List[AnyHttpUrl] = Field(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"info": {
|
||||
"_postman_id": "977c776c-3ab8-40d2-a0ab-7c56f6f510d8",
|
||||
"_postman_id": "afbe5e1b-166d-404d-8b1f-76d33fc07ecb",
|
||||
"name": "ElectionGuard Web Api",
|
||||
"description": "A collection of API calls for ElectionGuard Web Api",
|
||||
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
||||
|
@ -136,7 +136,7 @@
|
|||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"filter\": {\n \"state\": \"OPEN\"\n }\n}",
|
||||
"raw": "{\n \"filter\": {\n \"state\": \"CREATED\"\n }\n}",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
|
@ -257,7 +257,7 @@
|
|||
"method": "POST",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{mediator-url}}/api/{{version}}/election/close?election_id=some-election-id-1",
|
||||
"raw": "{{mediator-url}}/api/{{version}}/election/close?election_id=hamilton-general-election-1",
|
||||
"host": [
|
||||
"{{mediator-url}}"
|
||||
],
|
||||
|
@ -270,7 +270,7 @@
|
|||
"query": [
|
||||
{
|
||||
"key": "election_id",
|
||||
"value": "some-election-id-1"
|
||||
"value": "hamilton-general-election-1"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -283,7 +283,7 @@
|
|||
"method": "POST",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{mediator-url}}/api/{{version}}/election/publish?election_id=some-election-id-1",
|
||||
"raw": "{{mediator-url}}/api/{{version}}/election/publish?election_id=hamilton-general-election-1",
|
||||
"host": [
|
||||
"{{mediator-url}}"
|
||||
],
|
||||
|
@ -296,7 +296,7 @@
|
|||
"query": [
|
||||
{
|
||||
"key": "election_id",
|
||||
"value": "some-election-id-1"
|
||||
"value": "hamilton-general-election-1"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1707,7 +1707,7 @@
|
|||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"guardian_id\": \"guardian_1\",\n \"sequence_order\": 1,\n \"number_of_guardians\": 3,\n \"quorum\": 2\n}",
|
||||
"raw": "{\n \"guardian_id\": \"guardian_1\",\n \"name\": \"Bob Smith 1\",\n \"sequence_order\": 1,\n \"number_of_guardians\": 3,\n \"quorum\": 2\n}",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
|
@ -1884,7 +1884,7 @@
|
|||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"owner_id\":\"hamilton-county-canvass-board-member-0\",\n \"sequence_order\": 0\n \"quorum\": 3\n}",
|
||||
"raw": "{\n \"owner_id\":\"hamilton-county-canvass-board-member-0\",\n \"sequence_order\": 0,\n \"quorum\": 3\n}",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
|
|
ΠΠ°Π³ΡΡΠ·ΠΊΠ°β¦
Π‘ΡΡΠ»ΠΊΠ° Π² Π½ΠΎΠ²ΠΎΠΉ Π·Π°Π΄Π°ΡΠ΅