Skip to content

Commit cc15cbc

Browse files
committed
feat(api): add /v1/publications resource
1 parent f8649cb commit cc15cbc

17 files changed

Lines changed: 507 additions & 28 deletions

app.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22

33
from contextlib import asynccontextmanager
44

5-
from fastapi import FastAPI
5+
from fastapi import FastAPI, Request
6+
from fastapi.responses import JSONResponse
67

7-
from api_v1 import router
88
from db import dispose_engine
99
from platforms.adapter_manager import AdapterManager
10+
from rest_services.v1.routes import router as v1_router
1011
from server_identity_keys import initialize_server_identity_keys
12+
from utils import get_logger
13+
14+
logger = get_logger(__name__)
1115

1216

1317
@asynccontextmanager
@@ -20,4 +24,19 @@ async def lifespan(app: FastAPI):
2024

2125

2226
app = FastAPI(lifespan=lifespan)
23-
app.include_router(router, prefix="/v1")
27+
app.include_router(v1_router, prefix="/v1")
28+
29+
30+
@app.exception_handler(ValueError)
31+
@app.exception_handler(NotImplementedError)
32+
async def error_exception_handler(request: Request, exc: ValueError):
33+
return JSONResponse(status_code=400, content={"error": str(exc)})
34+
35+
36+
@app.exception_handler(Exception)
37+
async def general_exception_handler(request: Request, exc: Exception):
38+
logger.exception(exc)
39+
return JSONResponse(
40+
status_code=500,
41+
content={"error": "Something went wrong. Please try again later."},
42+
)

grpc_services/v3/exchange_oauth2_code.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ def ExchangeOAuth2CodeAndStore(self, request, context):
7676
with get_session() as s:
7777
token = create_token(
7878
platform=request.platform.lower(),
79+
cat_id=adapter["cat_id"],
80+
protocol="oauth2",
7981
token_data={
8082
"account_id": result["userinfo"]["account_identifier"],
8183
"token": result["token"],

grpc_services/v3/exchange_pnba_code.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ def ExchangePNBACodeAndStore(self, request, context):
9999
with get_session() as s:
100100
token = create_token(
101101
platform=request.platform.lower(),
102+
cat_id=adapter["cat_id"],
103+
protocol="pnba",
102104
token_data={
103105
"account_id": result["userinfo"]["account_identifier"],
104106
"token": result["userinfo"]["account_identifier"],

grpc_services/v3/revoke_oauth2_token.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ def RevokeOAuth2Token(self, request, context):
3333

3434
try:
3535
with get_session() as s:
36-
token, token_hash_obj, ss_kid, es_kid, ec_kid_pk = get_keys_for_decryption(
37-
token_id_bytes=request.token_id,
38-
key_id=request.key_id,
39-
session=s,
36+
token, token_hash_obj, ss_kid, es_kid, _, ec_kid_pk = (
37+
get_keys_for_decryption(
38+
token_id_bytes=request.token_id, key_id=request.key_id, session=s
39+
)
4040
)
4141

4242
try:

grpc_services/v3/revoke_pnba_token.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ def RevokePNBAToken(self, request, context):
3333

3434
try:
3535
with get_session() as s:
36-
token, token_hash_obj, ss_kid, es_kid, ec_kid_pk = get_keys_for_decryption(
37-
token_id_bytes=request.token_id, key_id=request.key_id, session=s
36+
token, token_hash_obj, ss_kid, es_kid, _, ec_kid_pk = (
37+
get_keys_for_decryption(
38+
token_id_bytes=request.token_id, key_id=request.key_id, session=s
39+
)
3840
)
3941

4042
try:

grpc_services/v3/sync_keys.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def SyncKeys(self, request, context):
5050
)
5151

5252
with get_session() as s:
53-
_, token_hash_obj, ss_kid, es_kid, ec_kid_pk = get_keys_for_decryption(
53+
_, token_hash_obj, ss_kid, es_kid, _, ec_kid_pk = get_keys_for_decryption(
5454
token_id_bytes=request.token_id, key_id=request.key_id, session=s
5555
)
5656

grpc_services/v3/utils.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@
3030

3131
def get_keys_for_decryption(
3232
token_id_bytes: bytes, key_id: int, session: Session
33-
) -> tuple[Token, TokenHash, bytes, bytes, bytes]:
33+
) -> tuple[Token, TokenHash, bytes, bytes, bytes, bytes]:
3434
"""
3535
Fetch token and all necessary keys for decryption.
36-
Returns (Token, TokenHash, ss_kid, es_kid, ec_kid_pk).
36+
Returns (Token, TokenHash, ss_kid, es_kid, es_kid_pk, ec_kid_pk).
3737
"""
3838
token = get_by_token_id(token_id_bytes, session)
3939
if not token:
@@ -53,7 +53,14 @@ def get_keys_for_decryption(
5353
if not ce_key:
5454
raise ValueError(f"Client ephemeral key not found for kid {key_id}")
5555

56-
return token, token_hash_obj, ss_kid, se_key.private_key, ce_key.public_key
56+
return (
57+
token,
58+
token_hash_obj,
59+
ss_kid,
60+
se_key.private_key,
61+
se_key.public_key,
62+
ce_key.public_key,
63+
)
5764

5865

5966
def get_oauth2_adapter(platform: str) -> dict:

migrations/versions/002_add_tokens_table.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ def upgrade() -> None:
2323
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
2424
sa.Column("token_id", sa.LargeBinary(4), nullable=False, unique=True),
2525
sa.Column("platform", sa.String(length=100), nullable=False),
26+
sa.Column("cat_id", sa.SmallInteger(), nullable=False),
27+
sa.Column("protocol", sa.String(length=100), nullable=False),
2628
sa.Column("token_data", sa.Text(), nullable=False),
2729
sa.Column("created_at", sa.DateTime(), nullable=False),
2830
sa.Column("updated_at", sa.DateTime(), nullable=False),

models/client_ephemeral_key.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
LargeBinary,
1414
UniqueConstraint,
1515
)
16-
from sqlalchemy.orm import relationship
16+
from sqlalchemy.orm import Session, relationship
1717

1818
from db import Base
1919

@@ -46,3 +46,10 @@ class ClientEphemeralKey(Base):
4646
),
4747
Index("ix_client_ephemeral_keys_token_hash_id_used", "token_hash_id", "used"),
4848
)
49+
50+
51+
def delete_by_index(token_hash_id: int, key_index: int, session: Session) -> None:
52+
"""Delete a client ephemeral key by token_hash_id and key_index."""
53+
session.query(ClientEphemeralKey).filter_by(
54+
token_hash_id=token_hash_id, key_index=key_index
55+
).delete()

models/server_ephemeral_key.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
LargeBinary,
1414
UniqueConstraint,
1515
)
16-
from sqlalchemy.orm import relationship
16+
from sqlalchemy.orm import Session, relationship
1717

1818
from db import Base
1919
from db_types import PrivateEncryptedBinary
@@ -48,3 +48,10 @@ class ServerEphemeralKey(Base):
4848
),
4949
Index("ix_server_ephemeral_keys_token_hash_id_used", "token_hash_id", "used"),
5050
)
51+
52+
53+
def delete_by_index(token_hash_id: int, key_index: int, session: Session) -> None:
54+
"""Delete a server ephemeral key by token_hash_id and key_index."""
55+
session.query(ServerEphemeralKey).filter_by(
56+
token_hash_id=token_hash_id, key_index=key_index
57+
).delete()

0 commit comments

Comments
 (0)