Skip to content
Snippets Groups Projects
Verified Commit 4f83d1bb authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Added API endpoint to query profiles

parent 8203fa01
No related branches found
No related tags found
No related merge requests found
from django.conf.urls import url
from channels.routing import ProtocolTypeRouter, URLRouter
from retribute_api.search import consumers
application = ProtocolTypeRouter(
{
"http": URLRouter(
[
url(
r"^api/v1/search/(?P<lookup_type>.+):(?P<lookup>.+)$",
consumers.SearchSingleConsumer,
)
]
)
}
)
import aiohttp.client
import json
from channels.generic.http import AsyncHttpConsumer
from . import sources
async def json_response(self, status, content):
await self.send_response(
status,
json.dumps(content, indent=2, sort_keys=True).encode("utf-8"),
headers=[{"Content-Type": "application/json"}],
)
class SearchSingleConsumer(AsyncHttpConsumer):
async def handle(self, body):
lookup_type = self.scope["url_route"]["kwargs"]["lookup_type"]
lookup = self.scope["url_route"]["kwargs"]["lookup"]
try:
source = sources.registry._data[lookup_type]
except KeyError:
await json_response(self, 400, {"detail": "Invalid lookup"})
try:
async with aiohttp.client.ClientSession() as session:
data = await source.get(lookup, session)
except Exception:
raise
try:
profile = sources.result_to_retribute_profile(lookup_type, lookup, data)
except Exception:
raise
await json_response(self, 200, profile)
......@@ -34,11 +34,11 @@ class Activitypub(Source):
id = "activitypub"
async def get(self, lookup, session):
response = await session.get(
async with session.get(
lookup, headers={"Accept": "application/activity+json"}
)
response.raise_for_status()
actor_data = await response.json()
) as response:
response.raise_for_status()
actor_data = await response.json()
serializer = activitypub.ActorSerializer(data=actor_data)
serializer.is_valid(raise_exception=True)
for tag in serializer.validated_data["tag"]:
......@@ -64,12 +64,11 @@ class Webfinger(Source):
found = None
if "activitypub" in links:
found = await Activitypub().get(links["activitypub"], session)
return found
def result_to_retribute_profile(lookup_type, lookup, data):
path = settings.BASE_URL + "/compat/"
path = settings.BASE_URL + "/compat"
now = timezone.now()
valid_means = [
(link, means.extract_from_url(link["url"])) for link in data["links"]
......@@ -89,7 +88,7 @@ def result_to_retribute_profile(lookup_type, lookup, data):
final = {
"version": "0.1",
"id": "https://retribute.me.test/compat/{}:{}".format(lookup_type, lookup),
"id": "{}/{}:{}".format(path, lookup_type, lookup),
"title": "Compat profile for {}:{}".format(lookup_type, lookup),
"updated": now.isoformat(),
"identities": [],
......
......@@ -3,12 +3,12 @@ from rest_framework import serializers
async def lookup(name, session):
username, domain = name.split("@")
response = await session.get(
async with session.get(
"https://{}/.well-known/webfinger".format(domain),
params={"resource": "acct:{}".format(name)},
)
response.raise_for_status()
return await response.json()
) as response:
response.raise_for_status()
return await response.json()
class AccountLinkSerializer(serializers.Serializer):
......
......@@ -5,6 +5,7 @@ import asynctest
from django.utils import timezone
from config import routing
pytest_plugins = "aiohttp.pytest_plugin"
......@@ -31,3 +32,8 @@ def now(mocker):
now = timezone.now()
mocker.patch.object(timezone, "now", return_value=now)
return now
@pytest.fixture
def application():
return routing.application
import json
from channels.testing import HttpCommunicator
from retribute_api.search import consumers
from retribute_api.search import sources
async def test_search_consumer_success(loop, application, mocker, coroutine_mock):
get = mocker.patch.object(sources.Webfinger, "get", coroutine_mock())
expected = {"dummy": "json"}
get_profile = mocker.patch.object(
sources, "result_to_retribute_profile", return_value=expected
)
communicator = HttpCommunicator(
application, "GET", "/api/v1/search/webfinger:test@user.domain"
)
response = await communicator.get_response()
assert get.call_args[0][0] == "test@user.domain"
get_profile.assert_called_once_with(
"webfinger", "test@user.domain", get.return_value
)
assert response["status"] == 200
assert response["headers"] == [{"Content-Type": "application/json"}]
assert response["body"] == json.dumps(expected, indent=2, sort_keys=True).encode()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment