feat: add ballot casting endpoint

This commit is contained in:
Alexandre Teles 2022-11-17 02:57:58 -03:00
parent 0b45044649
commit 641bf689a4
6 changed files with 52 additions and 101 deletions

36
app/controllers/Ballot.py Normal file
View File

@ -0,0 +1,36 @@
from redis import asyncio as aioredis
import app.utils.Logger as Logger
from app.dependencies import load_config
from app.utils.RedisConnector import RedisConnector
config: dict = load_config()
class Ballot:
"""Implements a ballot for ReVanced Polling API."""
redis = RedisConnector.connect(config['tokens']['database'])
BallotLogger = Logger.BallotLogger()
async def store(self, discord_hashed_id: str, ballot: str) -> bool:
"""Store a ballot.
Args:
discord_hashed_id (str): Discord hashed ID of the voter
ballot (dict): Ballot to store
Returns:
bool: True if the ballot was stored successfully, False otherwise
"""
stored: bool = False
try:
await self.redis.set(name=discord_hashed_id, value=ballot, nx=True)
await self.BallotLogger.log("STORE_BALLOT", None, discord_hashed_id)
stored = True
except aioredis.RedisError as e:
await self.BallotLogger.log("STORE_BALLOT", e)
raise e
return stored

View File

@ -1,8 +1,4 @@
from time import sleep
from redis import asyncio as aioredis from redis import asyncio as aioredis
import uvloop
import app.utils.Logger as Logger import app.utils.Logger as Logger
from app.dependencies import load_config from app.dependencies import load_config
from app.utils.RedisConnector import RedisConnector from app.utils.RedisConnector import RedisConnector

View File

@ -1,5 +1,4 @@
import os import os
import toml
import binascii import binascii
from redis import Redis from redis import Redis
@ -30,6 +29,7 @@ from app.routers import root
from app.routers import auth from app.routers import auth
from app.routers import items from app.routers import items
from app.routers import ping from app.routers import ping
from app.routers import ballot
"""Implements an API for our polling app""" """Implements an API for our polling app"""
@ -64,6 +64,7 @@ app.add_middleware(SlowAPIMiddleware)
app.include_router(root.router) app.include_router(root.router)
app.include_router(items.router) app.include_router(items.router)
app.include_router(ballot.router)
app.include_router(auth.router) app.include_router(auth.router)
app.include_router(ping.router) app.include_router(ping.router)

View File

@ -1,5 +1,4 @@
from pydantic import BaseModel from pydantic import BaseModel
from app.models.BallotFields import BallotFields
class BallotModel(BaseModel): class BallotModel(BaseModel):
"""Implements the fields for the ballots. """Implements the fields for the ballots.
@ -8,5 +7,4 @@ class BallotModel(BaseModel):
BaseModel (pydantic.BaseModel): BaseModel from pydantic BaseModel (pydantic.BaseModel): BaseModel from pydantic
""" """
discord_id_hash: str vote: str
ballot: str

View File

@ -3,33 +3,6 @@ import app.models.ResponseFields as ResponseFields
"""Implements pydantic models and model generator for the API's responses.""" """Implements pydantic models and model generator for the API's responses."""
class ToolsResponseModel(BaseModel):
"""Implements the JSON response model for the /tools endpoint.
Args:
BaseModel (pydantic.BaseModel): BaseModel from pydantic
"""
tools: list[ ResponseFields.ToolsResponseFields ]
class PatchesResponseModel(BaseModel):
"""Implements the JSON response model for the /patches endpoint.
Args:
BaseModel (pydantic.BaseModel): BaseModel from pydantic
"""
__root__: list[ ResponseFields.PatchesResponseFields ]
class ContributorsResponseModel(BaseModel):
"""Implements the JSON response model for the /contributors endpoint.
Args:
BaseModel (pydantic.BaseModel): BaseModel from pydantic
"""
repositories: list[ ResponseFields.ContributorsResponseFields ]
class PingResponseModel(BaseModel): class PingResponseModel(BaseModel):
"""Implements the JSON response model for the /heartbeat endpoint. """Implements the JSON response model for the /heartbeat endpoint.
@ -40,26 +13,6 @@ class PingResponseModel(BaseModel):
status: int status: int
detail: str detail: str
class ClientDeletedResponse(BaseModel):
"""Implements the response fields for deleted clients.
Args:
BaseModel (pydantic.BaseModel): BaseModel from pydantic
"""
id: str
deleted: bool
class ClientSecretUpdatedResponse(BaseModel):
"""Implements the response fields for updated client secrets.
Args:
BaseModel (pydantic.BaseModel): BaseModel from pydantic
"""
id: str
secret: str
class ClientAuthTokenResponse(BaseModel): class ClientAuthTokenResponse(BaseModel):
"""Implements the response fields for client auth tokens. """Implements the response fields for client auth tokens.
@ -69,36 +22,6 @@ class ClientAuthTokenResponse(BaseModel):
access_token: str access_token: str
class ClientTokenRefreshResponse(BaseModel):
"""Implements the response fields for client token refresh.
Args:
BaseModel (pydantic.BaseModel): BaseModel from pydantic
"""
access_token: str
class ClientStatusResponse(BaseModel):
"""Implements the response fields for client status.
Args:
BaseModel (pydantic.BaseModel): BaseModel from pydantic
"""
id: str
active: bool
class ChangelogsResponseModel(BaseModel):
"""Implements the JSON response model for the /changelogs endpoint.
Args:
BaseModel (pydantic.BaseModel): BaseModel from pydantic
"""
repository: str
path: str
commits: list[ ResponseFields.ChangelogsResponseFields ]
class RevokedTokenResponse(BaseModel): class RevokedTokenResponse(BaseModel):
"""Implements the response fields for token invalidation. """Implements the response fields for token invalidation.
@ -107,3 +30,12 @@ class RevokedTokenResponse(BaseModel):
""" """
revoked: bool revoked: bool
class BallotCastedResponse(BaseModel):
"""Implements the response fields for ballot casted.
Args:
BaseModel (pydantic.BaseModel): BaseModel from pydantic
"""
casted: bool

View File

@ -51,28 +51,16 @@ class UserLogger:
else: else:
logger.info(f"[User] REDIS {operation} {key} - OK") logger.info(f"[User] REDIS {operation} {key} - OK")
class AnnouncementsLogger: class BallotLogger:
async def log(self, operation: str, result: RedisError | None = None, key: str = "") -> None: async def log(self, operation: str, result: RedisError | None = None, key: str = "") -> None:
"""Logs internal cache operations """Logs ballot operations
Args: Args:
operation (str): Operation name operation (str): Operation name
key (str): Key used in the operation key (str): Key used in the operation
""" """
if type(result) is RedisError: if type(result) is RedisError:
logger.error(f"[ANNOUNCEMENT] REDIS {operation} - Failed with error: {result}") logger.error(f"[BALLOT] REDIS {operation} - Failed with error: {result}")
else: else:
logger.info(f"[ANNOUNCEMENT] REDIS {operation} {key} - OK") logger.info(f"[BALLOT] REDIS {operation} {key} - OK")
class MirrorsLogger:
async def log(self, operation: str, result: RedisError | None = None, key: str = "") -> None:
"""Logs internal cache operations
Args:
operation (str): Operation name
key (str): Key used in the operation
"""
if type(result) is RedisError:
logger.error(f"[MIRRORS] REDIS {operation} - Failed with error: {result}")
else:
logger.info(f"[MIRRORS] REDIS {operation} {key} - OK")