minor tweaks on otp_force

This commit is contained in:
vmarkop 2021-12-16 17:39:22 +02:00
parent 8d76ff2e29
commit 60b84162fa
7 changed files with 34 additions and 50 deletions

View file

@ -23,6 +23,7 @@ css_login = Bundle('node_modules/bootstrap/dist/css/bootstrap.css',
js_login = Bundle('node_modules/jquery/dist/jquery.js', js_login = Bundle('node_modules/jquery/dist/jquery.js',
'node_modules/bootstrap/dist/js/bootstrap.js', 'node_modules/bootstrap/dist/js/bootstrap.js',
'node_modules/icheck/icheck.js', 'node_modules/icheck/icheck.js',
'custom/js/custom.js',
filters=(ConcatFilter, 'jsmin'), filters=(ConcatFilter, 'jsmin'),
output='generated/login.js') output='generated/login.js')

View file

@ -8,6 +8,9 @@ import ldap.filter
from flask import current_app from flask import current_app
from flask_login import AnonymousUserMixin from flask_login import AnonymousUserMixin
from sqlalchemy import orm from sqlalchemy import orm
import qrcode as qrc
import qrcode.image.svg as qrc_svg
from io import BytesIO
from .base import db from .base import db
from .role import Role from .role import Role
@ -633,6 +636,13 @@ class User(db.Model):
for q in query: for q in query:
accounts.append(q[1]) accounts.append(q[1])
return accounts return accounts
def get_qrcode_value(self):
img = qrc.make(self.get_totp_uri(),
image_factory=qrc_svg.SvgPathImage)
stream = BytesIO()
img.save(stream)
return stream.getvalue()
def read_entitlements(self, key): def read_entitlements(self, key):
@ -794,7 +804,4 @@ def getUserInfo(DomainsOrAccounts):
current=[] current=[]
for DomainOrAccount in DomainsOrAccounts: for DomainOrAccount in DomainsOrAccounts:
current.append(DomainOrAccount.name) current.append(DomainOrAccount.name)
return current return current

View file

@ -591,8 +591,7 @@ def authenticate_user(user, authenticator, remember=False):
# Prepare user to enter /welcome screen, otherwise they won't have permission to do so # Prepare user to enter /welcome screen, otherwise they won't have permission to do so
def prepare_welcome_user(user_id): def prepare_welcome_user(user_id):
logout_user() logout_user()
session['user_id'] = user_id session['welcome_user_id'] = user_id
session['welcome'] = True
@index_bp.route('/logout') @index_bp.route('/logout')
def logout(): def logout():
@ -684,10 +683,8 @@ def register():
if Setting().get('verify_user_email'): if Setting().get('verify_user_email'):
send_account_verification(email) send_account_verification(email)
if Setting().get('otp_force') and Setting().get('otp_field_enabled'): if Setting().get('otp_force') and Setting().get('otp_field_enabled'):
login_user(user) user.update_profile(enable_otp=True)
current_user.update_profile(enable_otp=True) prepare_welcome_user(user.id)
user_id = current_user.id
prepare_welcome_user(user_id)
return redirect(url_for('index.welcome')) return redirect(url_for('index.welcome'))
else: else:
return redirect(url_for('index.login')) return redirect(url_for('index.login'))
@ -703,14 +700,11 @@ def register():
# Show welcome page on first login if otp_force is enabled # Show welcome page on first login if otp_force is enabled
@index_bp.route('/welcome', methods=['GET', 'POST']) @index_bp.route('/welcome', methods=['GET', 'POST'])
def welcome(): def welcome():
if 'welcome' not in session: if 'welcome_user_id' not in session:
return redirect(url_for('index.index')) return redirect(url_for('index.index'))
user_id = session['user_id'] user = User(id = session['welcome_user_id'])
user = User(id = user_id) encoded_img_data = base64.b64encode(user.get_qrcode_value())
login_user(user)
encoded_img_data = base64.b64encode(qrcode()[0])
prepare_welcome_user(user_id)
if request.method == 'GET': if request.method == 'GET':
return render_template('register_otp.html', qrcode_image=encoded_img_data.decode(), user=user) return render_template('register_otp.html', qrcode_image=encoded_img_data.decode(), user=user)
@ -722,7 +716,7 @@ def welcome():
return render_template('register_otp.html', qrcode_image=encoded_img_data.decode(), user=user, error="Invalid token") return render_template('register_otp.html', qrcode_image=encoded_img_data.decode(), user=user, error="Invalid token")
else: else:
return render_template('register_otp.html', qrcode_image=encoded_img_data.decode(), user=user, error="Token required") return render_template('register_otp.html', qrcode_image=encoded_img_data.decode(), user=user, error="Token required")
session.pop('welcome') session.pop('welcome_user_id')
return redirect(url_for('index.index')) return redirect(url_for('index.index'))
@index_bp.route('/confirm/<token>', methods=['GET']) @index_bp.route('/confirm/<token>', methods=['GET'])

View file

@ -1,7 +1,4 @@
import datetime import datetime
import qrcode as qrc
import qrcode.image.svg as qrc_svg
from io import BytesIO
from flask import Blueprint, request, render_template, make_response, jsonify, redirect, url_for, g, session, current_app from flask import Blueprint, request, render_template, make_response, jsonify, redirect, url_for, g, session, current_app
from flask_login import current_user, login_required, login_manager from flask_login import current_user, login_required, login_manager
@ -94,13 +91,9 @@ def qrcode():
if not current_user: if not current_user:
return redirect(url_for('index')) return redirect(url_for('index'))
img = qrc.make(current_user.get_totp_uri(), return current_user.get_qrcode_value(), 200, {
image_factory=qrc_svg.SvgPathImage)
stream = BytesIO()
img.save(stream)
return stream.getvalue(), 200, {
'Content-Type': 'image/svg+xml', 'Content-Type': 'image/svg+xml',
'Cache-Control': 'no-cache, no-store, must-revalidate', 'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache', 'Pragma': 'no-cache',
'Expires': '0' 'Expires': '0'
} }

View file

@ -285,4 +285,14 @@ function timer(elToUpdate, maxTime) {
}, 1000); }, 1000);
return interval; return interval;
} }
// copy otp secret code to clipboard
function copy_otp_secret_to_clipboard() {
var copyBox = document.getElementById("otp_secret");
copyBox.select();
copyBox.setSelectionRange(0, 99999); /* For mobile devices */
navigator.clipboard.writeText(copyBox.value);
$("#copy_tooltip").css("visibility", "visible");
setTimeout(function(){ $("#copy_tooltip").css("visibility", "collapse"); }, 2000);
}

