pull/1/head
Thomas Sileo 2018-06-16 21:57:07 +02:00
rodzic 587e580755
commit bcf4d14326
7 zmienionych plików z 41 dodań i 21 usunięć

Wyświetl plik

@ -5,7 +5,7 @@ install:
- pip install -r requirements.txt
- pip install -r dev-requirements.txt
script:
# - mypy --ignore-missing-imports little_boxes
- mypy --ignore-missing-imports little_boxes
- flake8 little_boxes
- black --check .
- python -m pytest -vv --cov=little_boxes

Wyświetl plik

@ -3,7 +3,7 @@ import logging
logger = logging.getLogger(__name__)
def strtobool(s: str) -> bool:
def strtobool(s: str) -> bool: # pragma: no cover
if s in ["y", "yes", "true", "on", "1"]:
return True
if s in ["n", "no", "false", "off", "0"]:

Wyświetl plik

@ -367,7 +367,7 @@ class BaseActivity(object, metaclass=_ActivityMeta):
actor_id = self._actor_id(actor)
return Person(**BACKEND.fetch_iri(actor_id))
def _pre_post_to_outbox(self) -> None:
def _pre_post_to_outbox(self, as_actor: "Person") -> None:
raise NotImplementedError
def _post_to_outbox(
@ -407,7 +407,7 @@ class BaseActivity(object, metaclass=_ActivityMeta):
)
return
if BACKEND.inbox_get_by_iri(as_actor, self.id):
if BACKEND.inbox_check_duplicate(as_actor, self.id):
# The activity is already in the inbox
logger.info(f"received duplicate activity {self}, dropping it")
return
@ -438,7 +438,7 @@ class BaseActivity(object, metaclass=_ActivityMeta):
self.outbox_set_id(BACKEND.activity_url(obj_id), obj_id)
try:
self._pre_post_to_outbox()
self._pre_post_to_outbox(self.get_actor())
logger.debug(f"called pre post to outbox hook")
except NotImplementedError:
logger.debug("pre post to outbox hook not implemented")
@ -671,12 +671,12 @@ class Undo(BaseActivity):
except NotImplementedError:
pass
def _pre_post_to_outbox(self) -> None:
def _pre_post_to_outbox(self, as_actor: "Person") -> None:
"""Ensures an Undo activity references an activity owned by the instance."""
if BACKEND is None:
raise UninitializedBackendError
if not BACKEND.is_from_outbox(self):
if not BACKEND.is_from_outbox(as_actor, self):
raise NotFromOutboxError(f"object {self!r} is not owned by this instance")
def _post_to_outbox(
@ -774,6 +774,9 @@ class Announce(BaseActivity):
)
return
if BACKEND is None:
raise UninitializedBackendError
BACKEND.inbox_announce(as_actor, self)
def _undo_inbox(self, as_actor: "Person") -> None:
@ -789,6 +792,9 @@ class Announce(BaseActivity):
activity: ObjectType,
recipients: List[str],
) -> None:
if BACKEND is None:
raise UninitializedBackendError
BACKEND.outbox_announce(as_actor, self)
def _undo_outbox(self, as_actor: "Person") -> None:
@ -834,14 +840,14 @@ class Delete(BaseActivity):
BACKEND.inbox_delete(as_actor, self)
# FIXME(tsileo): handle the delete_threads here?
def _pre_post_to_outbox(self) -> None:
def _pre_post_to_outbox(self, as_actor: "Person") -> None:
"""Ensures the Delete activity references a activity from the outbox (i.e. owned by the instance)."""
if BACKEND is None:
raise UninitializedBackendError
obj = self._get_actual_object()
if not BACKEND.is_from_outbox(self):
if not BACKEND.is_from_outbox(as_actor, self):
raise NotFromOutboxError(
f'object {obj["id"]} is not owned by this instance'
)
@ -878,11 +884,11 @@ class Update(BaseActivity):
BACKEND.inbox_update(as_actor, self)
def _pre_post_to_outbox(self) -> None:
def _pre_post_to_outbox(self, as_actor: "Person") -> None:
if BACKEND is None:
raise UninitializedBackendError
if not BACKEND.is_from_outbox(self):
if not BACKEND.is_from_outbox(as_actor, self):
raise NotFromOutboxError(f"object {self!r} is not owned by this instance")
def _post_to_outbox(

Wyświetl plik

@ -1,5 +1,7 @@
import abc
import typing
import os
import binascii
import requests
@ -13,6 +15,10 @@ class Backend(abc.ABC):
def user_agent(self) -> str:
return f"Little Boxes {__version__} (+http://github.com/tsileo/little-boxes)"
def random_object_id(self) -> str:
"""Generates a random object ID."""
return binascii.hexlify(os.urandom(8)).decode("utf-8")
def fetch_json(self, url: str, **kwargs):
resp = requests.get(
url,
@ -21,6 +27,15 @@ class Backend(abc.ABC):
)
return resp
def is_from_outbox(self, as_actor: "ap.Person", activity: "ap.BaseActivity") -> bool:
return activity.get_actor().id == as_actor.id
@abc.abstractmethod
def post_to_remote_inbox(
self, as_actor: "ap.Person", payload_encoded: str, recp: str
) -> None:
pass # pragma: no cover
@abc.abstractmethod
def base_url(self) -> str:
pass # pragma: no cover
@ -29,6 +44,10 @@ class Backend(abc.ABC):
def fetch_iri(self, iri: str) -> "ap.ObjectType":
pass # pragma: no cover
@abc.abstractmethod
def inbox_check_duplicate(self, as_actor: "ap.Person", iri: str) -> bool:
pass # pragma: no cover
@abc.abstractmethod
def activity_url(self, obj_id: str) -> str:
pass # pragma: no cover

Wyświetl plik

@ -39,6 +39,9 @@ def mentionify(content: str) -> Tuple[str, List[Dict[str, str]]]:
for mention in re.findall(MENTION_REGEX, content):
_, username, domain = mention.split("@")
actor_url = get_actor_url(mention)
if not actor_url:
# FIXME(tsileo): raise an error?
continue
p = get_backend().fetch_iri(actor_url)
tags.append(dict(type="Mention", href=p["id"], name=mention))
link = f'<span class="h-card"><a href="{p["url"]}" class="u-url mention">@<span>{username}</span></a></span>'

Wyświetl plik

@ -55,7 +55,7 @@ def _verify_h(signed_string, signature, pubkey):
def _body_digest(body: str) -> str:
h = hashlib.new("sha256")
h.update(body)
h.update(body) # type: ignore
return "SHA-256=" + base64.b64encode(h.digest()).decode("utf-8")

Wyświetl plik

@ -67,10 +67,6 @@ class InMemBackend(Backend):
return calls
def random_object_id(self) -> str:
"""Generates a random object ID."""
return binascii.hexlify(os.urandom(8)).decode("utf-8")
def setup_actor(self, name, pusername):
"""Create a new actor in this backend."""
p = ap.Person(
@ -126,7 +122,7 @@ class InMemBackend(Backend):
return True
return False
def inbox_get_by_iri(
def inbox_check_duplicate(
self, as_actor: ap.Person, iri: str
) -> Optional[ap.BaseActivity]:
for activity in self.DB[as_actor.id]["inbox"]:
@ -194,10 +190,6 @@ class InMemBackend(Backend):
as_actor = ap.parse_activity(self.fetch_iri(recp.replace("/inbox", "")))
act.process_from_inbox(as_actor)
def is_from_outbox(self, activity: ap.BaseActivity) -> bool:
# return as_actor.id == activity.get_actor().id
return True # FIXME(tsileo): implement this
@track_call
def inbox_like(self, as_actor: ap.Person, activity: ap.Like) -> None:
pass