Implement LDAP authentication

This commit is contained in:
Joshua M. Boniface 2018-08-22 18:10:39 +00:00 committed by Eliot Berriot
parent 6ed5740f6f
commit 4ce46ff2a0
17 changed files with 232 additions and 15 deletions

View file

@ -1,3 +1,5 @@
import unicodedata
import re
from django.conf import settings
@ -32,3 +34,21 @@ def clean_wsgi_headers(raw_headers):
cleaned[cleaned_header] = value
return cleaned
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)

View file

@ -33,7 +33,7 @@ class FederationMixin(object):
class ActorViewSet(FederationMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
lookup_field = "user__username"
lookup_field = "preferred_username"
lookup_value_regex = ".*"
authentication_classes = [authentication.SignatureAuthentication]
permission_classes = []
@ -136,7 +136,7 @@ class WellKnownViewSet(viewsets.GenericViewSet):
actor = actors.SYSTEM_ACTORS[username].get_actor_instance()
else:
try:
actor = models.Actor.objects.local().get(user__username=username)
actor = models.Actor.objects.local().get(preferred_username=username)
except models.Actor.DoesNotExist:
raise forms.ValidationError("Invalid username")

View file

@ -17,6 +17,7 @@ from django.utils import timezone
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from django_auth_ldap.backend import populate_user as ldap_populate_user
from versatileimagefield.fields import VersatileImageField
from versatileimagefield.image_warmer import VersatileImageFieldWarmer
@ -220,25 +221,25 @@ class Invitation(models.Model):
def create_actor(user):
username = user.username
username = federation_utils.slugify_username(user.username)
private, public = keys.get_key_pair()
args = {
"preferred_username": username,
"domain": settings.FEDERATION_HOSTNAME,
"type": "Person",
"name": username,
"name": user.username,
"manually_approves_followers": False,
"url": federation_utils.full_url(
reverse("federation:actors-detail", kwargs={"user__username": username})
reverse("federation:actors-detail", kwargs={"preferred_username": username})
),
"shared_inbox_url": federation_utils.full_url(
reverse("federation:actors-inbox", kwargs={"user__username": username})
reverse("federation:actors-inbox", kwargs={"preferred_username": username})
),
"inbox_url": federation_utils.full_url(
reverse("federation:actors-inbox", kwargs={"user__username": username})
reverse("federation:actors-inbox", kwargs={"preferred_username": username})
),
"outbox_url": federation_utils.full_url(
reverse("federation:actors-outbox", kwargs={"user__username": username})
reverse("federation:actors-outbox", kwargs={"preferred_username": username})
),
}
args["private_key"] = private.decode("utf-8")
@ -247,6 +248,12 @@ def create_actor(user):
return federation_models.Actor.objects.create(**args)
@receiver(ldap_populate_user)
def init_ldap_user(sender, user, ldap_user, **kwargs):
if not user.actor:
user.actor = create_actor(user)
@receiver(models.signals.post_save, sender=User)
def warm_user_avatar(sender, instance, **kwargs):
if not instance.avatar: