File: //proc/thread-self/root/home/arjun/projects/buyercall/buyercall/blueprints/user/views.py
import copy
import uuid
import logging
import traceback
<<<<<<< HEAD
from datetime import datetime
import tldextract
import traceback
=======
import requests
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
from sqlalchemy import func
from flask import (
Blueprint,
redirect,
request,
flash,
url_for,
render_template,
current_app,
<<<<<<< HEAD
session,
g)
from buyercall.blueprints.activity.models import ActivityType, ActivityName, ActivityLogs
=======
session)
from buyercall.blueprints.activity.models import ActivityType, ActivityName, ActivityLogs
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
from buyercall.blueprints.user.decorators import role_required
from flask_login import (
login_required,
login_user,
current_user,
logout_user)
from flask_babel import gettext as _
from flask_cors import CORS
from buyercall.lib.safe_next_url import safe_next_url
from buyercall.lib.util_two_factor_auth import send_verification_code
from buyercall.blueprints.user.decorators import anonymous_required
from buyercall.blueprints.user.forms import (
LoginForm,
TwoFactorAuthForm,
BeginPasswordResetForm,
PasswordResetForm,
SignupForm,
UpdateCredentials,
UpdatePersonalDetails,
UpdateLocale,
UpdatePhoneNumber,
UpdateSecurity,
PersonalInformationForm,
SecurtyInformationForm,
UpdateSecurityForm,
ThemeSettingsForm)
from buyercall.extensions import bcrypt, db
from buyercall.blueprints.agents.models import Agent
from buyercall.blueprints.widgets.models import Widget
from buyercall.blueprints.filters import format_phone_number
from buyercall.blueprints.user.models import User
from buyercall.blueprints.partnership.models import Partnership, PartnershipAccount
from buyercall.lib.supervisor_manager import (
current_supervisor_user,
login_user as supervisor_login_user,
logout_user as supervisor_logout_user,
login_required as supervisor_login_required)
from buyercall.blueprints.filters import format_phone_number_bracket
<<<<<<< HEAD
from dateutil.tz import UTC
from buyercall.blueprints.notification.utilities import send_notifications
from buyercall.lib.util_boto3_s3 import refresh_presigned_url, generate_presigned_file_url
# from buyercall.extensions import socket, emit
=======
from buyercall.blueprints.user.utilities.failed_login_notify import FailedLoginNotifier
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
log = logging.getLogger(__name__)
user = Blueprint('user', __name__, template_folder='templates')
CORS(user) # enable CORS on the user blueprint
ALLOWED_EXTENSIONS = ['jpg', 'jpeg', 'png']
def get_partnership():
# Get partnership details by user's partner_url
if 'request_config' in g:
if 'partner_url' in g.request_config:
partnership = Partnership.query.filter(Partnership.partner_url == g.request_config['partner_url']).first()
if partnership:
return partnership
return Partnership.query.get(1)
@user.route('/login', methods=['GET', 'POST'])
@anonymous_required()
def login():
domain = request.host.replace('www', '')
white_label = False
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_logo = primary_partner.logo
partner_name = primary_partner.name
partner_url = primary_partner.partner_url
partner_custom_styles = primary_partner.custom_styles
partners = Partnership.query.filter(Partnership.active.is_(True)).all()
for partner in partners:
if partner.partner_url and partner.id != 1:
partner_domain = partner.partner_url.replace('https://', '').replace('www', '')
if partner_domain == domain:
partner_url = partner_domain
white_label = True
if partner.logo:
partner_logo = partner.logo
if partner.custom_styles:
partner_custom_styles = partner.custom_styles
partner_name = partner.name
<<<<<<< HEAD
form = LoginForm(next=request.args.get('next'))
next_url = request.form.get('next')
remember = request.form.get('remember', False)
if remember == 'y':
remember = True
else:
remember = False
# get partnership details
partnership = get_partnership()
partnership_logo = partnership.alternative_logo
if '::' in partnership_logo:
bucket_name, key = partnership_logo.split("::")
partnership_logo = generate_presigned_file_url(key, bucket_name)
if form.validate_on_submit():
u = User.find_by_identity(request.form.get('identity').lower())
try:
if u and u.authenticated(password=request.form.get('password')):
# As you can see remember me is always enabled, this was a design
# decision I made because more often than not users want this
# enabled. This allows for a less complicated login form.
#
# If however you want them to be able to select whether they
# should remain logged in then perform the following 3 steps:
# 1) Replace 'True' below with: request.form.get('remember', False)
# 2) Uncomment the 'remember' field in user/forms.py#LoginForm
# 3) Add a checkbox to the login form with the id/name 'remember'
# Check to see if the user has done security on-boarding yet
if not u.two_factor_auth_onboard:
return redirect(url_for('user.additional_user_security_onboarding',
user_sid=u.sid,
url=next_url,
remember=remember))
# Have the user verify their account with two-factor authentication
# if two_factor_auth is set to True
if u.two_factor_auth:
code = send_verification_code(u.phonenumber)
log.info('the verification code is: {}'.format(code))
data = {
'user_id': u.sid,
'notify_message_type': 'TWO_FACTOR_AUTH_REQUEST',
'user_related_entities': "You've",
'other_user_related_entities': f'{u.firstname} {u.lastname}',
'hyperlink': f'{partnership.partner_url}/dashboard'
}
response = send_notifications(**data)
return redirect(url_for('user.two_factor_auth',
user_sid=u.sid,
url=next_url,
remember=remember))
# Login the user and redirect them to the appropriate page
if u.active and login_user(u, remember=remember):
u.update_activity_tracking(request.remote_addr)
data = {
'user_id': u.sid,
'notify_message_type': 'LOGGED_IN',
'other_user_related_entities': f'{u.firstname} {u.lastname}',
'user_related_entities': "You've",
'hyperlink': f'{partnership.partner_url}/dashboard'
}
response = send_notifications(**data)
# Handle optionally redirecting to the next URL safely
if next_url:
return redirect(safe_next_url(next_url))
# if current_user.role in ['sysadmin', 'partner'] and not current_user.is_admin_user_with_groups:
#
# return redirect(url_for('dashboard.user_dashboard'))
# elif current_user.role in ['admin'] and current_user.is_admin_user_with_groups \
# and current_user.is_viewing_partnership \
# and current_user.get_user_viewing_partnership_account_subscription_plan != 'partnershipsingle':
# return redirect(url_for('dashboard.user_dashboard'))
# elif current_user.role in ['admin'] and current_user.is_admin_user_with_groups \
# and current_user.is_viewing_partnership \
# and current_user.get_user_viewing_partnership_account_subscription_plan == 'partnershipsingle':
# return redirect(url_for('contacts.user_dashboard'))
# elif current_user.is_admin_user_with_groups:
# return redirect(url_for('partnership.user_dashboard'))
# elif current_user.role in ['agent'] and current_user.subscription.plan != 'partnershipsingle':
# return redirect(url_for('contacts.user_dashboard'))
# elif current_user.subscription and current_user.subscription.plan == 'partnershipsingle':
# return redirect(url_for('user.user_dashboard'))
else:
return redirect(url_for('dashboard.user_dashboard'))
else:
flash(_('This account has been disabled.'), 'danger')
else:
flash(_('Email or password is incorrect.'), 'danger')
except Exception as e:
print("Error : ", e)
log.error(traceback.format_exc())
log.info('There is an issue with the password for user: {}'.format(u.email))
flash(
_('There is a problem with your password. Please reset your password by clicking '
'on the forget your password? link below the submit button.'),
'danger')
return render_template('user/login.jinja2', form=form, partnership=partnership, partnership_logo=partnership_logo)
@user.route('/login-old', methods=['GET', 'POST'])
@anonymous_required()
def login_old():
=======
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
form = LoginForm(next=request.args.get('next'))
next_url = request.form.get('next')
remember = request.form.get('remember', False)
if remember == 'y':
remember = True
else:
remember = False
recaptcha_response = request.form.get('g-recaptcha-response', None)
if not recaptcha_response:
return render_template('user/login.jinja2', white_label=white_label, partner_logo=partner_logo,
partner_name=partner_name, partner_url=partner_url,
partner_custom_styles=partner_custom_styles, form=form,
site_key=current_app.config.get('RC_SITE_KEY_V3'))
verify_url = 'https://www.google.com/recaptcha/api/siteverify'
response = requests.post(
f"{verify_url}?secret={current_app.config.get('RC_SECRET_KEY_V3')}&response={recaptcha_response}").json()
if not response.get('success', False):
log.info('Please add a valid Google ReCaptcha keys, or add your domain to the ReCaptcha admin console.')
return render_template('user/login.jinja2', white_label=white_label, partner_logo=partner_logo,
partner_name=partner_name, partner_url=partner_url,
partner_custom_styles=partner_custom_styles, form=form,
site_key=current_app.config.get('RC_SITE_KEY_V3'))
if form.validate_on_submit():
user_email = request.form.get('identity')
u = User.find_by_identity(user_email.lower())
if u is None:
flash(_(f'The email address {user_email} does not exist. Please try again or contact support.'), 'danger')
return render_template('user/login.jinja2', white_label=white_label, partner_logo=partner_logo,
partner_name=partner_name, partner_url=partner_url,
partner_custom_styles=partner_custom_styles, form=form,
site_key=current_app.config.get('RC_SITE_KEY_V3'))
if FailedLoginNotifier(u).is_blocked():
return render_template('user/login.jinja2', white_label=white_label, partner_logo=partner_logo,
partner_name=partner_name, partner_url=partner_url,
partner_custom_styles=partner_custom_styles, form=form,
site_key=current_app.config.get('RC_SITE_KEY_V3'))
try:
if u and u.authenticated(password=request.form.get('password')):
# As you can see remember me is always enabled, this was a design
# decision I made because more often than not users want this
# enabled. This allows for a less complicated login form.
#
# If however you want them to be able to select whether they
# should remain logged in then perform the following 3 steps:
# 1) Replace 'True' below with: request.form.get('remember', False)
# 2) Uncomment the 'remember' field in user/forms.py#LoginForm
# 3) Add a checkbox to the login form with the id/name 'remember'
# Set session variable to be identified during 2FA and TOS
session["user_identify"] = u.email.lower()
# logic to save ip address
u.save_ip_address(ip_address=request.remote_addr)
# start logic to save user-agent
new_os_status = u.save_user_agent(os_value=request.user_agent.string)
if new_os_status:
from buyercall.blueprints.user.tasks import send_new_os_notification, send_support_new_os_notification
from user_agents import parse
from buyercall.blueprints.user.utilities.get_request_location import UserUtilities
# fetch user-agent details
user_agent = parse(request.user_agent.string)
# get partnership name from user
partnership_name = u.get_partnership_name(u) or u.email
# get partnership logo
if u.partnership_id:
partnership_logo = u.partnership.logo
else:
partnership_logo = None
# get location details based on ip
user_ip = request.environ.get('HTTP_X_FORWARDED_FOR') \
if request.environ.get('HTTP_X_FORWARDED_FOR') else request.remote_addr
data = UserUtilities().get_request_complete_details(user_ip)
# password reset url
reset_token = u.serialize_token()
# send email for new user-agent to user
send_new_os_notification.delay(username=u.name or u.email,
partnership_name=partnership_name,
reset_token=reset_token,
location=f"{data.get('city')},"
f" {data.get('regionName')},"
f" {data.get('country')}" if data else None,
subject=f"New login alert to {partnership_name},"
f" from {user_agent.browser.family} on {user_agent.os.family}",
device=f"{user_agent.browser.family}{user_agent.browser.version_string},"
f" {user_agent.os.family}{user_agent.os.version_string}",
email=u.email,
ip=data.get('query'),
partnership_logo=partnership_logo)
"""
# send email for new user-agent to support
send_support_new_os_notification.delay(partnership_name=partnership_name,
location=f"{data.get('city')},"
f" {data.get('regionName')},"
f" {data.get('country')}" if data else None,
subject=f"New login alert to {partnership_name},"
f" from {user_agent.browser.family} on {user_agent.os.family} ",
device=f"{user_agent.browser.family}{user_agent.browser.version_string},"
f" {user_agent.os.family}{user_agent.os.version_string}",
email=u.email,
ip=data.get('query'),
partnership_logo=partnership_logo)
"""
# end start logic to save user-agent
# start password expiry check
reset_token = u.serialize_token()
password_status = u.get_password_expire_status(u)
if not password_status:
# Construct the URL with the reset_token as a query parameter
reset_url = url_for('user.password_reset') + f"?reset_token={reset_token}"
# Redirect to the reset URL
flash(_('Your password has expired, please reset your password'), 'danger')
return redirect(reset_url)
# end password expiry check
# Check to see if the user has done security on-boarding yet
if not u.two_factor_auth_onboard:
return redirect(url_for('user.additional_user_security_onboarding',
user_id=u.id,
url=next_url,
remember=remember))
<<<<<<< HEAD
# Have the user verify their account with two-factor authentication
# if two_factor_auth is set to True
if u.two_factor_auth:
ActivityLogs.add_log(u.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_SUCCESS, request)
if u.partnership is None:
p_name = ''
p_no = ''
else:
p_name = u.partnership.name
p_no = u.partnership.operational_number
code = send_verification_code(format_phone_number(u.phonenumber), p_name, p_no)
log.info('the verification code is: {}'.format(code))
=======
# Has the user verified their account with two-factor authentication
# if two_factor_auth is set to True
if u.two_factor_auth:
ActivityLogs.add_log(u.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_SUCCESS, request)
send_verification_code(u)
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
return redirect(url_for('user.two_factor_auth',
user_id=u.id,
url=next_url,
remember=remember))
# Has the user agreed to tos
if not u.tos_agreement:
ActivityLogs.add_log(u.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_SUCCESS, request)
return redirect(url_for('user.tos_get',
user_id=u.id,
url=next_url,
remember=remember))
# Login the user and redirect them to the appropriate page
if u.active and login_user(u, remember=remember):
ActivityLogs.add_log(u.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_SUCCESS, request)
u.update_activity_tracking(request.remote_addr)
# Reset failed login attempts on successful login
FailedLoginNotifier(u).reset_attempt()
# Handle optionally redirecting to the next URL safely
if next_url:
return redirect(safe_next_url(next_url))
<<<<<<< HEAD
if current_user.role in ['sysadmin', 'limitsysadmin', 'partner'] and not current_user.is_admin_user_with_groups:
=======
if current_user.role in ['sysadmin', 'limitsysadmin',
'partner'] and not current_user.is_admin_user_with_groups:
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
return redirect(url_for('admin.dashboard'))
elif current_user.role in ['admin'] and current_user.is_admin_user_with_groups \
and current_user.is_viewing_partnership \
and current_user.get_user_viewing_partnership_account_subscription_plan != 'partnershipsingle':
return redirect(url_for('dashboard.user_dashboard_old'))
elif current_user.role in ['admin'] and current_user.is_admin_user_with_groups \
and current_user.is_viewing_partnership \
and current_user.get_user_viewing_partnership_account_subscription_plan == 'partnershipsingle':
return redirect(url_for('contacts.contact_list'))
elif current_user.is_admin_user_with_groups:
return redirect(url_for('partnership.company_accounts'))
elif current_user.role in ['agent'] and current_user.subscription.plan != 'partnershipsingle':
return redirect(url_for('contacts.contact_list'))
elif current_user.subscription and current_user.subscription.plan == 'partnershipsingle':
return redirect(url_for('user.settings'))
else:
return redirect(url_for('dashboard.user_dashboard_old'))
else:
ActivityLogs.add_log(u.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_FAILED, request)
<<<<<<< HEAD
flash(_('This account has been disabled.'), 'danger')
else:
if u:
ActivityLogs.add_log(u.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_FAILED, request)
flash(_('Email or password is incorrect.'), 'danger')
=======
if FailedLoginNotifier(u).notify():
flash(_("We’ve detected 3 failed attempts to login. The account has been temporarily locked. "
"Please try again in 15 minutes."), 'danger')
else:
flash(_('This account has been disabled.'), 'danger')
else:
if u:
ActivityLogs.add_log(u.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_FAILED, request)
# Set user login failed attempts
if FailedLoginNotifier(u).notify():
flash(_("We’ve detected 3 failed attempts to login. The account has been temporarily locked. "
"Please try again in 15 minutes."), 'danger')
else:
flash(_('Email address or password is incorrect.'), 'danger')
# save email id posted to the request log error
from buyercall.blueprints.sysadmin.models import RequestLog
import json
request_id = request.environ.get('HTTP_X_REQUEST_ID')
# updating the request log with the error
RequestLog().update_record(
request_id, {"error": f"Login Failed with email: {request.form.get('identity').lower()}"})
flash(_('Identity or password is incorrect.'), 'danger')
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
except Exception as e:
print(f"The exception in login is {e}")
log.error(traceback.format_exc())
if u:
log.info('There is an issue with the password for user: {}'.format(u.email))
ActivityLogs.add_log(u.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_FAILED, request)
<<<<<<< HEAD
flash(_("There is a problem with your password. Please reset your password by clicking on "
"the 'forget your password?' link below the submit button."), 'danger')
return render_template('user/login_old.jinja2', form=form)
# Ask the user if they want to do 2 factor authentication onboarding page
# The user will be able to enable 2 factor authentication, which will be
# prompted every time they login
@user.route('/additional_user_security/<uuid:user_sid>', methods=['GET', 'POST'])
def additional_user_security_onboarding(user_sid):
domain = request.host.replace('www', '')
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_url = primary_partner.partner_url
partner_custom_styles = primary_partner.custom_styles
partner_name = primary_partner.name
partners = Partnership.query.filter(Partnership.active.is_(True)).all()
for partner in partners:
if partner.partner_url and partner.id != 1:
partner_domain = partner.partner_url.replace('https://', '').replace('www', '')
if partner_domain == domain:
partner_url = partner_domain
if partner.custom_styles:
partner_custom_styles = partner.custom_styles
partner_name = partner.name
# Find the current active user in the database
active_user = User.query.filter(User.sid == user_sid, User.is_deactivated.is_(False)).first()
# The form allowing the user to update their phone number, which will
# receive the sms two-factor authentication
form = UpdatePhoneNumber(phonenumber=active_user.phonenumber)
# Gather the next url from the request. This is the
# url the user intends to visit after doing the on-boarding
next_url = request.args.get('url')
# Get the 'remember me' boolean from the request
remember = request.args.get('remember')
if remember == 'True':
remember = True
else:
remember = False
# Get partnership details by partner_url
partnership = get_partnership()
partnership_logo = partnership.alternative_logo
if '::' in partnership_logo:
bucket_name, key = partnership_logo.split("::")
partnership_logo = generate_presigned_file_url(key, bucket_name)
if form.validate_on_submit():
active_user.phonenumber = request.form.get('phonenumber')
# Set the on-boarding field to true. If set to True
# the user will not see the on-boarding screen again
active_user.two_factor_auth_onboard = True
# By setting two_factor_auth True two-factor authentication will
# be enabled for the user
active_user.two_factor_auth = True
db.session.commit()
flash(_('Great. Two step verification has been enabled on your account. After'
' logging in you will be asked to verify your account through a verification code.'), 'success')
# Redirect the user back to log in them to use the two-step verification
return redirect(url_for('user.login'))
return render_template('user/two_factor_auth_onboarding.jinja2', form=form,
user=active_user,
next_url=next_url,
remember=remember,
partner_custom_styles=partner_custom_styles,
partner_url=partner_url,
partner_name=partner_name,
partnership_logo=partnership_logo
)
# This function gets called when the user decides to decline two-factor authentication
# on the on-boarding page
@user.route('/decline_additional_securty/<uuid:user_sid>', methods=['GET', 'POST'])
def decline_additional_security(user_sid):
active_user = User.query.filter(User.sid == user_sid, User.is_deactivated.is_(False)).first()
next_url = request.args.get('url')
remember = request.args.get('remember')
if remember == 'True':
remember = True
else:
remember = False
if request.method == 'POST':
active_user.two_factor_auth_onboard = True
active_user.two_factor_auth = False
flash(_('You have opted out of two step verification. You can enable it at any time under '
'your account settings. two step verification will help keep your account extra secure.'), 'warning')
# Has the user agreed to the terms and conditions
if active_user.active and active_user.tos_agreement is False:
return redirect(url_for('user.tos_get',
user_id=active_user.id,
url=next_url,
remember=remember))
# Login the user and redirect them to the appropriate page
if active_user.active and login_user(active_user, remember=remember):
ActivityLogs.add_log(current_user.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_SUCCESS, request)
active_user.update_activity_tracking(request.remote_addr)
partnership = Partnership.query.filter(Partnership.id == active_user.partnership_id).first()
if not partnership:
partnership = Partnership.query.get(1)
if next_url:
return redirect(safe_next_url(next_url))
if active_user.role in ['sysadmin', 'limitsysadmin', 'partner']:
return redirect(url_for('admin.dashboard'))
elif active_user.role in ['agent'] and current_user.subscription.plan != 'partnershipsingle':
return redirect(url_for('contacts.contact_list'))
elif active_user.subscription and active_user.subscription.plan == 'partnershipsingle':
return redirect(url_for('user.settings'))
else:
return redirect(url_for('dashboard.user_dashboard'))
else:
ActivityLogs.add_log(current_user.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_FAILED, request)
flash(_('This account has been disabled.'), 'danger')
=======
# Set user login failed attempts
if FailedLoginNotifier(u).notify():
flash(_("We’ve detected 3 failed attempts to login. The account has been temporarily locked. "
"Please try again in 15 minutes."), 'danger')
else:
flash(_("There is a problem with your password. Please reset your password by clicking on "
"the 'forget your password?' link below the submit button."), 'danger')
else:
flash(_("There is a problem with your password. Please reset your password by clicking on "
"the 'forget your password?' link below the submit button."), 'danger')
flash(_("There is a problem with your password. Please reset your password by clicking on "
"the 'forget your password?' link below the submit button."), 'danger')
return render_template('user/login.jinja2', white_label=white_label, partner_logo=partner_logo,
partner_name=partner_name, partner_url=partner_url,
partner_custom_styles=partner_custom_styles, form=form,
site_key=current_app.config.get('RC_SITE_KEY_V3'))
# Ask the user if they want to do 2-factor authentication onboarding page
# The user will be able to enable 2-factor authentication, which will be
# prompted every time they log in
@user.route('/additional_user_security/<int:user_id>', methods=['GET', 'POST'])
def additional_user_security_onboarding(user_id):
# Find the current active user in the database
active_user = User.query.filter(User.id == user_id, User.is_deactivated.is_(False)).first()
if active_user and active_user.email.lower() == session.get('user_identify'):
choice_len = 0
domain = request.host.replace('www', '')
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_url = primary_partner.partner_url
partner_custom_styles = primary_partner.custom_styles
partner_name = primary_partner.name
partners = Partnership.query.filter(Partnership.active.is_(True)).all()
for partner in partners:
if partner.partner_url and partner.id != 1:
partner_domain = partner.partner_url.replace('https://', '').replace('www', '')
if partner_domain == domain:
partner_url = partner_domain
if partner.custom_styles:
partner_custom_styles = partner.custom_styles
partner_name = partner.name
form = UpdateSecurity()
crt_user_phone = format_phone_number_bracket(active_user.phonenumber)
crt_user_email = active_user.email
sms_label = 'SMS - ' + crt_user_phone
email_label = 'Email - ' + crt_user_email
# Generate choices based on boolean fields from the database
choices = []
if active_user.role in ('admin', 'agent'):
if active_user.partnership.is_2fa_sms_enabled and active_user.partnership_account.is_2fa_sms_enabled:
choices.append(('field1', sms_label))
if active_user.partnership.is_2fa_email_enabled and active_user.partnership_account.is_2fa_email_enabled:
if active_user.partnership.is_2fa_sms_enabled and active_user.partnership_account.is_2fa_sms_enabled:
choices.append(('field2', email_label))
else:
choices.append(('field1', email_label))
elif active_user.role == 'partner':
if active_user.partnership.is_2fa_sms_enabled:
choices.append(('field1', sms_label))
if active_user.partnership.is_2fa_email_enabled:
if active_user.partnership.is_2fa_sms_enabled:
choices.append(('field2', email_label))
else:
choices.append(('field1', email_label))
elif active_user.role in ('sysadmin', 'limitsysadmin'):
choices.append(('field1', sms_label))
choices.append(('field2', email_label))
form.choice.choices = choices
if len(choices) > 1:
choice_len = 2
# Gather the next url from the request. This is the
# url the user intends to visit after doing the on-boarding
next_url = request.args.get('url')
# Get the 'remember me' boolean from the request
remember = request.args.get('remember', 'False')
if remember == 'True':
remember = True
else:
remember = False
if form.validate_on_submit():
if form.auth_method.data == 'SMS':
active_user.is_2fa_sms = True
active_user.is_2fa_email = False
elif form.auth_method.data == 'EMAIL':
active_user.is_2fa_sms = False
active_user.is_2fa_email = True
# Set the on-boarding field to true. If set to True
# the user will not see the on-boarding screen again
active_user.two_factor_auth_onboard = True
# By setting two_factor_auth True two-factor authentication will
# be enabled for the user
active_user.two_factor_auth = True
db.session.commit()
flash(_('Great. Two step verification has been enabled on your account. After'
' logging in you will be asked to verify your account through a verification code.'), 'success')
# Redirect the user back to log in them to use the two-step verification
return redirect(url_for('user.login'))
return render_template('user/two_factor_auth_onboarding.jinja2', form=form,
user=active_user,
next_url=next_url,
remember=remember,
partner_custom_styles=partner_custom_styles,
partner_url=partner_url,
partner_name=partner_name,
choice_len=choice_len
)
else:
flash(_('We were unable to identify your account. Please try again or contact support.'), 'danger')
# Redirect the user back to log in due to failing session check
return redirect(url_for('user.login'))
# This function gets called when the user decides to decline two-factor authentication
# on the on-boarding page
@user.route('/decline_additional_securty/<int:user_id>', methods=['GET', 'POST'])
def decline_additional_security(user_id):
active_user = User.query.filter(User.id == user_id, User.is_deactivated.is_(False)).first()
if active_user and active_user.email.lower() == session.get('user_identify'):
next_url = request.args.get('url')
remember = request.args.get('remember', 'False')
if remember == 'True':
remember = True
else:
remember = False
if request.method == 'POST':
active_user.two_factor_auth_onboard = True
active_user.two_factor_auth = False
db.session.commit()
# Has the user agreed to the terms and conditions
if active_user.active and active_user.tos_agreement is False:
return redirect(url_for('user.tos_get',
user_id=active_user.id,
url=next_url,
remember=remember))
# Login the user and redirect them to the appropriate page
"""
if active_user.active and login_user(active_user, remember=remember):
ActivityLogs.add_log(current_user.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_SUCCESS, request)
active_user.update_activity_tracking(request.remote_addr)
if next_url:
return redirect(safe_next_url(next_url))
if active_user.role in ['sysadmin', 'limitsysadmin', 'partner']:
return redirect(url_for('admin.dashboard'))
elif active_user.role in ['agent'] and current_user.subscription.plan != 'partnershipsingle':
return redirect(url_for('contacts.contact_list'))
elif active_user.subscription and active_user.subscription.plan == 'partnershipsingle':
return redirect(url_for('user.settings'))
else:
return redirect(url_for('dashboard.user_dashboard'))
else:
ActivityLogs.add_log(current_user.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_FAILED, request)
flash(_('This account has been disabled.'), 'danger')
return redirect(url_for('user.login'))
"""
flash(_('You have opted out of two step verification. You can enable it at any time under '
'your account settings, which we highly recommend. Please login to continue.'), 'warning')
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
return redirect(url_for('user.login'))
else:
flash(_('We were unable to decline your actions. Please try again or contact support.'), 'danger')
# Redirect the user back to log in due to failing session check
return redirect(url_for('user.login'))
<<<<<<< HEAD
# This function allows the user to skip the two-factor authentication on-boarding
=======
"""
# This function allows the user to skip the two factor authentication on-boarding
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
# until the next time they log in.
@user.route('/skip_additional_security/<uuid:user_sid>', methods=['GET', 'POST'])
def skip_additional_security(user_sid):
active_user = User.query.filter(User.sid == user_sid, User.is_deactivated.is_(False)).first()
next_url = request.args.get('url')
remember = request.args.get('remember', 'False')
if remember == 'True':
remember = True
else:
remember = False
active_user.two_factor_auth_onboard = False
active_user.two_factor_auth = False
db.session.commit()
flash(_('You have opted to skip the two step verification setup for now. We will ask you again next '
'time you login.'), 'warning')
# Has the user agreed to the terms and conditions
<<<<<<< HEAD
if active_user.active and active_user.tos_agreement is False:
return redirect(url_for('user.tos_get',
user_id=active_user.id,
url=next_url,
remember=remember))
=======
#if active_user.active and active_user.tos_agreement is False:
# return redirect(url_for('user.tos_get',
# user_id=active_user.id,
# url=next_url,
# remember=remember))
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
# Login the user and redirect them to the appropriate page
if active_user.active and login_user(active_user, remember=remember):
ActivityLogs.add_log(current_user.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_SUCCESS, request)
active_user.update_activity_tracking(request.remote_addr)
partnership = Partnership.query.filter(Partnership.id == active_user.partnership_id).first()
if not partnership:
partnership = Partnership.query.get(1)
if next_url:
return redirect(safe_next_url(next_url))
if active_user.role in ['sysadmin', 'limitsysadmin', 'partner']:
return redirect(url_for('admin.dashboard'))
elif active_user.role in ['agent'] and current_user.subscription.plan != 'partnershipsingle':
return redirect(url_for('contacts.contact_list'))
elif active_user.subscription.plan == 'partnershipsingle':
return redirect(url_for('user.settings'))
else:
return redirect(url_for('dashboard.user_dashboard'))
else:
ActivityLogs.add_log(current_user.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_FAILED, request)
flash(_('This account has been disabled.'), 'danger')
return redirect(url_for('user.login'))
"""
# This function will be called if two-factor authentication is enabled
# for the user. The user will need to enter a verification code
<<<<<<< HEAD
@user.route('/verification/<uuid:user_sid>', methods=['POST', 'GET'])
def two_factor_auth(user_sid):
# Grab the next url if available as argument to send the user
# to if they did 2-factor auth
domain = request.host.replace('www', '')
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_url = primary_partner.partner_url
partner_custom_styles = primary_partner.custom_styles
partners = Partnership.query.filter(Partnership.active.is_(True)).all()
for partner in partners:
if partner.partner_url and partner.id != 1:
partner_domain = partner.partner_url.replace('https://', '').replace('www', '')
if partner_domain == domain:
partner_url = partner_domain
if partner.custom_styles:
partner_custom_styles = partner.custom_styles
# Grab the next url if available as argument to send the user
# to if they did 2 factor auth
active_user = User.query.filter(User.sid == user_sid, User.is_deactivated.is_(False)).first()
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_name = primary_partner.name
user_partnership = Partnership.query.filter(Partnership.id == active_user.partnership_id).first()
if user_partnership is not None:
partner_name = user_partnership.name
next_url = request.args.get('url')
remember = request.args.get('remember')
partnership = get_partnership()
partnership_logo = partnership.alternative_logo
if '::' in partnership_logo:
bucket_name, key = partnership_logo.split("::")
partnership_logo = generate_presigned_file_url(key, bucket_name)
if remember == 'True':
remember = True
else:
remember = False
active_user = User.query.filter(User.sid == user_sid, User.is_deactivated.is_(False)).first()
user_number = format_phone_number_bracket(active_user.phonenumber)
log.info('the number is {}'.format(user_number))
form = TwoFactorAuthForm()
if form.validate_on_submit():
# Compare the code sent to the user and the one saved in the session
if request.form['code'] == session['verification_code']:
ActivityLogs.add_log(active_user.id, ActivityType.AUTHORIZATION, ActivityName.TWOFACTAUTH_SUCCESS, request)
# Has the user agreed to the terms and conditions
if active_user.active and active_user.tos_agreement is False:
return redirect(url_for('user.tos_get',
user_id=active_user.id,
url=next_url,
remember=remember))
# Login the user and redirect them to the appropriate page
if active_user.active and login_user(active_user, remember=remember):
active_user.update_activity_tracking(request.remote_addr)
partnership = Partnership.query.filter(Partnership.id == active_user.partnership_id).first()
if not partnership:
partnership = Partnership.query.get(1)
# Handle optionally redirecting to the next URL safely.
if next_url:
return redirect(safe_next_url(next_url))
if current_user.role in ['sysadmin', 'limitsysadmin', 'partner']:
return redirect(url_for('admin.dashboard'))
elif current_user.role in ['agent'] and current_user.subscription.plan != 'partnershipsingle':
return redirect(url_for('contacts.contact_list'))
elif current_user.subscription.plan == 'partnershipsingle':
return redirect(url_for('user.settings'))
else:
return redirect(url_for('dashboard.user_dashboard'))
else:
flash(_('This account has been disabled.'), 'danger')
return redirect(url_for('user.login'))
else:
ActivityLogs.add_log(active_user.id, ActivityType.AUTHORIZATION, ActivityName.TWOFACTAUTH_FAILED, request)
flash(_('You have entered an incorrect verification code. Please try again.'), 'danger')
return redirect(url_for('user.two_factor_auth',
user_sid=active_user.sid,
url=next_url,
remember=remember))
else:
log.error(f'Form error: {form.errors}')
# Allow the user to resend the verification code if they didn't
# receive it first time round
if request.method == 'POST':
if 'btn_resend_code' in request.form:
if request.form['btn_resend_code'] == 'btn_resend_code':
try:
send_verification_code(active_user.phonenumber)
flash(_('Code sent successfully.'), 'info')
log.info('The remember me value is {}'.format(remember))
return redirect(url_for('user.two_factor_auth',
user_sid=active_user.sid,
url=next_url,
remember=remember))
except Exception as e:
log.debug(
'There was a problem sending a verification code for user sid: {}'.format(active_user.sid))
return render_template('user/two_factor_auth.jinja2',
partner_name=partner_name,
form=form,
user=active_user,
user_number=user_number,
next_url=next_url,
remember=remember,
partner_custom_styles=partner_custom_styles,
partner_url=partner_url,
partnership_logo=partnership_logo
)
=======
@user.route('/verification/<int:user_id>', methods=['POST', 'GET'])
def two_factor_auth(user_id):
active_user = User.query.filter(User.id == user_id, User.is_deactivated.is_(False)).first()
if active_user and active_user.email.lower() == session.get('user_identify'):
domain = request.host.replace('www', '')
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_url = primary_partner.partner_url
partner_custom_styles = primary_partner.custom_styles
partners = Partnership.query.filter(Partnership.active.is_(True)).all()
for partner in partners:
if partner.partner_url and partner.id != 1:
partner_domain = partner.partner_url.replace('https://', '').replace('www', '')
if partner_domain == domain:
partner_url = partner_domain
if partner.custom_styles:
partner_custom_styles = partner.custom_styles
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_name = primary_partner.name
user_partnership = Partnership.query.filter(Partnership.id == active_user.partnership_id).first()
if user_partnership is not None:
partner_name = user_partnership.name
next_url = request.args.get('url')
remember = request.args.get('remember', 'False')
if remember == 'True':
remember = True
else:
remember = False
user_number = format_phone_number_bracket(active_user.phonenumber)
form = TwoFactorAuthForm()
if form.validate_on_submit():
# Compare the code sent to the user and the one saved in the session
if request.form['code'] == session['verification_code']:
ActivityLogs.add_log(active_user.id, ActivityType.AUTHORIZATION, ActivityName.TWOFACTAUTH_SUCCESS, request)
# Has the user agreed to the terms and conditions
if active_user.active and active_user.tos_agreement is False:
return redirect(url_for('user.tos_get',
user_id=active_user.id,
url=next_url,
remember=remember))
# Login the user and redirect them to the appropriate page
if active_user.active and login_user(active_user, remember=remember):
active_user.update_activity_tracking(request.remote_addr)
# Handle optionally redirecting to the next URL safely.
if next_url:
return redirect(safe_next_url(next_url))
if current_user.role in ['sysadmin', 'limitsysadmin', 'partner']:
return redirect(url_for('admin.dashboard'))
elif current_user.role in ['agent'] and current_user.subscription.plan != 'partnershipsingle':
return redirect(url_for('contacts.contact_list'))
elif current_user.subscription.plan == 'partnershipsingle':
return redirect(url_for('user.settings'))
else:
return redirect(url_for('dashboard.user_dashboard'))
else:
flash(_('This account has been disabled.'), 'danger')
return redirect(url_for('user.login'))
else:
ActivityLogs.add_log(active_user.id, ActivityType.AUTHORIZATION, ActivityName.TWOFACTAUTH_FAILED, request)
flash(_('You have entered an incorrect verification code. Please try again.'), 'danger')
return redirect(url_for('user.two_factor_auth',
user_id=active_user.id,
url=next_url,
remember=remember))
# Allow the user to resend the verification code if they didn't
# receive it first time round
if request.method == 'POST':
if request.form['btn_resend_code'] == 'btn_resend_code':
try:
send_verification_code(active_user)
log.info('The remember me value is {}'.format(remember))
return redirect(url_for('user.two_factor_auth',
user_id=active_user.id,
url=next_url,
remember=remember))
except Exception as e:
log.debug('There was a problem sending a verification code for user id: {}'.format(active_user.id))
return render_template('user/two_factor_auth.jinja2',
partner_name=partner_name,
form=form,
user=active_user,
user_number=user_number,
next_url=next_url,
remember=remember,
partner_custom_styles=partner_custom_styles,
partner_url=partner_url,
partner_id=partner.id
)
else:
flash(_('We were unable to complete your actions. Please try again or contact support.'), 'danger')
# Redirect the user back to log in due to failing session check
return redirect(url_for('user.login'))
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
@user.route('/tos/<int:user_id>', methods=['GET'])
def tos_get(user_id):
<<<<<<< HEAD
domain = request.host.replace('www', '')
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_url = primary_partner.partner_url
partner_custom_styles = primary_partner.custom_styles
partners = Partnership.query.filter(Partnership.active.is_(True)).all()
for partner in partners:
if partner.partner_url and partner.id != 1:
partner_domain = partner.partner_url.replace('https://', '').replace('www', '')
if partner_domain == domain:
partner_url = partner_domain
if partner.custom_styles:
partner_custom_styles = partner.custom_styles
active_user = User.query.filter(User.id == user_id, User.is_deactivated.is_(False)).first()
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_name = primary_partner.name
user_partnership = Partnership.query.filter(Partnership.id == active_user.partnership_id).first()
if user_partnership is not None:
partner_name = user_partnership.name
if active_user:
=======
print(session.get('user_identify'))
active_user = User.query.filter(User.id == user_id, User.is_deactivated.is_(False)).first()
if active_user and active_user.email.lower() == session.get('user_identify'):
domain = request.host.replace('www', '')
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_url = primary_partner.partner_url
partner_custom_styles = primary_partner.custom_styles
partners = Partnership.query.filter(Partnership.active.is_(True)).all()
for partner in partners:
if partner.partner_url and partner.id != 1:
partner_domain = partner.partner_url.replace('https://', '').replace('www', '')
if partner_domain == domain:
partner_url = partner_domain
if partner.custom_styles:
partner_custom_styles = partner.custom_styles
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_name = primary_partner.name
user_partnership = Partnership.query.filter(Partnership.id == active_user.partnership_id).first()
if user_partnership is not None:
partner_name = user_partnership.name
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
if active_user.is_deactivated is True:
flash(_('This account has been disabled.'), 'danger')
return redirect(url_for('user.login'))
else:
return render_template('user/tos.jinja2',
partner_name=partner_name,
user=active_user,
partner_url=partner_url,
<<<<<<< HEAD
partner_custom_styles=partner_custom_styles)
else:
=======
partner_custom_styles=partner_custom_styles,
partner_id=partner.id)
else:
flash(_('We were unable to complete your TOS action. Please try again or contact support.'), 'danger')
# Redirect the user back to log in due to failing session check
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
return redirect(url_for('user.login'))
@user.route('/tos_agree/<int:user_id>', methods=['POST'])
def tos_agree_post(user_id):
<<<<<<< HEAD
next_url = request.args.get('url')
remember = request.args.get('remember')
if remember == 'True':
remember = True
else:
remember = False
active_user = User.query.filter(User.id == user_id, User.is_deactivated.is_(False)).first()
if active_user:
active_user.tos_agreement = True
ActivityLogs.add_log(active_user.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_ACCEPTTERMS, request)
db.session.commit()
=======
active_user = User.query.filter(User.id == user_id, User.is_deactivated.is_(False)).first()
if active_user and active_user.email.lower() == session.get('user_identify'):
next_url = request.args.get('url')
remember = request.args.get('remember', 'False')
if remember == 'True':
remember = True
else:
remember = False
active_user.tos_agreement = True
ActivityLogs.add_log(active_user.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_ACCEPTTERMS, request)
db.session.commit()
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
# Login the user and redirect them to the appropriate page
if active_user.active and login_user(active_user, remember=remember):
active_user.update_activity_tracking(request.remote_addr)
# Handle optionally redirecting to the next URL safely.
if next_url:
<<<<<<< HEAD
return redirect(safe_next_url(next_url))
if current_user.role in ['sysadmin', 'limitsysadmin', 'partner']:
return redirect(url_for('admin.dashboard'))
elif current_user.role in ['agent'] and current_user.subscription.plan != 'partnershipsingle':
return redirect(url_for('contacts.contact_list'))
elif current_user.subscription.plan == 'partnershipsingle':
return redirect(url_for('user.settings'))
else:
=======
flash(_('Thank you for accepting our Terms of Service.'), 'success')
return redirect(safe_next_url(next_url))
if current_user.role in ['sysadmin', 'limitsysadmin', 'partner']:
flash(_('Thank you for accepting our Terms of Service.'), 'success')
return redirect(url_for('admin.dashboard'))
elif current_user.role in ['agent'] and current_user.subscription.plan != 'partnershipsingle':
flash(_('Thank you for accepting our Terms of Service.'), 'success')
return redirect(url_for('contacts.contact_list'))
elif current_user.subscription.plan == 'partnershipsingle':
flash(_('Thank you for accepting our Terms of Service.'), 'success')
return redirect(url_for('user.settings'))
else:
flash(_('Thank you for accepting our Terms of Service.'), 'success')
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
return redirect(url_for('dashboard.user_dashboard'))
else:
flash(_('This account has been disabled.'), 'danger')
ActivityLogs.add_log(active_user.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_FAILED, request)
return redirect(url_for('user.login'))
<<<<<<< HEAD
return redirect(url_for('user.login'))
=======
else:
flash(_('We were unable to complete your TOS confirmation. Please try again or contact support.'), 'danger')
# Redirect the user back to log in due to failing session check
return redirect(url_for('user.login'))
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
@user.route('/tos_disagree/<int:user_id>', methods=['POST'])
def tos_disagree_post(user_id):
active_user = User.query.filter(User.id == user_id, User.is_deactivated.is_(False)).first()
<<<<<<< HEAD
if active_user:
active_user.tos_agreement = False
ActivityLogs.add_log(active_user.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_DECLINETERMS, request)
db.session.commit()
return redirect(url_for('user.login'))
return redirect(url_for('user.login'))
=======
if active_user and active_user.email.lower() == session.get('user_identify'):
active_user.tos_agreement = False
ActivityLogs.add_log(active_user.id, ActivityType.AUTHORIZATION, ActivityName.LOGIN_DECLINETERMS, request)
db.session.commit()
flash(_('We require acceptance of our Terms of Service to continue. '
'Please contact support if you have any questions.'), 'danger')
return redirect(url_for('user.login'))
else:
flash(_('We were unable to complete your TOS declaration. Please try again or contact support.'), 'danger')
return redirect(url_for('user.login'))
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
@user.route('/logout')
@login_required
def logout():
# logging out supervisor as well
if current_supervisor_user.is_authenticated:
supervisor_logout_user()
ActivityLogs.add_log(current_user.id, ActivityType.AUTHORIZATION, ActivityName.LOGOUT, request)
logout_user()
flash(_('You have been logged out.'), 'success')
return redirect(url_for('user.login'))
@user.route('/account/begin_password_reset', methods=['GET', 'POST'])
@anonymous_required()
def begin_password_reset():
domain = request.host.replace('www', '')
white_label = False
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_name = primary_partner.name
partner_url = primary_partner.partner_url
partner_custom_styles = primary_partner.custom_styles
partners = Partnership.query.filter(Partnership.active.is_(True)).all()
for partner in partners:
if partner.partner_url and partner.id != 1:
partner_domain = partner.partner_url.replace('https://', '').replace('www', '')
if partner_domain == domain:
partner_url = partner_domain
white_label = True
if partner.custom_styles:
partner_custom_styles = partner.custom_styles
partner_name = partner.name
form = BeginPasswordResetForm()
# Get partnership details by partner_url
partnership = get_partnership()
partnership_logo = partnership.alternative_logo
if '::' in partnership_logo:
bucket_name, key = partnership_logo.split("::")
partnership_logo = generate_presigned_file_url(key, bucket_name)
if form.validate_on_submit():
user_email = request.form.get('identity')
u = User.initialize_password_reset(user_email.lower())
log.info('The user email requesting a password reset is: {}'.format(user_email.lower()))
flash(_('An email has been sent to %(email)s.',
email=u.email), 'success')
return redirect(url_for('user.login'))
return render_template('user/begin_password_reset.jinja2', form=form, partner_name=partner_name,
white_label=white_label, partner_url=partner_url,
<<<<<<< HEAD
partner_custom_styles=partner_custom_styles, partnership_logo=partnership_logo)
=======
partner_custom_styles=partner_custom_styles)
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
@user.route('/account/password_reset', methods=['GET', 'POST'])
@anonymous_required()
def password_reset():
domain = request.host.replace('www', '')
white_label = False
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_name = primary_partner.name
partner_url = primary_partner.partner_url
partner_custom_styles = primary_partner.custom_styles
partners = Partnership.query.filter(Partnership.active.is_(True)).all()
for partner in partners:
if partner.partner_url and partner.id != 1:
partner_domain = partner.partner_url.replace('https://', '').replace('www', '')
if partner_domain == domain:
partner_url = partner_domain
white_label = True
if partner.custom_styles:
partner_custom_styles = partner.custom_styles
partner_name = partner.name
<<<<<<< HEAD
form = PasswordResetForm(reset_token=request.args.get('reset_token'))
# Get partnership details by partner_url
partnership = get_partnership()
partnership_logo = partnership.alternative_logo
if '::' in partnership_logo:
bucket_name, key = partnership_logo.split("::")
partnership_logo = generate_presigned_file_url(key, bucket_name)
if form.validate_on_submit():
u = User.deserialize_token(request.form.get('reset_token'))
if not u:
flash(_('Your reset token has expired or was tampered with.'),
'danger')
return redirect(url_for('user.begin_password_reset'))
form.populate_obj(u)
u.password = User.encrypt_password(request.form.get('password', None))
u.save()
# Send notification
partnership = Partnership.query.filter(Partnership.id == u.partnership_id).first()
if not partnership:
partnership = Partnership.query.get(1)
es_data = {
'user_id': u.sid,
'notify_message_type': 'PASSWORD_RESET',
'user_related_entities': "You've",
'other_user_related_entities': f'{u.firstname} {u.lastname}',
'hyperlink': f'{partnership.partner_url}/settings'
}
response = send_notifications(**es_data)
if login_user(u):
flash(_('Your password has been reset.'), 'success')
return redirect(url_for('user.settings'))
return render_template('user/password_reset.jinja2', form=form, partnership=partnership, partnership_logo=partnership_logo)
@user.route('/account/password_reset_old', methods=['GET', 'POST'])
@anonymous_required()
def password_reset_old():
=======
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
form = PasswordResetForm(reset_token=request.args.get('reset_token'))
if form.validate_on_submit():
u = User.deserialize_token(request.form.get('reset_token'))
if u is None:
flash(_('Your reset token has expired or was tampered with.'),
'danger')
return redirect(url_for('user.begin_password_reset'))
# start check old password is same as new password
status = User.check_password_match(u.password, request.form.get('password', None))
if status:
ActivityLogs.add_log(u.id, ActivityType.AUTHORIZATION, ActivityName.PASSWORDRESET_FAILED, request)
flash(_('your password is same as old password, please try a new one.'), 'danger')
# Construct the URL with the reset_token as a query parameter
reset_url = url_for('user.password_reset') + f"?reset_token={request.form.get('reset_token')}"
# Redirect to the reset URL
return redirect(reset_url)
# end check old password is same as new password
form.populate_obj(u)
u.password = User.encrypt_password(request.form.get('password', None))
u.save()
# save password updated date
u.save_password_updated_date()
ActivityLogs.add_log(u.id, ActivityType.AUTHORIZATION, ActivityName.PASSWORDRESET_SUCCESS, request)
#redirect to login page
flash(_('Your password has been reset.'), 'success')
return redirect(url_for('user.login'))
return render_template('user/password_reset.jinja2', form=form, white_label=white_label,
partner_name=partner_name, partner_url=partner_url,
partner_custom_styles=partner_custom_styles)
@user.route('/signup', methods=['GET', 'POST'])
@anonymous_required()
# TODO: review
def signup():
<<<<<<< HEAD
try:
current_app.config['RECAPTCHA_PUBLIC_KEY'] = current_app.config['RC_SITE_KEY']
current_app.config['RECAPTCHA_PRIVATE_KEY'] = current_app.config['RC_SECRET_KEY']
=======
domain = request.host.replace('www', '')
white_label = False
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_name = primary_partner.name
partner_url = primary_partner.partner_url
partner_custom_styles = primary_partner.custom_styles
partners = Partnership.query.filter(Partnership.active.is_(True)).all()
for partner in partners:
if partner.partner_url and partner.id != 1:
partner_domain = partner.partner_url.replace('https://', '').replace('www', '')
if partner_domain == domain:
partner_url = partner_domain
white_label = True
if partner.custom_styles:
partner_custom_styles = partner.custom_styles
partner_name = partner.name
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
domain = request.host.replace('www', '')
white_label = False
primary_partner = Partnership.query.filter(Partnership.id == 1).first()
partner_name = primary_partner.name
partner_url = primary_partner.partner_url
partner_custom_styles = primary_partner.custom_styles
partners = Partnership.query.filter(Partnership.active.is_(True)).all()
for partner in partners:
if partner.partner_url and partner.id != 1:
partner_domain = partner.partner_url.replace('https://', '').replace('www', '')
if partner_domain == domain:
partner_url = partner_domain
white_label = True
if partner.custom_styles:
partner_custom_styles = partner.custom_styles
partner_name = partner.name
form = SignupForm()
partnership_token = request.args.get('partnership', None)
account_token = request.args.get('account', None)
partnership_ = None
<<<<<<< HEAD
partnership = Partnership.query \
.filter(Partnership.account_invitation_url_token == partnership_token) \
=======
if not partnership:
log.error('No partnership found. Most likely because no partnership token was provided.')
return redirect(url_for('page.home'))
if form.is_submitted():
form_email = request.form.get('email').lower()
u = User.query \
.filter(func.lower(User.email) == form_email) \
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
.first()
if not partnership:
log.error('No partnership found. Most likely because no partnership token was provided.')
return redirect(url_for('page.home'))
partnership_logo = partnership.alternative_logo
if '::' in partnership_logo:
bucket_name, key = partnership_logo.split("::")
partnership_logo = generate_presigned_file_url(key, bucket_name)
account = None
if partnership_token:
partnership_ = Partnership.get_by_invitation_token(partnership_token)
if not partnership_:
flash(_('Invalid partnership invitation url.'), 'danger')
return render_template('user/signup.jinja2', form=form, partnership=partnership, partnership_logo=partnership_logo)
if account_token:
account = PartnershipAccount.get_by_invitation_token(account_token)
if not account:
flash(_('Invalid account invitation url.'), 'danger')
return render_template('user/signup.jinja2', form=form, partnership=partnership, partnership_logo=partnership_logo)
if form.validate_on_submit():
form_email = request.form.get('email').lower()
u = User.query \
.filter(func.lower(User.email) == form_email) \
.first()
was_deactivated = False
<<<<<<< HEAD
if u:
if not u.is_deactivated:
form.email.errors = {'Already exists'}
return render_template('user/signup.jinja2', form=form, partnership=partnership, partnership_logo=partnership_logo)
elif u.is_deactivated:
was_deactivated = True
u.is_deactivated = False
u.deactivated_on = None
db.session.commit()
=======
if not u.is_deactivated:
form.email.errors = {'Already exists'}
return render_template('user/signup.jinja2', form=form, partnership=partnership)
elif u.is_deactivated:
was_deactivated = True
u.is_deactivated = False
u.deactivated_on = None
db.session.commit()
else:
partnership_id = partnership.id
u = User()
account = PartnershipAccount()
account.business_type = partnership.business_type
account.name = u.email if not form.company else form.company.data
account.partnership_id = partnership_id
account.billing_type = partnership.default_billing_type
if account.billing_type in ['invoice','partnership']:
account.subscription_id = partnership.subscription_id
db.session.add(account)
db.session.commit()
partnership_account_id = account.id
form.populate_obj(u)
u.password = User.encrypt_password(request.form.get('password', None))
u.partnership_id = partnership_id
u.email = request.form.get('email').lower()
u.partnership_account_id = partnership_account_id
u.role = 'admin'
u.save()
# save password updated date
u.save_password_updated_date()
agent = Agent(
user_id=u.id,
firstname=u.firstname,
lastname=u.lastname,
email=u.email,
title=u.title or '',
department=u.department or '',
phonenumber=u.phonenumber,
mobile='',
extension=u.extension or None,
partnership_account_id=partnership_account_id
)
widget = Widget(
guid=str(uuid.uuid4()),
partnership_account_id=partnership_account_id,
name='Default',
options=default
)
db.session.add(agent)
db.session.add(widget)
db.session.commit()
if login_user(u):
if was_deactivated:
flash(_('Your account has been reactivated!'), 'success')
return render_template('user/settings.jinja2')
elif account.billing_type in ['invoice','partnership']:
if current_user.role == 'partner':
return redirect(url_for('user.settings'))
else:
return redirect(url_for('user.welcome'))
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
else:
u = User()
form.populate_obj(u)
u.password = User.encrypt_password(request.form.get('password', None))
u.partnership_id = partnership.id
u.email = request.form.get('email').lower()
if partnership_:
u.role = 'partner'
u.partnership_account_id = 1
elif account:
u.partnership_account_id = account.id
u.role = 'admin'
u.save()
# account = PartnershipAccount()
# account.business_type = partnership.business_type
# account.name = u.email if not form.company else form.company.data
# account.partnership_id = partnership_id
# account.billing_type = partnership.default_billing_type
# if account.billing_type in ['invoice', 'partnership']:
# account.subscription_id = partnership.subscription_id
# db.session.add(account)
# db.session.commit()
# Send notification
# data = {
# 'user_id': u.sid,
# 'notify_message_type': 'ACCOUNT_CREATED',
# 'user_related_entities': f'{u.email}',
# 'other_user_related_entities': f'{u.email}',
# 'hyperlink': f'{partnership.partner_url}/settings'
# }
# response = send_notifications(**data)
agent = Agent(
user_id=u.id,
firstname=u.firstname,
lastname=u.lastname,
email=u.email,
title=u.title or '',
department=u.department or '',
phonenumber=u.phonenumber,
mobile='',
extension=u.extension or None,
partnership_account_id=u.partnership_account_id
)
# widget = Widget(
# guid=str(uuid.uuid4()),
# partnership_account_id=u.partnership_account_id,
# name='Default',
# options=default
# )
db.session.add(agent)
# db.session.add(widget)
db.session.commit()
# Send notification
data = {
'user_id': u.sid,
'notify_message_type': 'USER_CREATED',
'user_related_entities': f'{u.email}',
'other_user_related_entities': f'{u.email}',
'hyperlink': f'{partnership.partner_url}/settings'
}
response = send_notifications(**data)
if login_user(u):
if was_deactivated:
flash(_('Your account has been reactivated!'), 'success')
return render_template('user/settings.jinja2')
# elif account.billing_type in ['invoice', 'partnership']:
# if current_user.role == 'partner':
return redirect(url_for('dashboard.user_dashboard'))
# else:
# return redirect(url_for('dashboard.user_dashboard'))
# # else:
# flash(_('Awesome, thanks for signing up!'), 'success')
# return redirect(url_for('billing.pricing'))
except Exception as e:
print('Error : ', e)
white_label = None
form = SignupForm()
return render_template('user/signup.jinja2', form=form, partnership=partnership,
white_label=white_label, partner_name=partner_name,
partner_url=partner_url, partner_custom_styles=partner_custom_styles, partnership_logo=partnership_logo)
<<<<<<< HEAD
=======
return render_template('user/signup.jinja2', form=form, partnership=partnership,
white_label=white_label, partner_name=partner_name,
partner_url=partner_url, partner_custom_styles=partner_custom_styles)
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
@user.route('/welcome', methods=['GET', 'POST'])
@login_required
def welcome():
agent = Agent.query \
.filter(Agent.partnership_account_id == current_user.partnership_account_id).first()
if agent:
phonenumber = format_phone_number(current_user.phonenumber)
flash(_("Great, you have signed up successfully!"), 'success')
return render_template('user/welcome.jinja2', agent=agent, phonenumber=phonenumber)
else:
return render_template('user/settings.jinja2')
@user.route('/settings', methods=['GET', 'POST'])
@login_required
def settings():
<<<<<<< HEAD
# Get partnership details by partner_url
partnership = get_partnership()
profile_form = PersonalInformationForm()
security_info_form = SecurtyInformationForm()
two_factor_auth_form = UpdateSecurityForm()
theme_settings_form = ThemeSettingsForm()
# Get languages from app configurations
languages = current_app.config['LANGUAGES']
# Get login information of user
login_access_info = {'sign_in_count': current_user.sign_in_count,
'current_sign_in_on': current_user.current_sign_in_on,
'current_sign_in_ip': current_user.current_sign_in_ip,
'last_sign_in_on': current_user.last_sign_in_on,
'last_sign_in_ip': current_user.last_sign_in_ip
}
partnership = Partnership.query.filter(Partnership.id == current_user.partnership_id).first()
if not partnership:
partnership = Partnership.query.get(1)
=======
>>>>>>> 2d4ba41568adf348959bbf7b64ffa061df87d07b
if current_user.role in ['sysadmin', 'limitsysadmin']:
return render_template('sysadmin/settings.jinja2')
elif current_user.role == 'admin' and current_user.is_viewing_partnership:
return redirect(url_for('dashboard.user_dashboard'))
else:
if not partnership.partner_url:
partnership = Partnership.query.get(1)
user = User.query.get(current_user.id)
data = {
'user_id': current_user.sid,
'notify_message_type': 'PROFILE_SETTINGS_VIEWED',
'user_related_entities': ["You've", 'your'],
'other_user_related_entities': [f'{current_user.firstname} {current_user.lastname}', "his"],
'hyperlink': f'{partnership.partner_url}/settings'
}
response = send_notifications(**data)
try:
if profile_form.btn_profile_form.data and profile_form.validate_on_submit():
avatar = request.files['avatar']
if avatar:
from buyercall.lib.util_boto3_s3 import generate_presigned_file_url, upload_file_object
avatar_ext = avatar.filename.split('.')[-1]
if avatar_ext in ALLOWED_EXTENSIONS:
partnership = Partnership.query.get(current_user.partnership_id)
key = f'{partnership.name}_{partnership.sid}/avatar_{current_user.sid}.{avatar_ext}'
key = key.replace(' ', '_')
resp = upload_file_object(avatar, current_app.config['USER_AVATAR_BUCKET'], key)
user.user_avatar = f"{current_app.config['USER_AVATAR_BUCKET']}::{key}"
user.save()
else:
flash(_('Unsupported image format for profile avatar'), 'warning')
return redirect(url_for('user.settings'))
user.firstname = profile_form.first_name.data
user.lastname = profile_form.last_name.data
user.title = profile_form.job_title.data
user.department = profile_form.department.data
user.agent.timezone = profile_form.timezone.data
user.locale = profile_form.locale.data
user.save()
flash(_('Successfully updated your personal informations'), 'success')
return redirect(url_for('user.settings'))
elif profile_form.btn_profile_form.data:
flash(_(profile_form.errors), 'warning')
return redirect(url_for('user.settings'))
if security_info_form.validate_on_submit() and security_info_form.btn_security_info_form.data:
user.email = security_info_form.email_address.data
user.phonenumber = security_info_form.phone_number.data
if security_info_form.password.data:
user.password = User.encrypt_password(security_info_form.password.data)
user.save()
flash(_('Successfully updated your security informations'), 'success')
return redirect(url_for('user.settings'))
elif security_info_form.btn_security_info_form.data:
flash(_(security_info_form.errors), 'warning')
return redirect(url_for('user.settings'))
if two_factor_auth_form.validate_on_submit() and two_factor_auth_form.btn_two_factor_auth_form.data:
user.two_factor_auth = two_factor_auth_form.two_factor_auth.data
user.save()
flash(_('Successfully updated two factor authentication.'), 'success')
return redirect(url_for('user.settings'))
elif two_factor_auth_form.btn_two_factor_auth_form.data:
flash(_(two_factor_auth_form.errors), 'warning')
return redirect(url_for('user.settings'))
if theme_settings_form.validate_on_submit() and theme_settings_form.btn_theme_settings_form.data:
user.dark_mode = theme_settings_form.dark_mode.data
user.save()
flash(_('Successfully updated theme settings.'), 'success')
return redirect(url_for('user.settings'))
elif theme_settings_form.btn_theme_settings_form.data:
flash(_(theme_settings_form.errors), 'warning')
return redirect(url_for('user.settings'))
except Exception as e:
print("Exception : ", e)
log.error(f"Error getting user settings. ")
return render_template('user/settings.jinja2',
user=user,
partnership=partnership,
profile_form=profile_form,
security_info_form=security_info_form,
two_factor_auth_form=two_factor_auth_form,
theme_settings_form=theme_settings_form,
login_access_info=login_access_info,
languages=languages)
@user.route('/settings-old')
@login_required
def settings_old():
if current_user.role == 'sysadmin':
return render_template('sysadmin/settings_old.jinja2')
elif current_user.role == 'admin' and current_user.is_viewing_partnership:
return redirect(url_for('dashboard.user_dashboard_old'))
else:
return render_template('user/settings_old.jinja2')
@user.route('/settings/update_credentials', methods=['GET', 'POST'])
@login_required
def update_credentials():
form = UpdateCredentials(current_user, uid=current_user.id)
if form.validate_on_submit():
# saving old password on to a variable
old_password = current_user.password
# We cannot form.populate_obj() because the password is optional.
new_password = request.form.get('password', '')
current_user.email = request.form.get('email')
if new_password:
current_user.password = User.encrypt_password(new_password)
current_user.save()
# start check password is same
if old_password and new_password:
status = User.check_password_match(old_password, new_password)
if not status:
current_user.save_password_updated_date()
# end check password is same
ActivityLogs.add_log(current_user.id, ActivityType.AUTHORIZATION, ActivityName.LOGOUT, request)
logout_user()
flash(_('Your sign in settings have been updated. Please log in again with your new credentials.'), 'success')
return redirect(url_for('user.login'))
return render_template('user/update_credentials.jinja2', form=form)
@user.route('/settings/update_personaldetails', methods=['GET', 'POST'])
@login_required
def update_personaldetails():
form = UpdatePersonalDetails(current_user, uid=current_user.id)
if form.validate_on_submit():
form.populate_obj(current_user)
current_user.save()
flash(_('Your personal details have been updated.'), 'success')
return redirect(url_for('user.settings'))
return render_template('user/update_personaldetails.jinja2', form=form)
@user.route('/settings/update_locale', methods=['GET', 'POST'])
@login_required
def update_locale():
form = UpdateLocale(locale=current_user.locale)
if form.validate_on_submit():
form.populate_obj(current_user)
current_user.save()
flash(_('Your locale settings have been updated.'), 'success')
return redirect(url_for('user.settings'))
return render_template('user/update_locale.jinja2', form=form)
@user.route('/settings/update_security', methods=['GET', 'POST'])
@login_required
def update_security():
form = UpdateSecurity(two_factor_auth=current_user.two_factor_auth)
crt_user = User.query.filter(User.id == current_user.id).first()
if crt_user:
crt_user_phone = format_phone_number_bracket(crt_user.phonenumber)
crt_user_email = crt_user.email
sms_label = 'SMS - ' + crt_user_phone
email_label = 'Email - ' + crt_user_email
# Generate choices based on boolean fields from the database
choices = []
if crt_user.role in ('admin', 'agent'):
if crt_user.partnership.is_2fa_sms_enabled and crt_user.partnership_account.is_2fa_sms_enabled:
choices.append(('field1', sms_label))
if crt_user.partnership.is_2fa_email_enabled and crt_user.partnership_account.is_2fa_email_enabled:
if crt_user.partnership.is_2fa_sms_enabled and crt_user.partnership_account.is_2fa_sms_enabled:
choices.append(('field2', email_label))
else:
choices.append(('field1', email_label))
elif crt_user.role == 'partner':
if crt_user.partnership.is_2fa_sms_enabled:
choices.append(('field1', sms_label))
if crt_user.partnership.is_2fa_email_enabled:
if crt_user.partnership.is_2fa_sms_enabled:
choices.append(('field2', email_label))
else:
choices.append(('field1', email_label))
elif crt_user.role in ('sysadmin', 'limitsysadmin'):
choices.append(('field1', sms_label))
choices.append(('field2', email_label))
form.choice.choices = choices
# Preselect the choice based on the database values
if len(choices) > 1:
if crt_user.is_2fa_sms:
form.choice.data = 'field1'
elif crt_user.is_2fa_email:
form.choice.data = 'field2'
if form.validate_on_submit():
form.populate_obj(current_user)
if current_user.partnership:
if current_user.partnership.is_2fa_enforced:
current_user.two_factor_auth = True
current_user.two_factor_auth_onboard = True
# Update the database record based on the selected option
if form.auth_method.data == 'SMS':
current_user.is_2fa_sms = True
current_user.is_2fa_email = False
elif form.auth_method.data == 'EMAIL':
current_user.is_2fa_sms = False
current_user.is_2fa_email = True
current_user.save()
flash(_('Your security settings have been updated.'), 'success')
return redirect(url_for('user.settings'))
return render_template('user/update_security.jinja2', form=form)
@user.route('/settings/rest_api', methods=['GET'])
@login_required
@role_required('admin', 'partner')
def rest_api_view():
generated = False, ''
if current_user.is_partnership_account_user:
if current_user.partnership_account.api_token_hash:
generated = True
elif current_user.is_partnership_user:
if current_user.partnership.api_token_hash:
generated = True
return render_template('user/rest_api.jinja2', generated=generated)
@user.route('/settings/rest_api', methods=['POST'])
@login_required
@role_required('admin', 'partner')
def rest_api_update():
token = ''
if current_user.is_partnership_account_user:
partnership_account_id = current_user.partnership_account_id
partnership_account_group_viewing = current_user.is_viewing_partnership
# Check if being viewed by super partner
if partnership_account_group_viewing:
partnership_account_id = current_user.get_user_viewing_partnership_account_id
token = current_user.partnership_account.regenerate_api_token(partnership_account_id)
elif current_user.is_partnership_user:
token = current_user.partnership.regenerate_api_token(current_user.partnership.id)
return render_template(
'user/rest_api.jinja2',
generated=True,
token=token
)
@user.route('/user/switch_back', methods=['GET'])
# @role_required('admin', 'partner', 'sysadmin')
@login_required
@supervisor_login_required
def switch_back():
target_user = copy.deepcopy(current_supervisor_user)
u = current_user
logout_user()
login_user(target_user, remember=False, force=True)
supervisor_logout_user()
return redirect(url_for('user.settings'))
# Add Subdomain to the global request variable
@user.before_request
def before_request():
"""
The URL that user visits is stored to a global variable partner_url in request_config
This global variable can be accessed from anywhere in this user app
Subdomains containing www is removed.
Request protocol isn't stored because it will be either http or https
The only things that affects identifying the partner are subdomain, domain and suffix(or tld)
Possible formats:
subdomain.domain.tld
domain.tld
subdomain.domain (To support sub.localhost)
domain (To support localhost)
"""
url = request.host_url
extract = tldextract.extract(url)
subdomain = extract.subdomain
domain = extract.domain
suffix = extract.suffix
if subdomain[:4] == 'wwww.': # Removing www from sites like www.subdomain.domain.tld
subdomain = subdomain[4:]
if subdomain == 'www': # Removing www from sites like www.domain.tld
subdomain = ''
partner_url = ''
if subdomain:
partner_url = f'{subdomain}.'
if suffix:
partner_url += f'{domain}.{suffix}'
else:
partner_url += f'{domain}'
g.request_config = {'partner_url': partner_url}
@user.route('/elasticsearch', methods=['GET'])
@login_required
def test_elasticsearch():
try:
a = []
b = a[1]
except Exception as e:
pass
# status = insert_error_data(request, es_client)
# print(status)
partnership = Partnership.query.get(current_user.partnership_id)
if not partnership:
partnership = Partnership.query.get(1)
partnership_account = PartnershipAccount.query.get(current_user.partnership_account_id)
if partnership_account:
account_id = partnership_account.sid
else:
account_id = 'NO-PARTNERSHIP-ACCOUNT'
params = {}
for p in request.args:
print(p)
data = {
'environment': 'DEVELOPMENT',
'hostname': request.host,
'ip': request.remote_addr,
'created': datetime.now(tz=UTC),
'method': request.method,
'is_api': False,
'params': {
'key': 'name',
'value': 'Jay'
},
'url': request.host_url,
'status_code': 500,
'status_code_root': 500,
'error_detail': traceback.format_exc(),
'user_id': current_user.sid,
'partnership_id': partnership.sid,
'account_id': account_id
}
# errorlog = insert_error_data(data=data, es_client=es_client)
return
@user.route('/push')
@login_required
def test_notify():
partnership = Partnership.query.get(current_user.partnership_id)
if not partnership:
partnership = Partnership.query.get(1)
data = {
'user_id': current_user.sid,
'notify_message_type': 'DASHBOARD_VIEWED',
'user_related_entities': ["You've"],
'other_user_related_entities': [f'{current_user.firstname} {current_user.lastname}'],
'hyperlink': 'http://localhost:8000/settings'
}
response = send_notifications(**data)
# Send mail
mail_subject = "You've a new notification"
mail_data = render_template('user/mail/notification.jinja2', user=current_user,
config=current_app.config, logo=partnership.logo)
recipients = 'namaste@ecosustain.in'
# celery
from buyercall.blueprints.user.tasks import send_notification_mail
mail_status = send_notification_mail(mail_subject, mail_data, recipients)
return response
@user.route('/user-management', methods=['GET'])
@login_required
@role_required('admin', 'partner')
def userManagement():
return render_template('user/user_management.jinja2')