View file

@ -41,7 +41,7 @@
Your secret key is: <br /> Your secret key is: <br />
<form> <form>
<input type=text id="otp_secret" value={{user.otp_secret}} readonly> <input type=text id="otp_secret" value={{user.otp_secret}} readonly>
<button type=button style="position:relative; right:28px" onclick="copy_to_clickboard()"> <i class="fa fa-clipboard"></i> </button> <button type=button style="position:relative; right:28px" onclick="copy_otp_secret_to_clipboard()"> <i class="fa fa-clipboard"></i> </button>
<br /><font color="red" id="copy_tooltip" style="visibility:collapse">Copied.</font> <br /><font color="red" id="copy_tooltip" style="visibility:collapse">Copied.</font>
</form> </form>
</p> </p>
@ -87,15 +87,4 @@
{% assets "js_validation" -%} {% assets "js_validation" -%}
<script type="text/javascript" src="{{ ASSET_URL }}"></script> <script type="text/javascript" src="{{ ASSET_URL }}"></script>
{%- endassets %} {%- endassets %}
<script>
// copy otp secret code to clipboard
function copy_to_clickboard() {
var copyBox = document.getElementById("otp_secret");
copyBox.select();
copyBox.setSelectionRange(0, 99999); /* For mobile devices */
navigator.clipboard.writeText(copyBox.value);
$("#copy_tooltip").css("visibility", "visible");
setTimeout(function(){ $("#copy_tooltip").css("visibility", "collapse"); }, 2000);
}
</script>
</html> </html>

View file

@ -97,7 +97,7 @@
Your secret key is: <br /> Your secret key is: <br />
<form> <form>
<input type=text id="otp_secret" value={{current_user.otp_secret}} readonly> <input type=text id="otp_secret" value={{current_user.otp_secret}} readonly>
<button type=button style="position:relative; right:28px" onclick="copy_to_clickboard()"> <i class="fa fa-clipboard"></i> </button> <button type=button style="position:relative; right:28px" onclick="copy_otp_secret_to_clipboard()"> <i class="fa fa-clipboard"></i> </button>
<br /><font color="red" id="copy_tooltip" style="visibility:collapse">Copied.</font> <br /><font color="red" id="copy_tooltip" style="visibility:collapse">Copied.</font>
</form> </form>
</div> </div>
@ -160,15 +160,5 @@
}; };
applyChanges(postdata, $SCRIPT_ROOT + '/user/profile', false, true); applyChanges(postdata, $SCRIPT_ROOT + '/user/profile', false, true);
}); });
// copy otp secret code to clipboard
function copy_to_clickboard() {
var copyBox = document.getElementById("otp_secret");
copyBox.select();
copyBox.setSelectionRange(0, 99999); /* For mobile devices */
navigator.clipboard.writeText(copyBox.value);
$("#copy_tooltip").css("visibility", "visible");
setTimeout(function(){ $("#copy_tooltip").css("visibility", "collapse"); }, 2000);
}
</script> </script>
{% endblock %} {% endblock %}