Пример #1
0
    def get(self):
        if self.request.get("token"):
            r = PasswordResetToken.get_by_id(self.request.get("token"))

            if r:
                user = User.get_by_id(r.email)
                self.tv["current_user"] = user.to_object()
                self.tv["token"] = self.request.get("token")
                self.render("frontend/reset-password.html")
            else:
                self.redirect('/password/reset?error='+ urllib.quote('Invalid Token.'))
        else:
            self.render("frontend/reset-password.html")
Пример #2
0
    def post(self):
        if self.request.get("password_original") == self.request.get("password_retype"):
            if self.request.get("email"):
                user = User.get_by_id(self.request.get("email"))
                user.password = hash_password(self.request.get("email"), self.request.get("password_original"))
                user.put()
                self.login(user)

                r = PasswordResetToken.get_by_id(self.request.get("token"))
                r.key.delete()

                self.redirect(self.uri_for('www-dashboard'))
        else:
            self.redirect('/password/reset?error='+ urllib.quote('Password does not match!.'))
            return
Пример #3
0
    def post(self):
        if self.request.get('email'):
            self.tv["user"] = User.query(User.email == self.request.get("email")).get()
            if self.tv["user"]:
                token = str(uuid.uuid4())
                reset_token = PasswordResetToken(id = token)
                reset_token.email = self.tv["user"].email
                reset_token.token = token
                reset_token.expires = datetime.datetime.now() + datetime.timedelta(hours = 1)
                reset_token.put()

                send_reset_password_email(self.tv["user"], token)
                self.redirect('/forgot-pass?success='+ urllib.quote('Details about how to reset your password have been sent to you by email.'))
            else:
                self.redirect('/forgot-pass?error='+ urllib.quote('Invalid Email.'))
            return
Пример #4
0
def reset_password():
    """
    Ask for a reset password link by email.
    ---
    tags:
        - Accounts
    responses:
        200:
            description: fixme.
    """
    email = request.args.get("email", None)
    if not email:
        abort(400)

    user = User.query.filter(User.email == email).first()
    if not user:
        abort(404)

    # generate a reset link
    prt = PasswordResetToken()
    prt.token = generate_random_token()
    prt.expires_at = None
    prt.user_id = user.id

    db.session.add(prt)
    db.session.commit()
    add_user_log(user.id, user.id, "user", "info",
                 "Password reset token generated")

    # Send email
    token_link = f"https://{current_app.config['AP_DOMAIN']}/password-reset/{prt.token}"
    msg = Message(subject="Password reset",
                  recipients=[user.email],
                  sender=current_app.config["MAIL_DEFAULT_SENDER"])

    _config = Config.query.first()
    if not _config:
        print("ERROR: cannot get instance Config from database")
    instance = {"name": None, "url": None}
    if _config:
        instance["name"] = _config.app_name
    instance["url"] = current_app.config["REEL2BITS_URL"]
    msg.body = render_template("email/password_reset.txt",
                               token_link=token_link,
                               user=user,
                               instance=instance)
    msg.html = render_template("email/password_reset.html",
                               token_link=token_link,
                               user=user,
                               instance=instance)
    err = None
    mail = current_app.extensions.get("mail")
    if not mail:
        err = "mail extension is none"
    else:
        try:
            mail.send(msg)
        except ConnectionRefusedError as e:
            # TODO: do something about that maybe
            print(f"Error sending mail: {e}")
            err = e
        except smtplib.SMTPRecipientsRefused as e:
            print(f"Error sending mail: {e}")
            err = e
        except smtplib.SMTPException as e:
            print(f"Error sending mail: {e}")
            err = e
        if err:
            add_log(
                "global", "ERROR",
                f"Error sending email for password reset user {user.id}: {err}"
            )
            add_user_log(user.id, user.id, "user", "error",
                         "An error occured while sending email")

    return jsonify({"status": "ok"}), 204
Пример #5
0
def forgot_password(request):
    """Form for requesting a PasswordResetToken for a specified account.
    Accepts email or username. Keeps for each user at most one token at a time 
    in the database. Also, it saves FakeTokens to obfuscate an account's existence
    whilst at the same time forcing a 5 minutes gap between the sending of two
    tokens for the same account."""
    
    if request.user.is_authenticated():
        return not_logged_out_routine(request)
    
    if request.method == 'POST':
        
        form = ForgotPasswordForm(request.POST)
        if form.is_valid():
            
            identifier = form.cleaned_data['identifier']
            
            user = None # do we need this here? -- Probably.
            
            try:
                
                # Form input could be an email or a username
                if looks_like_email(identifier):
                    user = CustomUser.objects.get(email=identifier)
                else:
                    user = CustomUser.objects.get(username=identifier)
                
                # At this point, we do have a user object.
                
                try:
                    # Between sending two tokens for the same user, a certain period should pass (--> settings)
                    previous_token = PasswordResetToken.objects.get(user=user)
                    if previous_token.blocks_new():
                        messages.error(request, 'You need to wait between sending two tokens for the same account.')
                        return redirect('accounts:forgot_password')
                    
                    # Only one token per user in the database; and we are about to create a new one.
                    else:
                        previous_token.delete()

                except PasswordResetToken.DoesNotExist:
                    # Fair enough.
                    pass
                
                # Alright, create the new token and send it.

                token = PasswordResetToken(user=user)
                token.save()
                request.session['token_value'] = token.value

                # EXTEND: send email

            except CustomUser.DoesNotExist:
                # No such user, therefor no email or token. But we do want a FakeToken.
                # See models.FakeToken or the docstring here for explanation why we do this FakeToken thing.
                try:
                    # Clear all previous FakeTokens.
                    
                    # No difference between email or username here:
                    previous_token = FakeToken.objects.get(user_identifier=identifier)
                    if previous_token.blocks_new() == True:
                        messages.error(request, 'You need to wait between sending two tokens for the same account.')
                        return redirect('accounts:forgot_password')
                    else:
                        previous_token.delete()

                except FakeToken.DoesNotExist:
                    pass
                
                ft = FakeToken(user_identifier=identifier)
                ft.save()
                request.session['token_value'] = None
            
            # we want to tell the user whether he had stated a username or an
            # email address; and we want to tell him which of both he stated
            if looks_like_email(identifier):
                request.session['token_email'] = identifier
                request.session['token_username'] = None
            else:
                request.session['token_email'] = None
                request.session['token_username'] = identifier

            return redirect('accounts:token_sent')
    
    else:
        form = ForgotPasswordForm
    
    return render(request, 'accounts/forgot_password.html', {
        'form':form
    })