|
@@ -20,90 +20,61 @@ from misago.users.audittrail import create_user_audit_trail
|
|
from misago.users.signatures import is_user_signature_valid
|
|
from misago.users.signatures import is_user_signature_valid
|
|
from misago.users.utils import hash_email
|
|
from misago.users.utils import hash_email
|
|
|
|
|
|
|
|
+from .online import Online
|
|
from .rank import Rank
|
|
from .rank import Rank
|
|
|
|
|
|
|
|
|
|
class UserManager(BaseUserManager):
|
|
class UserManager(BaseUserManager):
|
|
- @transaction.atomic
|
|
|
|
- def create_user(
|
|
|
|
- self, username, email, password=None, create_audit_trail=False,
|
|
|
|
- joined_from_ip=None, set_default_avatar=False, **extra_fields
|
|
|
|
- ):
|
|
|
|
- from misago.users.validators import validate_email, validate_username
|
|
|
|
-
|
|
|
|
- email = self.normalize_email(email)
|
|
|
|
- username = self.model.normalize_username(username)
|
|
|
|
-
|
|
|
|
|
|
+ def _create_user(self, username, email, password, **extra_fields):
|
|
|
|
+ """
|
|
|
|
+ Create and save a user with the given username, email, and password.
|
|
|
|
+ """
|
|
|
|
+ if not username:
|
|
|
|
+ raise ValueError("User must have an username.")
|
|
if not email:
|
|
if not email:
|
|
- raise ValueError(_("User must have an email address."))
|
|
|
|
-
|
|
|
|
- WATCH_DICT = {
|
|
|
|
- 'no': self.model.SUBSCRIBE_NONE,
|
|
|
|
- 'watch': self.model.SUBSCRIBE_NOTIFY,
|
|
|
|
- 'watch_email': self.model.SUBSCRIBE_ALL,
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if not 'subscribe_to_started_threads' in extra_fields:
|
|
|
|
- new_value = WATCH_DICT[settings.subscribe_start]
|
|
|
|
- extra_fields['subscribe_to_started_threads'] = new_value
|
|
|
|
-
|
|
|
|
- if not 'subscribe_to_replied_threads' in extra_fields:
|
|
|
|
- new_value = WATCH_DICT[settings.subscribe_reply]
|
|
|
|
- extra_fields['subscribe_to_replied_threads'] = new_value
|
|
|
|
-
|
|
|
|
- extra_fields.update({'is_staff': False, 'is_superuser': False})
|
|
|
|
-
|
|
|
|
- now = timezone.now()
|
|
|
|
- user = self.model(
|
|
|
|
- last_login=now,
|
|
|
|
- joined_on=now,
|
|
|
|
- joined_from_ip=joined_from_ip,
|
|
|
|
- **extra_fields
|
|
|
|
- )
|
|
|
|
|
|
+ raise ValueError("User must have an email address.")
|
|
|
|
|
|
|
|
+ user = self.model(**extra_fields)
|
|
user.set_username(username)
|
|
user.set_username(username)
|
|
user.set_email(email)
|
|
user.set_email(email)
|
|
user.set_password(password)
|
|
user.set_password(password)
|
|
|
|
|
|
- validate_username(username)
|
|
|
|
- validate_email(email)
|
|
|
|
-
|
|
|
|
if not 'rank' in extra_fields:
|
|
if not 'rank' in extra_fields:
|
|
user.rank = Rank.objects.get_default()
|
|
user.rank = Rank.objects.get_default()
|
|
|
|
|
|
|
|
+ now = timezone.now()
|
|
|
|
+ user.last_login=now
|
|
|
|
+ user.joined_on=now
|
|
|
|
+
|
|
user.save(using=self._db)
|
|
user.save(using=self._db)
|
|
|
|
+ self._assert_user_has_authenticated_role(user)
|
|
|
|
|
|
- if set_default_avatar:
|
|
|
|
- avatars.set_default_avatar(
|
|
|
|
- user, settings.default_avatar, settings.default_gravatar_fallback
|
|
|
|
- )
|
|
|
|
- else:
|
|
|
|
- # just for test purposes
|
|
|
|
- user.avatars = [{'size': 400, 'url': 'http://placekitten.com/400/400'}]
|
|
|
|
|
|
+ Online.objects.create(user=user, last_click=now)
|
|
|
|
|
|
|
|
+ return user
|
|
|
|
+
|
|
|
|
+ def _assert_user_has_authenticated_role(self, user):
|
|
authenticated_role = Role.objects.get(special_role='authenticated')
|
|
authenticated_role = Role.objects.get(special_role='authenticated')
|
|
if authenticated_role not in user.roles.all():
|
|
if authenticated_role not in user.roles.all():
|
|
user.roles.add(authenticated_role)
|
|
user.roles.add(authenticated_role)
|
|
user.update_acl_key()
|
|
user.update_acl_key()
|
|
|
|
+ user.save(update_fields=['acl_key'])
|
|
|
|
|
|
- user.save(update_fields=['avatars', 'acl_key'])
|
|
|
|
|
|
+ def create_user(self, username, email=None, password=None, **extra_fields):
|
|
|
|
+ extra_fields.setdefault('is_staff', False)
|
|
|
|
+ extra_fields.setdefault('is_superuser', False)
|
|
|
|
+ return self._create_user(username, email, password, **extra_fields)
|
|
|
|
|
|
- if create_audit_trail:
|
|
|
|
- create_user_audit_trail(user, user.joined_from_ip, user)
|
|
|
|
|
|
+ def create_superuser(self, username, email, password=None, **extra_fields):
|
|
|
|
+ extra_fields.setdefault('is_staff', True)
|
|
|
|
+ extra_fields.setdefault('is_superuser', True)
|
|
|
|
|
|
- # populate online tracker with default value
|
|
|
|
- Online.objects.create(user=user, last_click=now)
|
|
|
|
|
|
+ if extra_fields.get('is_staff') is not True:
|
|
|
|
+ raise ValueError('Superuser must have is_staff=True.')
|
|
|
|
+ if extra_fields.get('is_superuser') is not True:
|
|
|
|
+ raise ValueError('Superuser must have is_superuser=True.')
|
|
|
|
|
|
- return user
|
|
|
|
-
|
|
|
|
- @transaction.atomic
|
|
|
|
- def create_superuser(self, username, email, password, set_default_avatar=False):
|
|
|
|
- user = self.create_user(
|
|
|
|
- username,
|
|
|
|
- email,
|
|
|
|
- password=password,
|
|
|
|
- set_default_avatar=set_default_avatar,
|
|
|
|
- )
|
|
|
|
|
|
+ user = self._create_user(username, email, password, **extra_fields)
|
|
|
|
|
|
try:
|
|
try:
|
|
user.rank = Rank.objects.get(name=_("Forum team"))
|
|
user.rank = Rank.objects.get(name=_("Forum team"))
|
|
@@ -111,11 +82,6 @@ class UserManager(BaseUserManager):
|
|
except Rank.DoesNotExist:
|
|
except Rank.DoesNotExist:
|
|
pass
|
|
pass
|
|
|
|
|
|
- user.is_staff = True
|
|
|
|
- user.is_superuser = True
|
|
|
|
-
|
|
|
|
- updated_fields = ('rank', 'acl_key', 'is_staff', 'is_superuser')
|
|
|
|
- user.save(update_fields=updated_fields, using=self._db)
|
|
|
|
return user
|
|
return user
|
|
|
|
|
|
def get_by_username(self, username):
|
|
def get_by_username(self, username):
|
|
@@ -135,14 +101,14 @@ class User(AbstractBaseUser, PermissionsMixin):
|
|
ACTIVATION_USER = 1
|
|
ACTIVATION_USER = 1
|
|
ACTIVATION_ADMIN = 2
|
|
ACTIVATION_ADMIN = 2
|
|
|
|
|
|
- SUBSCRIBE_NONE = 0
|
|
|
|
- SUBSCRIBE_NOTIFY = 1
|
|
|
|
- SUBSCRIBE_ALL = 2
|
|
|
|
|
|
+ SUBSCRIPTION_NONE = 0
|
|
|
|
+ SUBSCRIPTION_NOTIFY = 1
|
|
|
|
+ SUBSCRIPTION_ALL = 2
|
|
|
|
|
|
- SUBSCRIBE_CHOICES = [
|
|
|
|
- (SUBSCRIBE_NONE, _("No")),
|
|
|
|
- (SUBSCRIBE_NOTIFY, _("Notify")),
|
|
|
|
- (SUBSCRIBE_ALL, _("Notify with e-mail")),
|
|
|
|
|
|
+ SUBSCRIPTION_CHOICES = [
|
|
|
|
+ (SUBSCRIPTION_NONE, _("No")),
|
|
|
|
+ (SUBSCRIPTION_NOTIFY, _("Notify")),
|
|
|
|
+ (SUBSCRIPTION_ALL, _("Notify with e-mail")),
|
|
]
|
|
]
|
|
|
|
|
|
LIMIT_INVITES_TO_NONE = 0
|
|
LIMIT_INVITES_TO_NONE = 0
|
|
@@ -252,12 +218,12 @@ class User(AbstractBaseUser, PermissionsMixin):
|
|
sync_unread_private_threads = models.BooleanField(default=False)
|
|
sync_unread_private_threads = models.BooleanField(default=False)
|
|
|
|
|
|
subscribe_to_started_threads = models.PositiveIntegerField(
|
|
subscribe_to_started_threads = models.PositiveIntegerField(
|
|
- default=SUBSCRIBE_NONE,
|
|
|
|
- choices=SUBSCRIBE_CHOICES,
|
|
|
|
|
|
+ default=SUBSCRIPTION_NONE,
|
|
|
|
+ choices=SUBSCRIPTION_CHOICES,
|
|
)
|
|
)
|
|
subscribe_to_replied_threads = models.PositiveIntegerField(
|
|
subscribe_to_replied_threads = models.PositiveIntegerField(
|
|
- default=SUBSCRIBE_NONE,
|
|
|
|
- choices=SUBSCRIBE_CHOICES,
|
|
|
|
|
|
+ default=SUBSCRIPTION_NONE,
|
|
|
|
+ choices=SUBSCRIPTION_CHOICES,
|
|
)
|
|
)
|
|
|
|
|
|
threads = models.PositiveIntegerField(default=0)
|
|
threads = models.PositiveIntegerField(default=0)
|
|
@@ -466,22 +432,6 @@ class User(AbstractBaseUser, PermissionsMixin):
|
|
return False
|
|
return False
|
|
|
|
|
|
|
|
|
|
-class Online(models.Model):
|
|
|
|
- user = models.OneToOneField(
|
|
|
|
- settings.AUTH_USER_MODEL,
|
|
|
|
- primary_key=True,
|
|
|
|
- related_name='online_tracker',
|
|
|
|
- on_delete=models.CASCADE,
|
|
|
|
- )
|
|
|
|
- last_click = models.DateTimeField(default=timezone.now)
|
|
|
|
-
|
|
|
|
- def save(self, *args, **kwargs):
|
|
|
|
- try:
|
|
|
|
- super().save(*args, **kwargs)
|
|
|
|
- except IntegrityError:
|
|
|
|
- pass # first come is first serve in online tracker
|
|
|
|
-
|
|
|
|
-
|
|
|
|
class UsernameChange(models.Model):
|
|
class UsernameChange(models.Model):
|
|
user = models.ForeignKey(
|
|
user = models.ForeignKey(
|
|
settings.AUTH_USER_MODEL,
|
|
settings.AUTH_USER_MODEL,
|