2021-07-21 01:12:26 +00:00
from urllib . parse import urlencode
2021-08-04 15:35:10 +00:00
from files . mail import *
from files . __main__ import app , limiter
2021-08-21 11:06:28 +00:00
from files . helpers . const import *
2021-07-21 01:12:26 +00:00
valid_username_regex = re . compile ( " ^[a-zA-Z0-9_ \ -] { 3,25}$ " )
valid_password_regex = re . compile ( " ^. { 8,100}$ " )
2021-07-27 22:31:28 +00:00
@app.get ( " /login " )
2021-07-21 01:12:26 +00:00
@auth_desired
def login_get ( v ) :
2021-09-19 13:11:34 +00:00
redir = request . values . get ( " redirect " , " / " ) . replace ( " /logged_out " , " " )
2021-07-21 01:12:26 +00:00
if v :
return redirect ( redir )
return render_template ( " login.html " ,
failed = False ,
redirect = redir )
def check_for_alts ( current_id ) :
# account history
past_accs = set ( session . get ( " history " , [ ] ) )
past_accs . add ( current_id )
session [ " history " ] = list ( past_accs )
# record alts
for past_id in session [ " history " ] :
if past_id == current_id :
continue
2021-09-17 08:29:05 +00:00
check1 = g . db . query ( Alt ) . options ( lazyload ( ' * ' ) ) . filter_by (
2021-07-21 01:12:26 +00:00
user1 = current_id , user2 = past_id ) . first ( )
2021-09-17 08:29:05 +00:00
check2 = g . db . query ( Alt ) . options ( lazyload ( ' * ' ) ) . filter_by (
2021-07-21 01:12:26 +00:00
user1 = past_id , user2 = current_id ) . first ( )
if not check1 and not check2 :
try :
2021-08-23 19:10:49 +00:00
new_alt = Alt ( user1 = past_id , user2 = current_id )
2021-07-21 01:12:26 +00:00
g . db . add ( new_alt )
2021-09-22 22:55:50 +00:00
g . db . flush ( )
2021-07-21 01:12:26 +00:00
except BaseException :
pass
2021-09-21 21:50:03 +00:00
alts = g . db . query ( Alt ) . options ( lazyload ( ' * ' ) )
otheralts = alts . filter ( or_ ( Alt . user1 == past_id , Alt . user2 == past_id , Alt . user1 == current_id , Alt . user2 == current_id ) ) . all ( )
2021-08-23 19:12:14 +00:00
for a in otheralts :
2021-09-21 21:50:03 +00:00
existing = alts . filter_by ( user1 = a . user1 , user2 = past_id ) . first ( )
if not existing :
2021-09-17 15:25:20 +00:00
new_alt = Alt ( user1 = a . user1 , user2 = past_id )
g . db . add ( new_alt )
g . db . flush ( )
2021-09-24 03:32:26 +00:00
2021-09-21 21:50:03 +00:00
existing = alts . filter_by ( user1 = a . user1 , user2 = current_id ) . first ( )
if not existing :
2021-09-17 15:25:20 +00:00
new_alt = Alt ( user1 = a . user1 , user2 = current_id )
g . db . add ( new_alt )
g . db . flush ( )
2021-09-24 03:32:26 +00:00
2021-09-21 21:50:03 +00:00
existing = alts . filter_by ( user1 = a . user2 , user2 = past_id ) . first ( )
if not existing :
2021-09-17 15:25:20 +00:00
new_alt = Alt ( user1 = a . user2 , user2 = past_id )
g . db . add ( new_alt )
g . db . flush ( )
2021-09-24 03:32:26 +00:00
2021-09-21 21:50:03 +00:00
existing = alts . filter_by ( user1 = a . user2 , user2 = current_id ) . first ( )
if not existing :
2021-09-17 15:25:20 +00:00
new_alt = Alt ( user1 = a . user2 , user2 = current_id )
g . db . add ( new_alt )
g . db . flush ( )
2021-08-23 19:12:14 +00:00
2021-07-21 01:12:26 +00:00
# login post procedure
2021-07-27 22:31:28 +00:00
@app.post ( " /login " )
2021-07-21 01:12:26 +00:00
@limiter.limit ( " 6/minute " )
def login_post ( ) :
2021-09-19 13:11:34 +00:00
username = request . values . get ( " username " )
2021-07-21 01:12:26 +00:00
2021-08-14 21:33:41 +00:00
if not username : abort ( 400 )
2021-07-21 01:12:26 +00:00
if " @ " in username :
2021-09-17 08:29:05 +00:00
account = g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter (
2021-07-25 22:11:26 +00:00
User . email . ilike ( username ) ) . first ( )
2021-07-21 01:12:26 +00:00
else :
account = get_user ( username , graceful = True )
if not account :
time . sleep ( random . uniform ( 0 , 2 ) )
2021-08-19 05:45:22 +00:00
return render_template ( " login.html " , failed = True )
2021-07-21 01:12:26 +00:00
# test password
2021-09-19 13:11:34 +00:00
if request . values . get ( " password " ) :
2021-07-21 01:12:26 +00:00
2021-09-19 13:11:34 +00:00
if not account . verifyPass ( request . values . get ( " password " ) ) :
2021-07-21 01:12:26 +00:00
time . sleep ( random . uniform ( 0 , 2 ) )
2021-08-19 05:45:22 +00:00
return render_template ( " login.html " , failed = True )
2021-07-21 01:12:26 +00:00
if account . mfa_secret :
now = int ( time . time ( ) )
hash = generate_hash ( f " { account . id } + { now } +2fachallenge " )
return render_template ( " login_2fa.html " ,
v = account ,
time = now ,
hash = hash ,
2021-09-19 13:11:34 +00:00
redirect = request . values . get ( " redirect " , " / " )
2021-07-21 01:12:26 +00:00
)
2021-09-19 13:11:34 +00:00
elif request . values . get ( " 2fa_token " , " x " ) :
2021-07-21 01:12:26 +00:00
now = int ( time . time ( ) )
2021-09-19 13:11:34 +00:00
if now - int ( request . values . get ( " time " ) ) > 600 :
2021-07-21 01:12:26 +00:00
return redirect ( ' /login ' )
2021-09-19 13:11:34 +00:00
formhash = request . values . get ( " hash " )
if not validate_hash ( f " { account . id } + { request . values . get ( ' time ' ) } +2fachallenge " ,
2021-07-21 01:12:26 +00:00
formhash
) :
return redirect ( " /login " )
2021-09-19 13:11:34 +00:00
if not account . validate_2fa ( request . values . get ( " 2fa_token " , " " ) . strip ( ) ) :
2021-07-21 01:12:26 +00:00
hash = generate_hash ( f " { account . id } + { time } +2fachallenge " )
return render_template ( " login_2fa.html " ,
v = account ,
time = now ,
hash = hash ,
failed = True ,
)
else :
abort ( 400 )
if account . is_banned and account . unban_utc > 0 and time . time ( ) > account . unban_utc :
2021-09-19 20:18:29 +00:00
account . is_banned = 0
account . unban_utc = 0
g . db . add ( account )
2021-07-21 01:12:26 +00:00
# set session and user id
session [ " user_id " ] = account . id
session [ " session_id " ] = token_hex ( 16 )
session [ " login_nonce " ] = account . login_nonce
session . permanent = True
check_for_alts ( account . id )
# check for previous page
2021-09-19 13:11:34 +00:00
redir = request . values . get ( " redirect " , " / " ) . replace ( " /logged_out " , " " )
2021-09-16 17:15:07 +00:00
g . db . commit ( )
2021-08-27 21:39:39 +00:00
return redirect ( redir )
2021-07-21 01:12:26 +00:00
2021-07-27 22:31:28 +00:00
@app.get ( " /me " )
@app.get ( " /@me " )
2021-07-21 01:12:26 +00:00
@auth_required
def me ( v ) :
2021-08-05 17:32:24 +00:00
if request . headers . get ( " Authorization " ) : return v . json
else : return redirect ( v . url )
2021-07-21 01:12:26 +00:00
2021-07-27 22:31:28 +00:00
@app.post ( " /logout " )
2021-07-21 01:12:26 +00:00
@auth_required
@validate_formkey
def logout ( v ) :
session . pop ( " user_id " , None )
session . pop ( " session_id " , None )
2021-09-08 11:05:31 +00:00
return { " message " : " Logout successful! " }
2021-07-21 01:12:26 +00:00
2021-07-27 22:31:28 +00:00
@app.get ( " /signup " )
2021-07-21 01:12:26 +00:00
@auth_desired
def sign_up_get ( v ) :
2021-07-26 18:47:42 +00:00
with open ( ' ./disablesignups ' , ' r ' ) as f :
2021-07-26 19:19:16 +00:00
if f . read ( ) == " yes " : return " New account registration is currently closed. Please come back later. " , 403
2021-07-21 01:12:26 +00:00
2021-07-25 21:59:20 +00:00
if v : return redirect ( " / " )
2021-07-21 01:12:26 +00:00
agent = request . headers . get ( " User-Agent " , None )
if not agent :
abort ( 403 )
# check for referral in link
2021-09-19 13:11:34 +00:00
ref = request . values . get ( " ref " , None )
2021-07-21 01:12:26 +00:00
if ref :
2021-09-17 08:29:05 +00:00
ref_user = g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter ( User . username . ilike ( ref ) ) . first ( )
2021-07-21 01:12:26 +00:00
else :
ref_user = None
if ref_user and ( ref_user . id in session . get ( " history " , [ ] ) ) :
2021-08-19 05:45:22 +00:00
return render_template ( " sign_up_failed_ref.html " )
2021-07-21 01:12:26 +00:00
# Make a unique form key valid for one account creation
now = int ( time . time ( ) )
2021-08-27 21:45:11 +00:00
token = token_hex ( 16 )
session [ " signup_token " ] = token
2021-07-21 01:12:26 +00:00
formkey_hashstr = str ( now ) + token + agent
# formkey is a hash of session token, timestamp, and IP address
formkey = hmac . new ( key = bytes ( environ . get ( " MASTER_KEY " ) , " utf-16 " ) ,
msg = bytes ( formkey_hashstr , " utf-16 " ) ,
digestmod = ' md5 '
) . hexdigest ( )
2021-09-19 13:11:34 +00:00
redir = request . values . get ( " redirect " , " / " ) . replace ( " /logged_out " , " " )
2021-07-21 01:12:26 +00:00
2021-09-19 13:11:34 +00:00
error = request . values . get ( " error " , None )
2021-07-21 01:12:26 +00:00
return render_template ( " sign_up.html " ,
formkey = formkey ,
now = now ,
redirect = redir ,
ref_user = ref_user ,
error = error ,
hcaptcha = app . config [ " HCAPTCHA_SITEKEY " ]
)
2021-07-27 22:31:28 +00:00
@app.post ( " /signup " )
2021-08-27 19:38:18 +00:00
@limiter.limit ( " 5/day " )
2021-07-21 01:12:26 +00:00
@auth_desired
def sign_up_post ( v ) :
2021-07-26 18:47:42 +00:00
with open ( ' ./disablesignups ' , ' r ' ) as f :
2021-07-26 19:19:16 +00:00
if f . read ( ) == " yes " : return " New account registration is currently closed. Please come back later. " , 403
2021-07-21 01:12:26 +00:00
if v :
abort ( 403 )
agent = request . headers . get ( " User-Agent " , None )
if not agent :
abort ( 403 )
2021-09-19 13:11:34 +00:00
form_timestamp = request . values . get ( " now " , ' 0 ' )
form_formkey = request . values . get ( " formkey " , " none " )
2021-07-21 01:12:26 +00:00
submitted_token = session . get ( " signup_token " , " " )
if not submitted_token :
abort ( 400 )
correct_formkey_hashstr = form_timestamp + submitted_token + agent
correct_formkey = hmac . new ( key = bytes ( environ . get ( " MASTER_KEY " ) , " utf-16 " ) ,
msg = bytes ( correct_formkey_hashstr , " utf-16 " ) ,
digestmod = ' md5 '
) . hexdigest ( )
now = int ( time . time ( ) )
2021-09-19 13:11:34 +00:00
username = request . values . get ( " username " ) . strip ( )
2021-07-21 01:12:26 +00:00
# define function that takes an error message and generates a new signup
# form
def new_signup ( error ) :
args = { " error " : error }
2021-09-19 13:11:34 +00:00
if request . values . get ( " referred_by " ) :
2021-09-17 08:29:05 +00:00
user = g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter_by (
2021-09-19 13:11:34 +00:00
id = request . values . get ( " referred_by " ) ) . first ( )
2021-07-21 01:12:26 +00:00
if user :
args [ " ref " ] = user . username
return redirect ( f " /signup? { urlencode ( args ) } " )
if now - int ( form_timestamp ) < 5 :
#print(f"signup fail - {username } - too fast")
return new_signup ( " There was a problem. Please try again. " )
if not hmac . compare_digest ( correct_formkey , form_formkey ) :
#print(f"signup fail - {username } - mismatched formkeys")
return new_signup ( " There was a problem. Please try again. " )
# check for matched passwords
2021-09-19 13:11:34 +00:00
if not request . values . get (
" password " ) == request . values . get ( " password_confirm " ) :
2021-07-21 01:12:26 +00:00
return new_signup ( " Passwords did not match. Please try again. " )
# check username/pass conditions
2021-07-27 21:58:35 +00:00
if not re . fullmatch ( valid_username_regex , username ) :
2021-07-21 01:12:26 +00:00
return new_signup ( " Invalid username " )
2021-09-19 13:11:34 +00:00
if not re . fullmatch ( valid_password_regex , request . values . get ( " password " ) ) :
2021-07-21 01:12:26 +00:00
return new_signup ( " Password must be between 8 and 100 characters. " )
2021-07-22 20:11:50 +00:00
# Check for existing accounts
2021-09-19 13:11:34 +00:00
email = request . values . get ( " email " )
2021-07-21 01:12:26 +00:00
email = email . strip ( )
2021-07-22 20:31:24 +00:00
if not email : email = None
2021-07-21 01:12:26 +00:00
2021-07-25 13:49:29 +00:00
existing_account = get_user ( username , graceful = True )
2021-07-21 01:12:26 +00:00
if existing_account and existing_account . reserved :
2021-09-03 19:43:12 +00:00
return redirect ( existing_account . url )
2021-07-21 01:12:26 +00:00
if existing_account or ( email and g . db . query (
User ) . filter ( User . email . ilike ( email ) ) . first ( ) ) :
# #print(f"signup fail - {username } - email already exists")
return new_signup (
" An account with that username or email already exists. " )
# check bot
if app . config . get ( " HCAPTCHA_SITEKEY " ) :
2021-09-19 13:11:34 +00:00
token = request . values . get ( " h-captcha-response " )
2021-07-21 01:12:26 +00:00
if not token :
return new_signup ( " Unable to verify captcha [1]. " )
data = { " secret " : app . config [ " HCAPTCHA_SECRET " ] ,
" response " : token ,
" sitekey " : app . config [ " HCAPTCHA_SITEKEY " ] }
url = " https://hcaptcha.com/siteverify "
x = requests . post ( url , data = data )
if not x . json ( ) [ " success " ] :
#print(x.json())
return new_signup ( " Unable to verify captcha [2]. " )
# kill tokens
session . pop ( " signup_token " )
# get referral
2021-09-19 13:11:34 +00:00
ref_id = int ( request . values . get ( " referred_by " , 0 ) )
2021-07-21 01:12:26 +00:00
# upgrade user badge
if ref_id :
ref_user = g . db . query ( User ) . options (
lazyload ( ' * ' ) ) . filter_by ( id = ref_id ) . first ( )
if ref_user :
2021-09-11 23:40:58 +00:00
# check self-setting badges
2021-09-17 08:29:05 +00:00
badge_types = g . db . query ( BadgeDef ) . options ( lazyload ( ' * ' ) ) . filter ( BadgeDef . qualification_expr . isnot ( None ) ) . all ( )
2021-09-11 23:40:58 +00:00
for badge in badge_types :
2021-09-14 14:22:09 +00:00
if eval ( badge . qualification_expr , { } , { ' v ' : ref_user } ) :
2021-09-11 23:40:58 +00:00
if not ref_user . has_badge ( badge . id ) :
new_badge = Badge ( user_id = ref_user . id , badge_id = badge . id )
g . db . add ( new_badge )
else :
bad_badge = ref_user . has_badge ( badge . id )
if bad_badge : g . db . delete ( bad_badge )
2021-07-21 01:12:26 +00:00
g . db . add ( ref_user )
2021-09-17 08:29:05 +00:00
id_1 = g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter_by ( id = 6 ) . count ( )
2021-08-21 11:06:28 +00:00
users_count = g . db . query ( User ) . count ( ) #paranoid
if id_1 == 0 and users_count < 6 : admin_level = 6
2021-08-01 05:33:58 +00:00
else : admin_level = 0
2021-07-21 01:12:26 +00:00
# make new user
2021-09-03 19:43:12 +00:00
new_user = User (
username = username ,
original_username = username ,
admin_level = admin_level ,
2021-09-19 13:11:34 +00:00
password = request . values . get ( " password " ) ,
2021-09-03 19:43:12 +00:00
email = email ,
created_utc = int ( time . time ( ) ) ,
referred_by = ref_id or None ,
2021-09-17 08:29:05 +00:00
ban_evade = int ( any ( [ x . is_banned and not x . unban_utc for x in g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter ( User . id . in_ ( tuple ( session . get ( " history " , [ ] ) ) ) ) . all ( ) if x ] ) ) ,
agendaposter = any ( [ x . agendaposter for x in g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter ( User . id . in_ ( tuple ( session . get ( " history " , [ ] ) ) ) ) . all ( ) if x ] ) ,
club_banned = any ( [ x . club_banned for x in g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter ( User . id . in_ ( tuple ( session . get ( " history " , [ ] ) ) ) ) . all ( ) if x ] )
2021-09-03 19:43:12 +00:00
)
2021-07-21 01:12:26 +00:00
g . db . add ( new_user )
2021-09-13 11:18:19 +00:00
g . db . flush ( )
2021-07-21 01:12:26 +00:00
# check alts
check_for_alts ( new_user . id )
# send welcome/verify email
2021-08-19 19:22:10 +00:00
if email : send_verification_email ( new_user )
2021-07-21 01:12:26 +00:00
# send welcome message
2021-08-21 11:06:28 +00:00
if " rdrama " in request . host : send_notification ( NOTIFICATIONS_ACCOUNT , new_user , " Dude bussy lmao " )
2021-07-21 01:12:26 +00:00
session [ " user_id " ] = new_user . id
session [ " session_id " ] = token_hex ( 16 )
2021-09-16 17:02:58 +00:00
g . db . commit ( )
2021-07-21 01:12:26 +00:00
return redirect ( " / " )
2021-07-27 22:31:28 +00:00
@app.get ( " /forgot " )
2021-07-21 01:12:26 +00:00
def get_forgot ( ) :
return render_template ( " forgot_password.html " ,
)
2021-07-27 22:31:28 +00:00
@app.post ( " /forgot " )
2021-07-21 01:12:26 +00:00
def post_forgot ( ) :
2021-09-19 13:11:34 +00:00
username = request . values . get ( " username " ) . lstrip ( ' @ ' )
email = request . values . get ( " email " , ' ' ) . strip ( )
2021-07-21 01:12:26 +00:00
2021-07-22 20:31:24 +00:00
email = email . replace ( " _ " , " \ _ " )
2021-09-17 08:29:05 +00:00
user = g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter (
2021-08-22 15:11:41 +00:00
User . username . ilike ( username ) ,
User . email . ilike ( email ) ) . first ( )
if not user and email . endswith ( " @gmail.com " ) :
2021-07-22 20:31:24 +00:00
email = email . split ( ' @ ' ) [ 0 ]
email = email . split ( ' + ' ) [ 0 ]
email = email . replace ( ' . ' , ' ' )
email = f " { email } @gmail.com "
2021-09-17 08:29:05 +00:00
user = g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter (
2021-08-22 15:11:41 +00:00
User . username . ilike ( username ) ,
User . email . ilike ( email ) ) . first ( )
2021-07-21 01:12:26 +00:00
if user :
# generate url
now = int ( time . time ( ) )
token = generate_hash ( f " { user . id } + { now } +forgot+ { user . login_nonce } " )
url = f " https:// { app . config [ ' SERVER_NAME ' ] } /reset?id= { user . id } &time= { now } &token= { token } "
send_mail ( to_address = user . email ,
2021-08-04 16:00:57 +00:00
subject = " Password Reset Request " ,
2021-07-21 01:12:26 +00:00
html = render_template ( " email/password_reset.html " ,
action_url = url ,
v = user )
)
return render_template ( " forgot_password.html " ,
2021-08-19 05:45:22 +00:00
msg = " If the username and email matches an account, you will be sent a password reset email. You have ten minutes to complete the password reset process. " )
2021-07-21 01:12:26 +00:00
2021-07-27 22:31:28 +00:00
@app.get ( " /reset " )
2021-07-21 01:12:26 +00:00
def get_reset ( ) :
2021-09-19 13:11:34 +00:00
user_id = request . values . get ( " id " )
timestamp = int ( request . values . get ( " time " , 0 ) )
token = request . values . get ( " token " )
2021-07-21 01:12:26 +00:00
now = int ( time . time ( ) )
if now - timestamp > 600 :
return render_template ( " message.html " ,
title = " Password reset link expired " ,
error = " That password reset link has expired. " )
2021-09-17 08:29:05 +00:00
user = g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter_by ( id = user_id ) . first ( )
2021-07-21 01:12:26 +00:00
if not validate_hash ( f " { user_id } + { timestamp } +forgot+ { user . login_nonce } " , token ) :
abort ( 400 )
if not user :
abort ( 404 )
reset_token = generate_hash ( f " { user . id } + { timestamp } +reset+ { user . login_nonce } " )
return render_template ( " reset_password.html " ,
v = user ,
token = reset_token ,
time = timestamp ,
)
2021-07-27 22:31:28 +00:00
@app.post ( " /reset " )
2021-07-21 01:12:26 +00:00
@auth_desired
def post_reset ( v ) :
if v :
return redirect ( ' / ' )
2021-09-19 13:11:34 +00:00
user_id = request . values . get ( " user_id " )
timestamp = int ( request . values . get ( " time " ) )
token = request . values . get ( " token " )
2021-07-21 01:12:26 +00:00
2021-09-19 13:11:34 +00:00
password = request . values . get ( " password " )
confirm_password = request . values . get ( " confirm_password " )
2021-07-21 01:12:26 +00:00
now = int ( time . time ( ) )
if now - timestamp > 600 :
return render_template ( " message.html " ,
title = " Password reset expired " ,
error = " That password reset form has expired. " )
2021-09-17 08:29:05 +00:00
user = g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter_by ( id = user_id ) . first ( )
2021-07-21 01:12:26 +00:00
if not validate_hash ( f " { user_id } + { timestamp } +reset+ { user . login_nonce } " , token ) :
abort ( 400 )
if not user :
abort ( 404 )
if not password == confirm_password :
return render_template ( " reset_password.html " ,
v = user ,
token = token ,
time = timestamp ,
error = " Passwords didn ' t match. " )
user . passhash = hash_password ( password )
g . db . add ( user )
2021-09-16 17:15:07 +00:00
g . db . commit ( )
2021-07-21 01:12:26 +00:00
return render_template ( " message_success.html " ,
title = " Password reset successful! " ,
message = " Login normally to access your account. " )
@app.route ( " /lost_2fa " )
@auth_desired
def lost_2fa ( v ) :
return render_template (
" lost_2fa.html " ,
v = v
)
2021-07-27 22:31:28 +00:00
@app.post ( " /request_2fa_disable " )
2021-07-21 01:12:26 +00:00
@limiter.limit ( " 6/minute " )
def request_2fa_disable ( ) :
2021-09-19 13:11:34 +00:00
username = request . values . get ( " username " )
2021-07-21 01:12:26 +00:00
user = get_user ( username , graceful = True )
if not user or not user . email or not user . mfa_secret :
return render_template ( " message.html " ,
title = " Removal request received " ,
message = " If username, password, and email match, we will send you an email. " )
2021-09-19 13:11:34 +00:00
email = request . values . get ( " email " )
2021-08-22 15:11:41 +00:00
if email != user . email and email . endswith ( " @gmail.com " ) :
2021-07-22 20:31:24 +00:00
email = email . split ( ' @ ' ) [ 0 ]
email = email . split ( ' + ' ) [ 0 ]
email = email . replace ( ' . ' , ' ' )
email = f " { email } @gmail.com "
2021-08-22 15:11:41 +00:00
if email != user . email :
return render_template ( " message.html " ,
title = " Removal request received " ,
message = " If username, password, and email match, we will send you an email. " )
2021-07-21 01:12:26 +00:00
2021-09-19 13:11:34 +00:00
password = request . values . get ( " password " )
2021-07-21 01:12:26 +00:00
if not user . verifyPass ( password ) :
return render_template ( " message.html " ,
title = " Removal request received " ,
message = " If username, password, and email match, we will send you an email. " )
#compute token
2021-07-23 20:31:29 +00:00
valid = int ( time . time ( ) )
2021-07-21 01:12:26 +00:00
token = generate_hash ( f " { user . id } + { user . username } +disable2fa+ { valid } + { user . mfa_secret } + { user . login_nonce } " )
2021-07-30 05:31:38 +00:00
action_url = f " https:// { app . config [ ' SERVER_NAME ' ] } /reset_2fa?id= { user . id } &t= { valid } &token= { token } "
2021-07-21 01:12:26 +00:00
send_mail ( to_address = user . email ,
2021-08-04 16:00:57 +00:00
subject = " 2FA Removal Request " ,
2021-07-21 01:12:26 +00:00
html = render_template ( " email/2fa_remove.html " ,
action_url = action_url ,
v = user )
)
return render_template ( " message.html " ,
title = " Removal request received " ,
message = " If username, password, and email match, we will send you an email. " )
2021-07-27 22:31:28 +00:00
@app.get ( " /reset_2fa " )
2021-07-21 01:12:26 +00:00
def reset_2fa ( ) :
now = int ( time . time ( ) )
2021-09-19 13:11:34 +00:00
t = int ( request . values . get ( " t " ) )
2021-07-21 01:12:26 +00:00
2021-07-23 20:31:29 +00:00
if now > t + 3600 * 24 :
2021-07-21 01:12:26 +00:00
return render_template ( " message.html " ,
title = " Expired Link " ,
error = " That link has expired. " )
2021-09-19 13:11:34 +00:00
token = request . values . get ( " token " )
uid = request . values . get ( " id " )
2021-07-21 01:12:26 +00:00
user = get_account ( uid )
if not validate_hash ( f " { user . id } + { user . username } +disable2fa+ { t } + { user . mfa_secret } + { user . login_nonce } " , token ) :
abort ( 403 )
#validation successful, remove 2fa
user . mfa_secret = None
g . db . add ( user )
2021-09-16 17:15:07 +00:00
g . db . commit ( )
2021-07-21 01:12:26 +00:00
return render_template ( " message_success.html " ,
title = " Two-factor authentication removed. " ,
message = " Login normally to access your account. " )