Skip to content

Commit

Permalink
got things running on kube, sort of
Browse files Browse the repository at this point in the history
  • Loading branch information
kheina committed Jul 14, 2024
1 parent a16223c commit 2107571
Show file tree
Hide file tree
Showing 43 changed files with 876 additions and 580 deletions.
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# credentials
**/credentials.*
**/credentials
credentials
**/credentials*.*
**/credentials*
credentials*

# config files
.vscode
Expand Down
3 changes: 0 additions & 3 deletions .isort.cfg

This file was deleted.

3 changes: 1 addition & 2 deletions account/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from psycopg2.errors import UniqueViolation

from authenticator.authenticator import Authenticator
from authenticator.models import LoginResponse, TokenResponse
from shared.auth import KhUser, browserFingerprint, verifyToken
from shared.config.constants import environment
from shared.email import Button, sendEmail
Expand All @@ -13,8 +14,6 @@
from shared.server import Request
from shared.sql import SqlInterface

from authenticator.models import LoginResponse, TokenResponse


auth = Authenticator()

Expand Down
2 changes: 1 addition & 1 deletion account/router.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from fastapi import APIRouter
from fastapi.responses import Response

from authenticator.models import BotCreateResponse, BotLoginRequest, ChangePasswordRequest, LoginRequest, LoginResponse
from shared.auth import Scope
from shared.config.constants import environment
from shared.datetime import datetime
Expand All @@ -9,7 +10,6 @@

from .account import Account, auth
from .models import ChangeHandle, CreateAccountRequest, FinalizeAccountRequest
from authenticator.models import BotCreateResponse, BotLoginRequest, ChangePasswordRequest, LoginRequest, LoginResponse


