add barkshark-lib dep
This commit is contained in:
parent
848350684f
commit
026f5bd11d
|
@ -1,7 +1,8 @@
|
|||
import aputils
|
||||
import click
|
||||
import platform
|
||||
|
||||
from aputils import Signer
|
||||
from blib import HttpDate
|
||||
from pathlib import Path
|
||||
|
||||
from . import TRANS
|
||||
|
@ -29,7 +30,7 @@ def cli_setup(ctx: click.Context) -> None:
|
|||
click.confirm(TRANS.fetch("setup", "prompt-database"), abort = True)
|
||||
ctx.obj.config.sqlite_path.unlink()
|
||||
|
||||
current = aputils.HttpDate.new_utc()
|
||||
current = HttpDate.new_utc()
|
||||
|
||||
with ctx.obj.database.session(True) as s:
|
||||
s.create_tables()
|
||||
|
@ -47,10 +48,10 @@ def cli_setup(ctx: click.Context) -> None:
|
|||
})
|
||||
|
||||
click.echo(TRANS.fetch("setup", "create-key", username = ctx.obj.config.host))
|
||||
instance_signer = aputils.Signer.new(f"https://{ctx.obj.config.web_host}/actor")
|
||||
instance_signer = Signer.new(f"https://{ctx.obj.config.web_host}/actor")
|
||||
|
||||
click.echo(TRANS.fetch("setup", "create-key", username = "relay"))
|
||||
relay_signer = aputils.Signer.new(f"https://{ctx.obj.config.web_host}/relay")
|
||||
relay_signer = Signer.new(f"https://{ctx.obj.config.web_host}/relay")
|
||||
|
||||
s.insert("user", {
|
||||
"id": -99,
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import aputils
|
||||
import sqlite3
|
||||
|
||||
from aputils import MessageDate
|
||||
from blib import HttpDate, Enum
|
||||
|
||||
from .connection import Connection
|
||||
from .schema import SCHEMA
|
||||
|
||||
|
||||
sqlite3.register_adapter(aputils.Enum, lambda v: v.value)
|
||||
sqlite3.register_adapter(aputils.HttpDate, lambda v: v.timestamp())
|
||||
sqlite3.register_adapter(aputils.MessageDate, lambda v: v.timestamp())
|
||||
sqlite3.register_adapter(Enum, lambda v: v.value)
|
||||
sqlite3.register_adapter(HttpDate, lambda v: v.timestamp())
|
||||
sqlite3.register_adapter(MessageDate, lambda v: v.timestamp())
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from aputils import JsonBase
|
||||
from bsql import Row, boolean
|
||||
from blib import JsonBase, convert_to_boolean
|
||||
from bsql import Row
|
||||
|
||||
from collections.abc import Callable, Iterator, Sequence
|
||||
from typing import Any, Generic, Self, TypeVar
|
||||
|
@ -9,7 +9,7 @@ from .. import TRANS
|
|||
|
||||
T = TypeVar("T")
|
||||
CONVERTERS: dict[type, tuple[Callable[[str], Any], Callable[[Any], str]]] = {
|
||||
bool: (boolean, str),
|
||||
bool: (convert_to_boolean, str),
|
||||
int: (int, str),
|
||||
dict: (JsonBase.parse, lambda value: JsonBase(value).to_json()),
|
||||
str: (str, str)
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import aputils
|
||||
import bsql
|
||||
import secrets
|
||||
|
||||
from aputils import Message, MessageDate, Nodeinfo, ObjectType, Signer, Webfinger
|
||||
from argon2 import PasswordHasher
|
||||
from basgi import Application as App
|
||||
from blib import HttpDate
|
||||
from bsql import Connection as BsqlConnection, Row
|
||||
from collections.abc import Iterator
|
||||
from typing import TYPE_CHECKING, Any, TypeVar
|
||||
|
||||
|
@ -23,7 +24,7 @@ if TYPE_CHECKING:
|
|||
T = TypeVar("T", bound = ObjectMixin)
|
||||
|
||||
|
||||
class Connection(bsql.Connection):
|
||||
class Connection(BsqlConnection):
|
||||
@property
|
||||
def app(self) -> Application:
|
||||
return App.get("BarksharkSocial") # type: ignore[return-value]
|
||||
|
@ -100,8 +101,6 @@ class Connection(bsql.Connection):
|
|||
if not domain:
|
||||
domain = self.config.host
|
||||
|
||||
print(username, domain)
|
||||
|
||||
with self.select("user", username = username, domain = domain) as cur:
|
||||
return User.from_possible_row(cur.one())
|
||||
|
||||
|
@ -156,7 +155,7 @@ class Connection(bsql.Connection):
|
|||
description: str | None = None,
|
||||
short_description: str | None = None) -> Instance:
|
||||
|
||||
date = aputils.HttpDate.new_utc()
|
||||
date = HttpDate.new_utc()
|
||||
data = Instance.new(
|
||||
domain = domain,
|
||||
web_domain = web_domain,
|
||||
|
@ -171,9 +170,9 @@ class Connection(bsql.Connection):
|
|||
|
||||
|
||||
def put_instance_data(self,
|
||||
nodeinfo: aputils.Nodeinfo,
|
||||
webfinger: aputils.Webfinger,
|
||||
actor: aputils.Message) -> Instance:
|
||||
nodeinfo: Nodeinfo,
|
||||
webfinger: Webfinger,
|
||||
actor: Message) -> Instance:
|
||||
|
||||
if self.get_instance(actor.domain) is not None:
|
||||
raise KeyError("Instance already exists")
|
||||
|
@ -193,7 +192,7 @@ class Connection(bsql.Connection):
|
|||
except KeyError:
|
||||
description = None
|
||||
|
||||
current = aputils.HttpDate.new_utc()
|
||||
current = HttpDate.new_utc()
|
||||
instance = Instance(
|
||||
id = 0 if has_instance else 1,
|
||||
domain = webfinger.domain,
|
||||
|
@ -229,8 +228,8 @@ class Connection(bsql.Connection):
|
|||
raise ValueError(TRANS.fetch("error", "empty-row"))
|
||||
|
||||
TRANS.print("setup", "create-key", username = username)
|
||||
signer = aputils.Signer.new(f"https://{instance.web_domain}/user/{username}#main-key")
|
||||
date = aputils.HttpDate.new_utc()
|
||||
signer = Signer.new(f"https://{instance.web_domain}/user/{username}#main-key")
|
||||
date = HttpDate.new_utc()
|
||||
data = User(
|
||||
id = 0 if has_user else 1,
|
||||
username = username,
|
||||
|
@ -260,7 +259,7 @@ class Connection(bsql.Connection):
|
|||
return self.insert_row(data)
|
||||
|
||||
|
||||
def put_remote_user(self, actor: aputils.Message) -> User:
|
||||
def put_remote_user(self, actor: Message) -> User:
|
||||
with self.run("get-at-least-1-user") as cur:
|
||||
has_user = cur.one() is not None
|
||||
|
||||
|
@ -274,7 +273,7 @@ class Connection(bsql.Connection):
|
|||
date = actor.published
|
||||
|
||||
except AttributeError:
|
||||
date = aputils.MessageDate.now()
|
||||
date = MessageDate.now()
|
||||
|
||||
data = User(
|
||||
id = 0 if has_user else 1,
|
||||
|
@ -288,7 +287,7 @@ class Connection(bsql.Connection):
|
|||
password = None,
|
||||
permission = PermissionLevel.REMOTE,
|
||||
locked = actor.manually_approves_followers,
|
||||
is_bot = actor.type != aputils.ObjectType.PERSON,
|
||||
is_bot = actor.type != ObjectType.PERSON,
|
||||
private_key = None,
|
||||
public_key = actor.pubkey,
|
||||
bio = actor.get("summary", ""),
|
||||
|
@ -348,7 +347,7 @@ class Connection(bsql.Connection):
|
|||
|
||||
|
||||
def put_cookie(self, user: User, user_agent: str | None) -> Cookie:
|
||||
date = aputils.HttpDate.new_utc()
|
||||
date = HttpDate.new_utc()
|
||||
params = {
|
||||
"code": secrets.token_hex(16),
|
||||
"userid": user.id,
|
||||
|
@ -369,7 +368,7 @@ class Connection(bsql.Connection):
|
|||
pass
|
||||
|
||||
|
||||
def get_count(row: bsql.Row | None) -> int:
|
||||
def get_count(row: Row | None) -> int:
|
||||
if not row:
|
||||
return 0
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import aputils
|
||||
import bsql
|
||||
import typing
|
||||
|
||||
from aputils import MessageDate, Signer
|
||||
from blib import HttpDate
|
||||
from bsql import Row
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Any, Self
|
||||
|
@ -29,7 +30,7 @@ class ObjectMixin:
|
|||
|
||||
|
||||
@classmethod
|
||||
def from_row(cls: type[Self], row: bsql.Row | dict[str, Any]) -> Self:
|
||||
def from_row(cls: type[Self], row: Row | dict[str, Any]) -> Self:
|
||||
data = []
|
||||
|
||||
for key in cls.__dataclass_fields__:
|
||||
|
@ -40,7 +41,7 @@ class ObjectMixin:
|
|||
value = row[key]
|
||||
|
||||
if isinstance(value, datetime):
|
||||
value = aputils.MessageDate.parse(value)
|
||||
value = MessageDate.parse(value)
|
||||
|
||||
data.append(value)
|
||||
|
||||
|
@ -51,7 +52,7 @@ class ObjectMixin:
|
|||
|
||||
|
||||
@classmethod
|
||||
def from_possible_row(cls: type[Self], row: bsql.Row | dict[str, Any] | None) -> Self | None:
|
||||
def from_possible_row(cls: type[Self], row: Row | dict[str, Any] | None) -> Self | None:
|
||||
if row is None:
|
||||
return None
|
||||
|
||||
|
@ -108,7 +109,7 @@ class Follow(ObjectMixin):
|
|||
target.get_instance(connection).id,
|
||||
followid,
|
||||
accept,
|
||||
aputils.HttpDate.new_utc()
|
||||
HttpDate.new_utc()
|
||||
)
|
||||
|
||||
|
||||
|
@ -177,11 +178,11 @@ class User(ObjectMixin):
|
|||
|
||||
|
||||
@property
|
||||
def signer(self) -> aputils.Signer:
|
||||
def signer(self) -> Signer:
|
||||
if self.private_key:
|
||||
return aputils.Signer(self.private_key, self.actor + "#main-key")
|
||||
return Signer(self.private_key, self.actor + "#main-key")
|
||||
|
||||
return aputils.Signer(self.public_key, self.actor + "#main-key")
|
||||
return Signer(self.public_key, self.actor + "#main-key")
|
||||
|
||||
|
||||
# auth middleware stuff
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from aputils import IntEnum, StrEnum
|
||||
from blib import IntEnum, StrEnum
|
||||
|
||||
|
||||
class PermissionLevel(IntEnum):
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#info
|
||||
.avatar
|
||||
%div
|
||||
-if user.domain != state.config.host
|
||||
-if user.domain != app.config.host
|
||||
%p.handle
|
||||
%a(href="{{user.page_url}}" target="_new") << @{{user.handle}}
|
||||
|
||||
|
|
|
@ -4,8 +4,9 @@ import httpx
|
|||
import logging
|
||||
import traceback
|
||||
|
||||
from aputils import JsonBase, Message, Signature, SignatureFailureError
|
||||
from aputils import Message, Signature, SignatureFailureError
|
||||
from basgi import Client, HttpError, Request
|
||||
from blib import JsonBase
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from .database.connection import Connection
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from importlib.resources import files as PackageFiles
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
def get_resource(path: str) -> Path:
|
||||
|
@ -10,31 +9,3 @@ def get_resource(path: str) -> Path:
|
|||
def read_resource_text(path: str) -> str:
|
||||
with get_resource(path).open("r", encoding = "utf-8") as fd:
|
||||
return fd.read()
|
||||
|
||||
|
||||
class DictProperty:
|
||||
"Provide attribute access to a dict key."
|
||||
|
||||
|
||||
def __init__(self, key: str):
|
||||
self.key = key
|
||||
|
||||
|
||||
def __get__(self, obj: dict[str, Any] | None, objtype: type[Any] | None = None) -> Any:
|
||||
if obj is None:
|
||||
return self
|
||||
|
||||
try:
|
||||
return obj[self.key]
|
||||
|
||||
except KeyError:
|
||||
objname = object.__class__.__name__
|
||||
raise AttributeError(f"'{objname}' has no attribute '{self.key}'") from None
|
||||
|
||||
|
||||
def __set__(self, obj: dict[str, Any], value: Any) -> None:
|
||||
obj[self.key] = value
|
||||
|
||||
|
||||
def __delete__(self, obj: dict[str, Any]) -> None:
|
||||
del obj[self.key]
|
||||
|
|
|
@ -76,6 +76,10 @@ async def handle_undo(request: Request, message: Message, user: User) -> None:
|
|||
else:
|
||||
obj = Message.parse(message.object)
|
||||
|
||||
if obj.type not in ObjectType.Actor:
|
||||
print(repr(obj.type))
|
||||
return
|
||||
|
||||
if obj.object_id != user.actor:
|
||||
logging.warning(
|
||||
"Follow object does not match actor: msg=%s, actor=%s",
|
||||
|
@ -104,6 +108,8 @@ async def handle_undo(request: Request, message: Message, user: User) -> None:
|
|||
|
||||
|
||||
async def process_message(request: Request, message: Message, user: User) -> None:
|
||||
print(f"process_message: {user.handle}, message:", message.to_json(4), flush = True)
|
||||
|
||||
if request.state.user.actor != message.actor_id:
|
||||
logging.warning(
|
||||
"Message actor and signature keyid do not match: msg=%s, actor=%s",
|
||||
|
@ -120,7 +126,7 @@ async def process_message(request: Request, message: Message, user: User) -> Non
|
|||
logging.error(error.response.read())
|
||||
|
||||
except KeyError:
|
||||
logging.debug("Unhandled message type: %s", message.type.name)
|
||||
logging.debug("Unhandled message type: %s", message.type)
|
||||
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
|
|
|
@ -59,15 +59,19 @@ async def handle_instance_actor_get(request: Request) -> Response:
|
|||
async def handle_instance_actor_post(request: Request) -> Response:
|
||||
ensure_signed(request)
|
||||
|
||||
return Response(202, "UvU")
|
||||
with request.app.state.database.session(False) as s:
|
||||
if (user := s.get_user(request.app.state.config.host)) is None:
|
||||
raise HttpError(404, "User not found")
|
||||
|
||||
message = Message.parse(await request.body())
|
||||
asyncio.create_task(process_message(request, message, user))
|
||||
return Response(200, "uvu")
|
||||
|
||||
|
||||
@router.get("BarksharkSocial", "/relay")
|
||||
async def handle_relay_get(request: Request) -> Response:
|
||||
config = request.app.state.config
|
||||
|
||||
with request.app.state.database.session(False) as s:
|
||||
if (user := s.get_user("relay", config.host)) is None:
|
||||
if (user := s.get_user("relay")) is None:
|
||||
raise HttpError(404, "User not found")
|
||||
|
||||
data = Message.new_actor(
|
||||
|
@ -87,7 +91,13 @@ async def handle_relay_get(request: Request) -> Response:
|
|||
async def handle_relay_post(request: Request) -> Response:
|
||||
ensure_signed(request)
|
||||
|
||||
return Response(202, "UvU")
|
||||
with request.app.state.database.session(False) as s:
|
||||
if (user := s.get_user("relay")) is None:
|
||||
raise HttpError(404, "User not found")
|
||||
|
||||
message = Message.parse(await request.body())
|
||||
asyncio.create_task(process_message(request, message, user))
|
||||
return Response(200, "uvu")
|
||||
|
||||
|
||||
@router.get("BarksharkSocial", "/user/{username}")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from aputils import HttpDate
|
||||
from argon2.exceptions import VerifyMismatchError
|
||||
from basgi import HttpError, FileResponse, Request, Response, TemplateResponse, router
|
||||
from blib import HttpDate
|
||||
from datetime import timedelta
|
||||
|
||||
from ..misc import get_resource
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import aputils
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from aputils import Signer, register_validator
|
||||
from argon2 import PasswordHasher
|
||||
from bsql import Database
|
||||
from pathlib import Path
|
||||
|
@ -126,8 +126,8 @@ class Application(App[Request, RequestState, AppState]):
|
|||
return context
|
||||
|
||||
|
||||
@aputils.register_validator(Request)
|
||||
async def handle_validate_request(signer: aputils.Signer, request: Request) -> bool:
|
||||
@register_validator(Request)
|
||||
async def handle_validate_request(signer: Signer, request: Request) -> bool:
|
||||
return signer.validate_signature(
|
||||
request.method,
|
||||
request.path,
|
||||
|
|
5
dev.py
5
dev.py
|
@ -130,13 +130,8 @@ def cli_update_files() -> None:
|
|||
|
||||
|
||||
@cli.command("exec", context_settings = {"allow_extra_args": True})
|
||||
@option("--watch", "-w", is_flag = True)
|
||||
@pass_context
|
||||
def cli_run(ctx: Context, watch: bool = False) -> None:
|
||||
if watch:
|
||||
handle_run_watcher("-m", "barkshark_social", *ctx.args)
|
||||
return
|
||||
|
||||
run_python("-m", "barkshark_social", *ctx.args)
|
||||
|
||||
|
||||
|
|
|
@ -39,10 +39,12 @@ dependencies = [
|
|||
"argon2-cffi == 23.1.0",
|
||||
"barkshark-sql == 0.1.3",
|
||||
"click == 8.1.7",
|
||||
"itsdangerous == 2.1.2",
|
||||
"pymemcache == 4.0.0",
|
||||
"pyyaml == 6.0.1",
|
||||
"uvicorn[standard] == 0.29.0"
|
||||
"uvicorn[standard] == 0.29.0",
|
||||
|
||||
"barkshark-asgi @ https://git.barkshark.xyz/barkshark/basgi/archive/main.tar.gz",
|
||||
"barkshark-lib @ https://git.barkshark.xyz/barkshark/blib/archive/main.tar.gz"
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
|
|
Loading…
Reference in a new issue