accounts.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. from hmac import new
  2. from unicodedata import category
  3. from flask import Blueprint, render_template, request, flash, redirect, url_for
  4. from flask_login import login_user, login_required, logout_user, current_user
  5. from werkzeug.security import generate_password_hash, check_password_hash
  6. from .models import User
  7. from . import db
  8. from .forms import LoginForm, RegForm, MFAForm
  9. # MFA
  10. import pyotp
  11. accounts = Blueprint('accounts', __name__)
  12. @accounts.route('/login', methods=['GET', 'POST'])
  13. def login():
  14. form = LoginForm()
  15. if form.validate_on_submit():
  16. email = form.email.data
  17. challenge_passwd = form.passwd.data
  18. # Check fo user in User table
  19. user = User.query.filter_by(email=email).first()
  20. # If there's a user
  21. if user:
  22. if check_password_hash(user.password, challenge_passwd):
  23. return redirect(url_for('accounts.mfa', user_chal = user.id)) # passes user to mfa
  24. else:
  25. flash('Unsucessful Login!', category='error')
  26. else:
  27. flash('Unsucessful Login!', category='error')
  28. return render_template('login.html', user = current_user, form = form)
  29. @accounts.route('/logout')
  30. @login_required
  31. def logout():
  32. logout_user()
  33. return redirect(url_for('accounts.login'))
  34. @accounts.route('/register', methods=['GET', 'POST'])
  35. def register():
  36. pass_list = list()
  37. form = RegForm()
  38. if form.validate_on_submit():
  39. email = form.email.data
  40. username = form.username.data
  41. passwd_1 = form.passwd_1.data
  42. passwd_2 = form.passwd_2.data
  43. # Basic User Input Checks
  44. email_check = User.query.filter_by(email=email).first()
  45. if len(email) < 1:
  46. flash('Your Email must be longer than 0 characters.', category='error')
  47. elif email_check:
  48. flash('This Email is already taken', category='error')
  49. else:
  50. pass_list.append('p')
  51. if len(username) < 1:
  52. flash('Username must be something', category='error')
  53. else:
  54. pass_list.append('p')
  55. if len(passwd_1) < 8 or len(passwd_2) < 8:
  56. flash('Your Password must be longer than or equal to 8 characters.', category='error')
  57. else:
  58. if passwd_1 != passwd_2:
  59. flash('Your Passwords must match!', category='error')
  60. else:
  61. if len(pass_list) == 2:
  62. new_user = User(email=email,
  63. username=username,
  64. password=generate_password_hash(passwd_2, method='sha256')
  65. )
  66. db.session.add(new_user)
  67. db.session.commit()
  68. flash('Account Registration Successful!', category='success')
  69. return redirect(url_for('dashboards.market'))
  70. else:
  71. flash('Registration Failed', category='error')
  72. return render_template("register.html", user = current_user, form = form)
  73. @accounts.route('/mfa', methods=['GET', 'POST'])
  74. def mfa():
  75. form = MFAForm()
  76. user_chal = request.args['user_chal']
  77. user = User.query.filter_by(id = user_chal).first()
  78. # check for existing totphash
  79. if not user.totphash:
  80. # generate random secret key for auth
  81. secret = pyotp.random_base32()
  82. # add to User table and show this secret next time.
  83. dbcall = User.query.filter_by(id = user.id).first()
  84. dbcall.totphash = secret
  85. db.session.commit()
  86. flash('Generated new TOTP Secret', category='success')
  87. else: # create a new totphash
  88. secret = user.totphash
  89. challenge_answer = int(pyotp.TOTP(secret).now())
  90. if form.validate_on_submit():
  91. otp = int(form.otp.data)
  92. # checks MFA
  93. if challenge_answer == otp:
  94. flash('Login Successful!', category='sucess')
  95. login_user(user, remember=True)
  96. return redirect(url_for('dashboards.market'))
  97. else:
  98. flash('Login Unsuccessful!', category='error')
  99. return redirect(url_for('accounts.mfa'))
  100. return render_template('mfa.html', secret = secret, form = form, user = user)