app = APIRouter(
Expand Down
15 changes: 0 additions & 15 deletions authenticator/Dockerfile

This file was deleted.

9 changes: 6 additions & 3 deletions authenticator/authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,14 @@
"""


KVS: KeyValueStore = KeyValueStore('kheina', 'token')
BotLoginSerializer: AvroSerializer = AvroSerializer(BotLogin)
BotLoginDeserializer: AvroDeserializer = AvroDeserializer(BotLogin)


class Authenticator(SqlInterface, Hashable) :

EmailRegex = re_compile(r'^(?P<user>[A-Z0-9._%+-]+)@(?P<domain>[A-Z0-9.-]+\.[A-Z]{2,})$', flags=IGNORECASE)
KVS: KeyValueStore

def __init__(self) :
Hashable.__init__(self)
Expand All @@ -112,6 +112,9 @@ def __init__(self) :
'id': 0,
}

if getattr(Authenticator, 'KVS', None) is None :
Authenticator.KVS = KeyValueStore('kheina', 'token')


def _validateEmail(self, email: str) -> Dict[str, str] :
e = Authenticator.EmailRegex.search(email)
Expand Down Expand Up @@ -213,7 +216,7 @@ def generate_token(self, user_id: int, token_data: dict) -> TokenResponse :
algorithm=self._token_algorithm,
fingerprint=token_data.get('fp', '').encode(),
)
KVS.put(guid.bytes, token_info, self._token_expires_interval)
Authenticator.KVS.put(guid.bytes, token_info, self._token_expires_interval)

version = self._token_version.encode()
content = b64encode(version) + b'.' + b64encode(load)
Expand All @@ -233,7 +236,7 @@ def generate_token(self, user_id: int, token_data: dict) -> TokenResponse :
async def logout(self, guid: RefId) :
# since this endpoint is behind user.authenticated, we already know that the
# token exists and all the information is correct. we just need to delete it.
await KVS.remove_async(guid)
await Authenticator.KVS.remove_async(guid)


def fetchPublicKey(self, key_id, algorithm: Optional[AuthAlgorithm] = None) -> PublicKeyResponse :
Expand Down
32 changes: 16 additions & 16 deletions configs/configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from avrofastapi.schema import convert_schema
from avrofastapi.serialization import AvroDeserializer, AvroSerializer, Schema, parse_avro_schema
from shared.auth import KhUser
from shared.base64 import b64decode
from shared.caching import AerospikeCache
from shared.caching.key_value_store import KeyValueStore
from shared.config.constants import environment
Expand All @@ -26,7 +25,6 @@
PatreonClient: PatreonApi = PatreonApi(fetch('creator_access_token', str))
KVS: KeyValueStore = KeyValueStore('kheina', 'configs', local_TTL=60)
UserConfigSerializer: AvroSerializer = AvroSerializer(UserConfig)
UserConfigKeyFormat: str = 'user_config.{user_id}'
AvroMarker: bytes = b'\xC3\x01'
ColorRegex: Pattern = re_compile(r'^(?:#(?P<hex>[a-f0-9]{8}|[a-f0-9]{6})|(?P<var>[a-z0-9-]+))$')
PropValidators: Dict[CssProperty, Pattern] = {
Expand Down Expand Up @@ -75,7 +73,7 @@ def getFunding(self) -> int :

@HttpErrorHandler('retrieving config')
@AerospikeCache('kheina', 'configs', '{config}', _kvs=KVS)
async def getConfig(self, config: ConfigType) -> BaseModel :
async def getConfig[T: BaseModel](self, config: ConfigType, _: Type[T]) -> T :
data: List[bytes] = await self.query_async("""
SELECT bytes
FROM kheina.public.configs
Expand Down Expand Up @@ -119,42 +117,43 @@ async def updateConfig(self, user: KhUser, config: ConfigType, value: BaseModel)
KVS.put(config, value)


def _validateColors(css_properties: Optional[Dict[CssProperty, str]]) -> Optional[Dict[CssProperty, Union[str, int]]] :
@staticmethod
def _validateColors(css_properties: Optional[Dict[CssProperty, str]]) -> Optional[Dict[str, Union[str, int]]] :
if not css_properties :
return None

output: Dict[CssProperty, Union[str, int]] = { }
output: Dict[str, Union[str, int]] = { }

# color input is very strict
for prop, value in css_properties.items() :
if prop in PropValidators :
if PropValidators[prop].match(value) :
output[prop.value.replace('_', '-')] = value
output[prop.value] = value
continue

else :
raise BadRequest(f'{value} is not a valid value. when setting a background property, value must be a valid value for that property')

color: str = prop.value.replace('_', '-')
color = CssProperty(prop.value.replace('_', '-'))

match: Match[str] = ColorRegex.match(value)
match: Optional[Match[str]] = ColorRegex.match(value)
if not match :
raise BadRequest(f'{value} is not a valid color. value must be in the form "#xxxxxx", "#xxxxxxxx", or the name of another color variable (without the preceding deshes)')

if match.group('hex') :
if len(match.group('hex')) == 6 :
output[color] = int(match.group('hex') + 'ff', 16)
output[color.value] = int(match.group('hex') + 'ff', 16)

elif len(match.group('hex')) == 8 :
output[color] = int(match.group('hex') + 'ff', 16)
output[color.value] = int(match.group('hex'), 16)

else :
raise BadRequest(f'{value} is not a valid color. value must be in the form "#xxxxxx", "#xxxxxxxx", or the name of another color variable (without the preceding deshes)')

else :
c: str = match.group('var').replace('-', '_')
if c in CssProperty._member_map_ :
output[color] = CssProperty[c]
output[color.value] = c

else :
raise BadRequest(f'{value} is not a valid color. value must be in the form "#xxxxxx", "#xxxxxxxx", or the name of another color variable (without the preceding deshes)')
Expand All @@ -166,7 +165,7 @@ def _validateColors(css_properties: Optional[Dict[CssProperty, str]]) -> Optiona
async def setUserConfig(self, user: KhUser, value: UserConfigRequest) -> None :
user_config: UserConfig = UserConfig(
blocking_behavior=value.blocking_behavior,
blocked_tags=value.blocked_tags,
blocked_tags=list(map(list, value.blocked_tags)) if value.blocked_tags else None,
# TODO: internal tokens need to be added so that we can convert handles to user ids
blocked_users=None,
wallpaper=value.wallpaper,
Expand All @@ -185,8 +184,7 @@ async def setUserConfig(self, user: KhUser, value: UserConfigRequest) -> None :
updated = now(),
bytes = %s,
updated_by = %s;
""",
(
""", (
config_key, data, user.user_id,
data, user.user_id,
),
Expand Down Expand Up @@ -223,7 +221,7 @@ async def getUserConfig(self, user: KhUser) -> UserConfigResponse :

return UserConfigResponse(
blocking_behavior=user_config.blocking_behavior,
blocked_tags=user_config.blocked_tags,
blocked_tags=list(map(set, user_config.blocked_tags)) if user_config.blocked_tags else [],
# TODO: internal tokens need to be added so that we can convert user ids to handles
blocked_users=None,
wallpaper=user_config.wallpaper.decode() if user_config.wallpaper else None,
Expand All @@ -239,7 +237,9 @@ async def getUserTheme(self, user: KhUser) -> str :

css_properties: str = ''

for name, value in user_config.css_properties.items() :
for key, value in user_config.css_properties.items() :
name = key.replace("_", "-")

if isinstance(value, int) :
css_properties += f'--{name}:#{value:08x} !important;'

Expand Down
2 changes: 1 addition & 1 deletion configs/models.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from enum import Enum, unique
from typing import Dict, List, Literal, Optional, Set, Union
from shared.models import PostId

from pydantic import BaseModel, conbytes

from avrofastapi.schema import AvroInt
from shared.models import PostId


UserConfigKeyFormat: str = 'user.{user_id}'
Expand Down
6 changes: 3 additions & 3 deletions configs/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from shared.server import Request

from .configs import Configs
from .models import BannerResponse, CostsStore, FundingResponse, UpdateConfigRequest, UserConfigRequest, UserConfigResponse
from .models import BannerResponse, ConfigType, CostsStore, FundingResponse, UpdateConfigRequest, UserConfigRequest, UserConfigResponse


app = APIRouter(
Expand Down Expand Up @@ -37,12 +37,12 @@ async def shutdown() :
################################################## PUBLIC ##################################################
@app.get('/banner', response_model=BannerResponse)
async def v1Banner() -> BannerResponse :
return await configs.getConfig('banner')
return await configs.getConfig(ConfigType.banner, BannerResponse)


@app.get('/funding', response_model=FundingResponse)
async def v1Funding() -> FundingResponse :
costs: Task[CostsStore] = ensure_future(configs.getConfig('costs'))
costs: Task[CostsStore] = ensure_future(configs.getConfig(ConfigType.costs, CostsStore))
return FundingResponse(
funds=configs.getFunding(),
costs=(await costs).costs,
Expand Down
Loading

0 comments on commit 2107571

Please sign in to comment.