add barkshark-lib dep

This commit is contained in:
Izalia Mae 2024-04-18 22:36:06 -04:00
parent 848350684f
commit 026f5bd11d
15 changed files with 74 additions and 86 deletions

View file

@ -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,

View file

@ -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())

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -1,4 +1,4 @@
from aputils import IntEnum, StrEnum
from blib import IntEnum, StrEnum
class PermissionLevel(IntEnum):

View file

@ -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}}

View file

@ -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

View file

@ -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]

View file

@ -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()

View file

@ -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}")

View file

@ -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

View file

@ -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
View file

@ -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)

View file

@ -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]