2018-08-22 18:10:39 +00:00
|
|
|
import unicodedata
|
|
|
|
import re
|
2018-03-28 22:00:01 +00:00
|
|
|
from django.conf import settings
|
|
|
|
|
2018-09-06 18:35:02 +00:00
|
|
|
from funkwhale_api.common import session
|
|
|
|
|
|
|
|
from . import signing
|
|
|
|
|
2018-03-28 22:00:01 +00:00
|
|
|
|
|
|
|
def full_url(path):
|
|
|
|
"""
|
|
|
|
Given a relative path, return a full url usable for federation purpose
|
|
|
|
"""
|
2018-07-22 10:20:16 +00:00
|
|
|
if path.startswith("http://") or path.startswith("https://"):
|
|
|
|
return path
|
2018-03-28 22:00:01 +00:00
|
|
|
root = settings.FUNKWHALE_URL
|
2018-06-09 13:36:16 +00:00
|
|
|
if path.startswith("/") and root.endswith("/"):
|
2018-03-28 22:00:01 +00:00
|
|
|
return root + path[1:]
|
2018-06-09 13:36:16 +00:00
|
|
|
elif not path.startswith("/") and not root.endswith("/"):
|
|
|
|
return root + "/" + path
|
2018-03-28 22:00:01 +00:00
|
|
|
else:
|
|
|
|
return root + path
|
2018-03-31 16:39:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
def clean_wsgi_headers(raw_headers):
|
|
|
|
"""
|
|
|
|
Convert WSGI headers from CONTENT_TYPE to Content-Type notation
|
|
|
|
"""
|
|
|
|
cleaned = {}
|
2018-06-09 13:36:16 +00:00
|
|
|
non_prefixed = ["content_type", "content_length"]
|
2018-03-31 16:39:10 +00:00
|
|
|
for raw_header, value in raw_headers.items():
|
|
|
|
h = raw_header.lower()
|
2018-06-09 13:36:16 +00:00
|
|
|
if not h.startswith("http_") and h not in non_prefixed:
|
2018-03-31 16:39:10 +00:00
|
|
|
continue
|
|
|
|
|
2018-06-09 13:36:16 +00:00
|
|
|
words = h.replace("http_", "", 1).split("_")
|
|
|
|
cleaned_header = "-".join([w.capitalize() for w in words])
|
2018-03-31 16:39:10 +00:00
|
|
|
cleaned[cleaned_header] = value
|
|
|
|
|
|
|
|
return cleaned
|
2018-08-22 18:10:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def slugify_username(username):
|
|
|
|
"""
|
|
|
|
Given a username such as "hello M. world", returns a username
|
|
|
|
suitable for federation purpose (hello_M_world).
|
|
|
|
|
|
|
|
Preserves the original case.
|
|
|
|
|
|
|
|
Code is borrowed from django's slugify function.
|
|
|
|
"""
|
|
|
|
|
|
|
|
value = str(username)
|
|
|
|
value = (
|
|
|
|
unicodedata.normalize("NFKD", value).encode("ascii", "ignore").decode("ascii")
|
|
|
|
)
|
|
|
|
value = re.sub(r"[^\w\s-]", "", value).strip()
|
|
|
|
return re.sub(r"[-\s]+", "_", value)
|
2018-09-06 18:35:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
def retrieve(fid, actor=None, serializer_class=None, queryset=None):
|
|
|
|
if queryset:
|
|
|
|
try:
|
|
|
|
# queryset can also be a Model class
|
|
|
|
existing = queryset.filter(fid=fid).first()
|
|
|
|
except AttributeError:
|
|
|
|
existing = queryset.objects.filter(fid=fid).first()
|
|
|
|
if existing:
|
|
|
|
return existing
|
|
|
|
|
|
|
|
auth = (
|
|
|
|
None if not actor else signing.get_auth(actor.private_key, actor.private_key_id)
|
|
|
|
)
|
|
|
|
response = session.get_session().get(
|
|
|
|
fid,
|
|
|
|
auth=auth,
|
|
|
|
timeout=5,
|
|
|
|
verify=settings.EXTERNAL_REQUESTS_VERIFY_SSL,
|
|
|
|
headers={
|
|
|
|
"Accept": "application/activity+json",
|
|
|
|
"Content-Type": "application/activity+json",
|
|
|
|
},
|
|
|
|
)
|
|
|
|
response.raise_for_status()
|
|
|
|
data = response.json()
|
|
|
|
if not serializer_class:
|
|
|
|
return data
|
|
|
|
serializer = serializer_class(data=data)
|
|
|
|
serializer.is_valid(raise_exception=True)
|
|
|
|
return serializer.save()
|