Compare commits
5 commits
11f9729931
...
789cd3f44c
Author | SHA1 | Date | |
---|---|---|---|
789cd3f44c | |||
964159a133 | |||
bf8142eb0b | |||
5c01f24e91 | |||
bd5068e73e |
7 changed files with 880 additions and 802 deletions
|
@ -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():
|
||||||
|
|
|
@ -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')
|
||||||
|
|
14
app/main.py
14
app/main.py
|
@ -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")
|
||||||
|
|
|
@ -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
1619
poetry.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -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
35
tests/test_inbox.py
Normal 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
|
Loading…
Reference in a new issue