Compare commits
2 commits
048c8927b8
...
d75ae86409
Author | SHA1 | Date | |
---|---|---|---|
d75ae86409 | |||
7bf70c933b |
7 changed files with 65 additions and 45 deletions
|
@ -1,6 +1,5 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.auth.admin import UserAdmin
|
|
||||||
|
|
||||||
from userausfall.models import User
|
from userausfall.models import User
|
||||||
|
|
||||||
admin.site.register(User, UserAdmin)
|
admin.site.register(User)
|
||||||
|
|
21
userausfall/ldap.py
Normal file
21
userausfall/ldap.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
from django.conf import settings
|
||||||
|
from ldap3 import Server, Connection, SYNC
|
||||||
|
|
||||||
|
|
||||||
|
def create_account(username, raw_password):
|
||||||
|
server = Server("localhost")
|
||||||
|
# The SAFE_SYNC client strategy doesn't seem to be present in Buster version of ldap3. We might want to use it as
|
||||||
|
# soon as it is available (multithreading).
|
||||||
|
connection = Connection(
|
||||||
|
server,
|
||||||
|
settings.USERAUSFALL_LDAP["ADMIN_USER_DN"],
|
||||||
|
settings.USERAUSFALL_LDAP["ADMIN_USER_PASSWORD"],
|
||||||
|
client_strategy=SYNC,
|
||||||
|
auto_bind=True,
|
||||||
|
)
|
||||||
|
is_success = connection.add(
|
||||||
|
f"cn={username},dc=local",
|
||||||
|
["simpleSecurityObject", "organizationalRole"],
|
||||||
|
{"userPassword": raw_password},
|
||||||
|
)
|
||||||
|
return is_success
|
16
userausfall/migrations/0005_delete_accountrequest.py
Normal file
16
userausfall/migrations/0005_delete_accountrequest.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# Generated by Django 2.2.20 on 2021-05-19 08:10
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('userausfall', '0004_user_confidant'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='AccountRequest',
|
||||||
|
),
|
||||||
|
]
|
|
@ -6,6 +6,18 @@ from django.db import models
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from userausfall import ldap
|
||||||
|
|
||||||
|
|
||||||
|
class MissingUserAttribute(Exception):
|
||||||
|
"""The user object is missing a required attribute."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordMismatch(Exception):
|
||||||
|
"""The given password does not match the user's password."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class UserManager(BaseUserManager):
|
class UserManager(BaseUserManager):
|
||||||
use_in_migrations = True
|
use_in_migrations = True
|
||||||
|
@ -51,22 +63,12 @@ class User(AbstractBaseUser, PermissionsMixin):
|
||||||
},
|
},
|
||||||
blank=True,
|
blank=True,
|
||||||
)
|
)
|
||||||
first_name = models.CharField(_('first name'), max_length=30, blank=True)
|
|
||||||
last_name = models.CharField(_('last name'), max_length=150, blank=True)
|
|
||||||
email = models.EmailField(_('email address'), unique=True, blank=True)
|
email = models.EmailField(_('email address'), unique=True, blank=True)
|
||||||
is_staff = models.BooleanField(
|
is_staff = models.BooleanField(
|
||||||
_('staff status'),
|
_('staff status'),
|
||||||
default=False,
|
default=False,
|
||||||
help_text=_('Designates whether the user can log into this admin site.'),
|
help_text=_('Designates whether the user can log into this admin site.'),
|
||||||
)
|
)
|
||||||
is_active = models.BooleanField(
|
|
||||||
_('active'),
|
|
||||||
default=True,
|
|
||||||
help_text=_(
|
|
||||||
'Designates whether this user should be treated as active. '
|
|
||||||
'Unselect this instead of deleting accounts.'
|
|
||||||
),
|
|
||||||
)
|
|
||||||
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
|
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
|
||||||
confidant = models.ForeignKey("User", on_delete=models.SET_NULL, null=True)
|
confidant = models.ForeignKey("User", on_delete=models.SET_NULL, null=True)
|
||||||
|
|
||||||
|
@ -87,29 +89,16 @@ class User(AbstractBaseUser, PermissionsMixin):
|
||||||
def get_confidant_email(self):
|
def get_confidant_email(self):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def get_full_name(self):
|
|
||||||
"""
|
|
||||||
Return the first_name plus the last_name, with a space in between.
|
|
||||||
"""
|
|
||||||
full_name = '%s %s' % (self.first_name, self.last_name)
|
|
||||||
return full_name.strip()
|
|
||||||
|
|
||||||
def get_short_name(self):
|
|
||||||
"""Return the short name for the user."""
|
|
||||||
return self.first_name
|
|
||||||
|
|
||||||
def email_user(self, subject, message, from_email=None, **kwargs):
|
def email_user(self, subject, message, from_email=None, **kwargs):
|
||||||
"""Send an email to this user."""
|
"""Send an email to this user."""
|
||||||
send_mail(subject, message, from_email, [self.email], **kwargs)
|
send_mail(subject, message, from_email, [self.email], **kwargs)
|
||||||
|
|
||||||
|
def create_ldap_account(self, raw_password):
|
||||||
class AccountRequest(models.Model):
|
"""Create the LDAP account which corresponds to this user."""
|
||||||
created_time = models.DateTimeField(auto_now_add=True)
|
if not self.username:
|
||||||
|
raise MissingUserAttribute("User is missing a username.")
|
||||||
email = models.EmailField()
|
if not self.confidant:
|
||||||
is_verified = models.BooleanField(default=False)
|
raise MissingUserAttribute("User is missing a confirmed confidant.")
|
||||||
|
if not self.check_password(raw_password):
|
||||||
confidant_email = models.EmailField(blank=True)
|
raise PasswordMismatch("The given password does not match the user's password.")
|
||||||
is_trustable = models.BooleanField(default=False)
|
return ldap.create_account(self.username, raw_password)
|
||||||
|
|
||||||
username = models.CharField(max_length=100, blank=True)
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from userausfall.models import AccountRequest, User
|
from userausfall.models import User
|
||||||
|
|
||||||
|
|
||||||
class UserSerializer(serializers.ModelSerializer):
|
class UserSerializer(serializers.ModelSerializer):
|
||||||
|
|
|
@ -149,3 +149,8 @@ REST_FRAMEWORK = {
|
||||||
'rest_framework.authentication.SessionAuthentication',
|
'rest_framework.authentication.SessionAuthentication',
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
USERAUSFALL_LDAP = {
|
||||||
|
'ADMIN_USER_DN': 'cn=admin,dc=local',
|
||||||
|
'ADMIN_USER_PASSWORD': os.environ.get('USERAUSFALL_LDAP_PASSWORD'),
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
from django.db.models.signals import post_save
|
|
||||||
from django.dispatch import receiver
|
|
||||||
|
|
||||||
from userausfall.models import AccountRequest
|
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=AccountRequest)
|
|
||||||
def account_request_saved(sender, instance: AccountRequest, **kwargs):
|
|
||||||
if instance.is_verified and instance.is_trustable and instance.username:
|
|
||||||
print('Create account and send password mail')
|
|
Reference in a new issue