def public_register(username, password, email, full_name): """ Given a parsed parameters, try register a new user knowing that it follows a public register flow. This can raise `exc.IntegrityError` exceptions in case of conflics found. :returns: User """ is_registered, reason = is_user_already_registered(username=username, email=email) if is_registered: raise exc.WrongArguments(reason) user_model = get_user_model() user = user_model(username=username, email=email, full_name=full_name) user.set_password(password) try: user.save() except IntegrityError: raise exc.WrongArguments(_("User is already registered.")) send_register_email(user) user_registered_signal.send(sender=user.__class__, user=user) return user
def change_email(self, request, pk=None): """ Verify the email change to current logged user. """ validator = serializers.ChangeEmailValidator(data=request.data, many=False) if not validator.is_valid(): raise exc.WrongArguments( _("Invalid, are you sure the token is correct and you " "didn't use it before?")) try: user = models.User.objects.get( email_token=validator.data["email_token"]) except models.User.DoesNotExist: raise exc.WrongArguments( _("Invalid, are you sure the token is correct and you " "didn't use it before?")) old_email = user.email new_email = user.new_email user.email = new_email user.new_email = None user.email_token = None user.save(update_fields=["email", "new_email", "email_token"]) user_change_email_signal.send(sender=user.__class__, user=user, old_email=old_email, new_email=new_email) return response.NoContent()
def cancel(self, request, pk=None): """ Cancel an account via token """ validator = serializers.CancelAccountValidator(data=request.data, many=False) if not validator.is_valid(): raise exc.WrongArguments( _("Invalid, are you sure the token is correct?")) try: max_age_cancel_account = getattr(settings, "MAX_AGE_CANCEL_ACCOUNT", None) user = get_user_for_token(validator.data["cancel_token"], "cancel_account", max_age=max_age_cancel_account) except exc.NotAuthenticated: raise exc.WrongArguments( _("Invalid, are you sure the token is correct?")) if not user.is_active: raise exc.WrongArguments( _("Invalid, are you sure the token is correct?")) user.cancel() return response.NoContent()
def change_avatar(self, request): """ Change avatar to current logged user. """ avatar = request.FILES.get('avatar', None) id = request.data.get('id', None) if not avatar: raise exc.WrongArguments(_("Incomplete arguments")) try: pil_image(avatar) except Exception: raise exc.WrongArguments(_("Invalid image format")) if id is None: request.user.photo = avatar request.user.save(update_fields=["photo"]) user_data = self.admin_serializer_class(request.user).data else: user = get_object_or_404(models.User, id=id) user.photo = avatar user.save(update_fields=["photo"]) user_data = self.admin_serializer_class(user).data return response.Ok(user_data)
def change_password(self, request, pk=None): """ Change password to current logged user. """ current_password = request.data.get("current_password") password = request.data.get("password") if not current_password: raise exc.WrongArguments(_("Current password parameter needed")) if not password: raise exc.WrongArguments(_("New password parameter needed")) if len(password) < 6: raise exc.WrongArguments( _("Invalid password length at least 6 charaters needed")) if current_password and not request.user.check_password( current_password): raise exc.WrongArguments(_("Invalid current password")) request.user.set_password(password) request.user.save(update_fields=["password"]) return response.NoContent()
def change_password_from_recovery(self, request, pk=None): """ Change password with token (from password recovery step). """ validator = serializers.RecoveryValidator(data=request.data, many=False) if not validator.is_valid(): raise exc.WrongArguments(_("Token is invalid")) try: user = models.User.objects.get(token=validator.data["token"]) except models.User.DoesNotExist: raise exc.WrongArguments(_("Token is invalid")) user.set_password(validator.data["password"]) user.token = None user.save(update_fields=["password", "token"]) return response.NoContent()
def get_and_validate_user(*, username: str, password: str) -> bool: """ Check if user with username/email exists and specified password matchs well with existing user password. if user is valid, user is returned else, corresponding exception is raised. """ user = get_user_by_username_or_email(username) if not user.check_password(password): raise exc.WrongArguments( _("Username or password does not match user.")) return user
def password_recovery(self, request, pk=None): username_or_email = request.data.get('username', None) if not username_or_email: raise exc.WrongArguments(_("Invalid username or email")) user = get_user_by_username_or_email(username_or_email) user.token = str(uuid.uuid1()) user.save(update_fields=["token"]) email = mail_builder.password_recovery(user, {"user": user}) email.send() return response.Ok( {"detail": _("A Mail has been sent to you successful!")})
def partial_update(self, request, *args, **kwargs): """ We must detect if the user is trying to change his email so we can save that value and generate a token that allows him to validate it in the new email account """ new_email = request.data.pop('email', None) if new_email is not None: valid_new_email = True duplicated_email = models.User.objects.filter( email=new_email).exists() try: validate_email(new_email) self.validate_user_email_allowed_domains(new_email) except ValidationError: valid_new_email = False valid_new_email = valid_new_email and new_email != request.user.email if duplicated_email: raise exc.WrongArguments(_("Duplicated email")) elif not valid_new_email: raise exc.WrongArguments(_("Not valid email")) # We need to generate a token for the email request.user.email_token = str(uuid.uuid1()) request.user.new_email = new_email request.user.save(update_fields=["email_token", "new_email"]) email = mail_builder.change_email(request.user.new_email, {"user": request.user}) email.send() return super().partial_update(request, *args, **kwargs)
def get_user_by_username_or_email(username_or_email): user_model = get_user_model() qs = user_model.objects.filter( Q(username__iexact=username_or_email) | Q(email__iexact=username_or_email)) if len(qs) > 1: qs = qs.filter( Q(username=username_or_email) | Q(email=username_or_email)) if len(qs) == 0: raise exc.WrongArguments( _("Username or password does not match user.")) user = qs[0] return user