2017-03-08 13:53:09 -05:00
|
|
|
|
from flask import render_template, redirect, request, url_for, flash, session, abort, current_app
|
|
|
|
|
from flask_login import login_required, login_user, logout_user, current_user
|
|
|
|
|
|
|
|
|
|
from . import auth
|
|
|
|
|
from .. import db
|
2017-06-10 23:26:10 -04:00
|
|
|
|
from ..models import User, Transaction
|
2017-03-08 13:53:09 -05:00
|
|
|
|
from ..email import send_email
|
|
|
|
|
from .forms import LoginForm, TwoFAForm, RegistrationForm, ChangePasswordForm,PasswordResetRequestForm, PasswordResetForm
|
2018-08-01 03:20:50 -04:00
|
|
|
|
from ..decorators import admin_required, permission_required
|
2017-03-08 13:53:09 -05:00
|
|
|
|
|
|
|
|
|
from io import BytesIO
|
|
|
|
|
import pyqrcode
|
|
|
|
|
|
2017-06-25 10:11:52 -04:00
|
|
|
|
def get_google_auth(state=None, token=None):
|
|
|
|
|
if token:
|
|
|
|
|
return OAuth2Session(current_app.config['CLIENT_ID'], token=token)
|
|
|
|
|
if state:
|
|
|
|
|
return OAuth2Session(
|
|
|
|
|
current_app.config['CLIENT_ID'],
|
|
|
|
|
state=state,
|
|
|
|
|
redirect_uri=current_app.config['REDIRECT_URI'])
|
|
|
|
|
oauth = OAuth2Session(
|
|
|
|
|
current_app.config['CLIENT_ID'],
|
|
|
|
|
redirect_uri=current_app.config['REDIRECT_URI'],
|
|
|
|
|
scope=current_app.config['SCOPE'])
|
|
|
|
|
return oauth
|
|
|
|
|
|
2017-03-08 13:53:09 -05:00
|
|
|
|
@auth.before_app_request
|
|
|
|
|
def before_request():
|
|
|
|
|
#print('session: %s' % str(session))
|
|
|
|
|
if current_user.is_authenticated:
|
|
|
|
|
current_user.ping()
|
|
|
|
|
#print('request for {} from {}#{}'.format(request.endpoint, current_user.email, current_user.pid))
|
|
|
|
|
if not current_user.confirmed and request.endpoint[:5] != 'auth.' and request.endpoint != 'static':
|
|
|
|
|
print(request.endpoint)
|
|
|
|
|
return redirect(url_for('auth.unconfirmed'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@auth.route('/unconfirmed')
|
|
|
|
|
def unconfirmed():
|
|
|
|
|
if current_user.is_anonymous or current_user.confirmed:
|
2017-05-12 15:10:56 -04:00
|
|
|
|
return redirect(url_for('main.index'))
|
2017-03-08 13:53:09 -05:00
|
|
|
|
return render_template('auth/unconfirmed.html')
|
|
|
|
|
|
|
|
|
|
@auth.route('/login', methods=['GET', 'POST'])
|
|
|
|
|
def login():
|
|
|
|
|
page = { 'title': 'Login' }
|
|
|
|
|
form = LoginForm()
|
|
|
|
|
if form.validate_on_submit():
|
|
|
|
|
user = User.query.filter_by(email=form.email.data).first()
|
|
|
|
|
|
|
|
|
|
if user is not None and user.verify_password(form.password.data):
|
2017-05-24 10:37:52 -04:00
|
|
|
|
if user.active == False:
|
|
|
|
|
flash('User disabled.')
|
|
|
|
|
return redirect(url_for('main.index'))
|
|
|
|
|
|
2017-03-08 13:53:09 -05:00
|
|
|
|
if user.twofactor:
|
|
|
|
|
# redirect to the two-factor auth page, passing username in session
|
|
|
|
|
session['email'] = user.email
|
|
|
|
|
session['memberberry'] = form.remember_me.data
|
|
|
|
|
return redirect(url_for('auth.twofactor'))
|
2017-05-24 10:37:52 -04:00
|
|
|
|
|
2017-03-08 13:53:09 -05:00
|
|
|
|
#print('remember: ' + str(form.remember_me.data))
|
|
|
|
|
login_user(user, form.remember_me.data)
|
2017-05-13 05:46:43 -04:00
|
|
|
|
previp = user.last_ip
|
2017-03-08 13:53:09 -05:00
|
|
|
|
if request.headers.getlist("X-Forwarded-For"):
|
|
|
|
|
lastip = request.headers.getlist("X-Forwarded-For")[0]
|
|
|
|
|
else:
|
|
|
|
|
lastip = request.remote_addr
|
|
|
|
|
user.last_ip = lastip
|
|
|
|
|
db.session.add(user)
|
|
|
|
|
db.session.commit()
|
2017-12-14 18:00:02 -05:00
|
|
|
|
send_email(current_app.config['MAIL_USERNAME'], user.email + ' logged in.', 'auth/email/adm_loginnotify', user=user, ipaddr=lastip )
|
|
|
|
|
#flash('Last Login: {} from {}'.format(user.last_seen.strftime("%a %d %B %Y %H:%M"), previp))
|
|
|
|
|
flash('Last Login: {}'.format(user.last_seen.strftime("%a %d %B %Y %H:%M")))
|
2018-01-11 08:19:59 -05:00
|
|
|
|
return redirect(request.args.get('next') or url_for('panel.dashboard'))
|
2017-05-13 05:46:43 -04:00
|
|
|
|
else:
|
|
|
|
|
flash('Invalid username or password.')
|
2017-03-08 13:53:09 -05:00
|
|
|
|
|
|
|
|
|
return render_template('auth/login.html', page=page, form=form)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@auth.route('/twofactor', methods=['GET', 'POST'])
|
|
|
|
|
def twofactor():
|
|
|
|
|
if 'email' not in session:
|
|
|
|
|
abort(404)
|
|
|
|
|
if 'memberberry' not in session:
|
|
|
|
|
abort(404)
|
|
|
|
|
page = { 'title': '2-Factor Login' }
|
|
|
|
|
form = TwoFAForm()
|
|
|
|
|
if form.validate_on_submit():
|
|
|
|
|
user = User.query.filter_by(email=session['email']).first()
|
|
|
|
|
del session['email']
|
|
|
|
|
|
|
|
|
|
if user is not None and user.verify_totp(form.token.data):
|
|
|
|
|
print('remember: ' + str(session['memberberry']))
|
|
|
|
|
login_user(user, session['memberberry'])
|
|
|
|
|
del session['memberberry']
|
|
|
|
|
|
|
|
|
|
if request.headers.getlist("X-Forwarded-For"):
|
|
|
|
|
lastip = request.headers.getlist("X-Forwarded-For")[0]
|
|
|
|
|
else:
|
|
|
|
|
lastip = request.remote_addr
|
|
|
|
|
user.last_ip = lastip
|
|
|
|
|
db.session.add(user)
|
|
|
|
|
db.session.commit()
|
|
|
|
|
#send_email(current_app.config['MAIL_USERNAME'], user.email + ' logged in.', 'auth/email/adm_loginnotify', user=user, ipaddr=lastip )
|
2018-01-11 08:19:59 -05:00
|
|
|
|
return redirect(request.args.get('next') or url_for('panel.dashboard'))
|
2017-05-24 10:37:52 -04:00
|
|
|
|
else:
|
|
|
|
|
flash('Invalid token.')
|
2017-03-08 13:53:09 -05:00
|
|
|
|
return render_template('auth/2fa.html', page=page, form=form)
|
|
|
|
|
|
|
|
|
|
@auth.route('/qrcode')
|
|
|
|
|
@login_required
|
|
|
|
|
def qrcode():
|
|
|
|
|
#if 'email' not in session:
|
|
|
|
|
# abort(404)
|
|
|
|
|
#user = User.query.filter_by(email=session['email']).first()
|
|
|
|
|
#if user is None:
|
|
|
|
|
# abort(404)
|
|
|
|
|
|
|
|
|
|
# for added security, remove username from session
|
|
|
|
|
#del session['email']
|
|
|
|
|
|
|
|
|
|
# render qrcode for FreeTOTP
|
|
|
|
|
url = pyqrcode.create(current_user.get_totp_uri())
|
|
|
|
|
stream = BytesIO()
|
|
|
|
|
url.svg(stream, scale=6)
|
|
|
|
|
return stream.getvalue(), 200, {
|
|
|
|
|
'Content-Type': 'image/svg+xml',
|
|
|
|
|
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
|
|
|
|
'Pragma': 'no-cache',
|
|
|
|
|
'Expires': '0'}
|
|
|
|
|
|
|
|
|
|
@auth.route("/logout", methods=['GET'])
|
|
|
|
|
@login_required
|
|
|
|
|
def logout():
|
|
|
|
|
logout_user()
|
|
|
|
|
flash('You have logged out')
|
2017-05-12 15:10:56 -04:00
|
|
|
|
return redirect(url_for('main.index'))
|
2017-03-08 13:53:09 -05:00
|
|
|
|
|
|
|
|
|
@auth.route('/register', methods=['GET', 'POST'])
|
2018-08-01 03:20:50 -04:00
|
|
|
|
@admin_required
|
2017-03-08 13:53:09 -05:00
|
|
|
|
def register():
|
|
|
|
|
#print(current_app.secret_key)
|
|
|
|
|
page = { 'title': 'Register' }
|
|
|
|
|
form = RegistrationForm()
|
|
|
|
|
if form.validate_on_submit():
|
2017-06-10 23:26:10 -04:00
|
|
|
|
user = User(email=form.email.data, password=form.password.data, wallet=current_app.config['REGISTER_BONUS'])
|
2017-03-08 13:53:09 -05:00
|
|
|
|
db.session.add(user)
|
|
|
|
|
db.session.commit()
|
2017-07-11 12:20:44 -04:00
|
|
|
|
#transaction = Transaction(user_id=int(user.pid), description='Registered account bonus', value=current_app.config['REGISTER_BONUS'])
|
|
|
|
|
#db.session.add(transaction)
|
|
|
|
|
#db.session.commit()
|
2017-03-08 13:53:09 -05:00
|
|
|
|
token = user.generate_confirmation_token()
|
2017-07-06 17:15:02 -04:00
|
|
|
|
send_email(user.email, 'Потвърдете Вашата регистрация', 'auth/email/confirm', user=user, token=token)
|
2017-03-08 13:53:09 -05:00
|
|
|
|
#notify admin
|
|
|
|
|
newip = request.remote_addr
|
|
|
|
|
if request.headers.getlist("X-Forwarded-For"):
|
|
|
|
|
newip = request.headers.getlist("X-Forwarded-For")[0]
|
|
|
|
|
else:
|
|
|
|
|
newip = request.remote_addr
|
|
|
|
|
send_email(current_app.config['MAIL_USERNAME'], user.email + ' registered!', 'auth/email/adm_regnotify', user=user, ipaddr=newip )
|
|
|
|
|
flash('Благодарим за регистрацията! Моля проверете вашият email за потвърждение')
|
|
|
|
|
return redirect(url_for('auth.login'))
|
|
|
|
|
return render_template('auth/register.html', page=page, form=form)
|
|
|
|
|
|
|
|
|
|
@auth.route('/confirm/<token>')
|
|
|
|
|
@login_required
|
|
|
|
|
def confirm(token):
|
|
|
|
|
if current_user.confirmed:
|
2017-05-12 15:10:56 -04:00
|
|
|
|
return redirect(url_for('main.index'))
|
2017-03-08 13:53:09 -05:00
|
|
|
|
if current_user.confirm(token):
|
|
|
|
|
flash('Вашият акаунт е потвърден. Благодаря!')
|
|
|
|
|
else:
|
|
|
|
|
flash('Времето за потвърждение на вашият код изтече.')
|
2017-05-12 15:10:56 -04:00
|
|
|
|
return redirect(url_for('main.index'))
|
2017-03-08 13:53:09 -05:00
|
|
|
|
|
|
|
|
|
@auth.route('/confirm')
|
|
|
|
|
@login_required
|
|
|
|
|
def resend_confirmation():
|
|
|
|
|
token = current_user.generate_confirmation_token()
|
2018-04-07 08:55:24 -04:00
|
|
|
|
send_email(current_user.email, 'Confirm_your_account',
|
2017-03-08 13:53:09 -05:00
|
|
|
|
'auth/email/confirm', user=current_user, token=token)
|
2018-04-07 08:55:24 -04:00
|
|
|
|
flash('New confirmation code was sent.')
|
2017-05-12 15:10:56 -04:00
|
|
|
|
return redirect(url_for('main.index'))
|
2017-03-08 13:53:09 -05:00
|
|
|
|
|
|
|
|
|
@auth.route('/change-password', methods=['GET', 'POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def change_password():
|
|
|
|
|
form = ChangePasswordForm()
|
|
|
|
|
if form.validate_on_submit():
|
|
|
|
|
if current_user.verify_password(form.old_password.data):
|
|
|
|
|
current_user.password = form.password.data
|
|
|
|
|
db.session.add(current_user)
|
|
|
|
|
db.session.commit()
|
2018-04-07 08:55:24 -04:00
|
|
|
|
flash('Your password was changed')
|
2017-05-12 15:10:56 -04:00
|
|
|
|
return redirect(url_for('main.index'))
|
2017-03-08 13:53:09 -05:00
|
|
|
|
else:
|
2018-04-07 08:55:24 -04:00
|
|
|
|
flash('Wrong password.')
|
2017-03-08 13:53:09 -05:00
|
|
|
|
return render_template("auth/change_password.html", form=form)
|
|
|
|
|
|
|
|
|
|
@auth.route('/reset', methods=['GET', 'POST'])
|
|
|
|
|
def password_reset_request():
|
|
|
|
|
if not current_user.is_anonymous:
|
2017-05-12 15:10:56 -04:00
|
|
|
|
return redirect(url_for('main.index'))
|
2017-03-08 13:53:09 -05:00
|
|
|
|
form = PasswordResetRequestForm()
|
|
|
|
|
if form.validate_on_submit():
|
|
|
|
|
user = User.query.filter_by(email=form.email.data).first()
|
|
|
|
|
if user:
|
|
|
|
|
token = user.generate_reset_token()
|
|
|
|
|
send_email(user.email, 'Reset Your Password',
|
|
|
|
|
'auth/email/reset_password',
|
|
|
|
|
user=user, token=token,
|
|
|
|
|
next=request.args.get('next'))
|
2017-09-09 02:32:04 -04:00
|
|
|
|
flash('An email with instructions to reset your password has been sent to you.')
|
2017-03-08 13:53:09 -05:00
|
|
|
|
return redirect(url_for('auth.login'))
|
|
|
|
|
return render_template('auth/reset_password.html', form=form)
|
|
|
|
|
|
|
|
|
|
@auth.route('/reset/<token>', methods=['GET', 'POST'])
|
|
|
|
|
def password_reset(token):
|
|
|
|
|
if not current_user.is_anonymous:
|
2017-05-12 15:10:56 -04:00
|
|
|
|
return redirect(url_for('main.index'))
|
2017-03-08 13:53:09 -05:00
|
|
|
|
form = PasswordResetForm()
|
|
|
|
|
if form.validate_on_submit():
|
|
|
|
|
user = User.query.filter_by(email=form.email.data).first()
|
|
|
|
|
if user is None:
|
2017-05-12 15:10:56 -04:00
|
|
|
|
return redirect(url_for('main.index'))
|
2017-03-08 13:53:09 -05:00
|
|
|
|
if user.reset_password(token, form.password.data):
|
|
|
|
|
flash('Your password has been updated.')
|
|
|
|
|
return redirect(url_for('auth.login'))
|
|
|
|
|
else:
|
2017-05-12 15:10:56 -04:00
|
|
|
|
return redirect(url_for('main.index'))
|
2017-03-08 13:53:09 -05:00
|
|
|
|
return render_template('auth/reset_password.html', form=form)
|
|
|
|
|
|