Compare commits

...

5 commits

Author SHA1 Message Date
789cd3f44c [perf] add some exception message 2023-04-06 17:36:49 +08:00
964159a133 [chroes] add respx package 2023-04-06 17:36:26 +08:00
bf8142eb0b [tests] add inbox stub test 2023-04-06 17:36:10 +08:00
5c01f24e91 [chores] bump packages version 2023-04-06 16:11:26 +08:00
bd5068e73e [fix] foreign key dependency
remove unnecessary foreign key undo id
2023-04-06 16:10:44 +08:00
7 changed files with 880 additions and 802 deletions

View file

@ -70,7 +70,8 @@ def run_migrations_online() -> None:
with connectable.connect() as connection: with connectable.connect() as connection:
context.configure( context.configure(
connection=connection, target_metadata=target_metadata connection=connection, target_metadata=target_metadata,
render_as_batch=True,
) )
with context.begin_transaction(): with context.begin_transaction():

View file

@ -33,12 +33,10 @@ def upgrade() -> None:
sa.Column('ap_object', sa.JSON(), nullable=False), sa.Column('ap_object', sa.JSON(), nullable=False),
sa.Column('activity_object_ap_id', sa.String(), nullable=True), sa.Column('activity_object_ap_id', sa.String(), nullable=True),
sa.Column('visibility', sa.Enum('PUBLIC', 'UNLISTED', 'FOLLOWERS_ONLY', 'DIRECT', name='visibilityenum'), nullable=False), sa.Column('visibility', sa.Enum('PUBLIC', 'UNLISTED', 'FOLLOWERS_ONLY', 'DIRECT', name='visibilityenum'), nullable=False),
sa.Column('undo_id', sa.Integer(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=False), sa.Column('is_deleted', sa.Boolean(), nullable=False),
sa.Column('relates_to_inbox_object_id', sa.Integer(), nullable=True), sa.Column('relates_to_inbox_object_id', sa.Integer(), nullable=True),
sa.Column('relates_to_outbox_object_id', sa.Integer(), nullable=True), sa.Column('relates_to_outbox_object_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['actor_id'], ['actor.id'], ), sa.ForeignKeyConstraint(['actor_id'], ['actor.id'], ),
sa.ForeignKeyConstraint(['undo_id'], ['inbox.id'], ),
sa.ForeignKeyConstraint(['relates_to_inbox_object_id'], ['inbox.id'], ), sa.ForeignKeyConstraint(['relates_to_inbox_object_id'], ['inbox.id'], ),
sa.ForeignKeyConstraint(['relates_to_outbox_object_id'], ['outbox.id'], ), sa.ForeignKeyConstraint(['relates_to_outbox_object_id'], ['outbox.id'], ),
sa.PrimaryKeyConstraint('id') sa.PrimaryKeyConstraint('id')
@ -59,7 +57,6 @@ def upgrade() -> None:
sa.Column('ap_object', sa.JSON(), nullable=False), sa.Column('ap_object', sa.JSON(), nullable=False),
sa.Column('activity_object_ap_id', sa.String(), nullable=True), sa.Column('activity_object_ap_id', sa.String(), nullable=True),
sa.Column('visibility', sa.Enum('PUBLIC', 'UNLISTED', 'FOLLOWERS_ONLY', 'DIRECT', name='visibilityenum'), nullable=False), sa.Column('visibility', sa.Enum('PUBLIC', 'UNLISTED', 'FOLLOWERS_ONLY', 'DIRECT', name='visibilityenum'), nullable=False),
sa.Column('undo_id', sa.Integer(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=False), sa.Column('is_deleted', sa.Boolean(), nullable=False),
sa.Column('likes_count', sa.Integer(), nullable=False), sa.Column('likes_count', sa.Integer(), nullable=False),
sa.Column('announces_count', sa.Integer(), nullable=False), sa.Column('announces_count', sa.Integer(), nullable=False),
@ -68,7 +65,6 @@ def upgrade() -> None:
sa.Column('relates_to_outbox_object_id', sa.Integer(), nullable=True), sa.Column('relates_to_outbox_object_id', sa.Integer(), nullable=True),
sa.Column('relates_to_actor_id', sa.Integer(), nullable=True), sa.Column('relates_to_actor_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['relates_to_actor_id'], ['actor.id'], ), sa.ForeignKeyConstraint(['relates_to_actor_id'], ['actor.id'], ),
sa.ForeignKeyConstraint(['undo_id'], ['outbox.id'], ),
sa.ForeignKeyConstraint(['relates_to_inbox_object_id'], ['inbox.id'], ), sa.ForeignKeyConstraint(['relates_to_inbox_object_id'], ['inbox.id'], ),
sa.ForeignKeyConstraint(['relates_to_outbox_object_id'], ['outbox.id'], ), sa.ForeignKeyConstraint(['relates_to_outbox_object_id'], ['outbox.id'], ),
sa.PrimaryKeyConstraint('id') sa.PrimaryKeyConstraint('id')

View file

@ -82,10 +82,18 @@ async def inbox(
payload = await request.json() payload = await request.json()
if httpsig_checker: if httpsig_checker:
await save_incoming(db_session, payload) if await save_incoming(db_session, payload):
return Response(status_code=202) return Response(status_code=202)
else:
return Response(
status_code=406,
content="invalid activitypub object"
)
else: else:
return Response(status_code=406) return Response(
status_code=406,
content="invalid http-sig"
)
@app.post("/outbox") @app.post("/outbox")

View file

@ -66,7 +66,6 @@ class InboxObject(Base):
visibility = Column(Enum(ap.VisibilityEnum), nullable=False) visibility = Column(Enum(ap.VisibilityEnum), nullable=False)
undo_id = Column(Integer, ForeignKey("inbox.id"), nullable=True)
is_deleted = Column(Boolean, nullable=False, default=False) is_deleted = Column(Boolean, nullable=False, default=False)
relates_to_inbox_object_id = Column( relates_to_inbox_object_id = Column(
Integer, Integer,
@ -81,7 +80,7 @@ class InboxObject(Base):
) )
relates_to_outbox_object_id = Column( relates_to_outbox_object_id = Column(
Integer, Integer,
ForeignKey("outbox.id"), ForeignKey("outbox.id", use_alter=True),
nullable=True, nullable=True,
) )
relates_to_outbox_object: Mapped[Optional["OutboxObject"]] = relationship( relates_to_outbox_object: Mapped[Optional["OutboxObject"]] = relationship(
@ -109,7 +108,6 @@ class OutboxObject(Base):
visibility = Column(Enum(ap.VisibilityEnum), nullable=False) visibility = Column(Enum(ap.VisibilityEnum), nullable=False)
undo_id = Column(Integer, ForeignKey("inbox.id"), nullable=True)
is_deleted = Column(Boolean, nullable=False, default=False) is_deleted = Column(Boolean, nullable=False, default=False)
likes_count = Column(Integer, nullable=False, default=0) likes_count = Column(Integer, nullable=False, default=0)
announces_count = Column(Integer, nullable=False, default=0) announces_count = Column(Integer, nullable=False, default=0)
@ -117,7 +115,7 @@ class OutboxObject(Base):
relates_to_inbox_object_id = Column( relates_to_inbox_object_id = Column(
Integer, Integer,
ForeignKey("inbox.id"), ForeignKey("inbox.id", use_alter=True),
nullable=True, nullable=True,
) )
relates_to_inbox_object: Mapped[Optional["InboxObject"]] = relationship( relates_to_inbox_object: Mapped[Optional["InboxObject"]] = relationship(

1619
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,7 @@ requests = "^2.28.2"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
pytest = "^7.2.0" pytest = "^7.2.0"
pytest-asyncio = "^0.21.0" pytest-asyncio = "^0.21.0"
respx = "^0.20.1"
[build-system] [build-system]
requires = ["poetry-core"] requires = ["poetry-core"]

35
tests/test_inbox.py Normal file
View file

@ -0,0 +1,35 @@
#!/usr/bin/env python3
import pytest
import fastapi
import respx
from app.main import app
from app.utils import precheck
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session
from app import activitypub as ap, httpsig
from app.config import AP_CONTENT_TYPE
def test_inbox_announce_request(
db: Session,
client: TestClient,
respx_mock: respx.MockRouter,
) -> None:
async def inbox_prechecker(
request: fastapi.Request,
) -> bool:
return True
app.dependency_overrides[precheck.inbox_prechecker] = inbox_prechecker
response = client.post(
"/inbox",
headers={"Content-Type": AP_CONTENT_TYPE},
json={"stub": 1},
)
print(response.headers)
print(response.content)
assert response.status_code == 200