<!DOCTYPE html> <html> <head> {% for src in js %} <script type="text/javascript" src="{{ src }}"></script> {% endfor %} {% for src in css %} <link type="text/css" rel="stylesheet" href="{{ src }}"> {% endfor %} <script type="text/javascript" src="{{ url_for( 'send_app_files', path = 'webauthn.js' ) }}"></script> <script type="text/javascript" src="{{ url_for( 'send_app_files', path = 'functions.js' ) }}"></script> <link type="text/css" rel="stylesheet" href="{{ url_for( 'send_app_files', path = 'app.css' ) }}"> <script type="text/javascript"> baseurl = "{{ baseurl }}"; </script> </head> <body> <div class="icnml_central"> <h1 style="margin-bottom: 0px">ICNML</h1> <h4 style="margin-top: 0px">International Close Non-Matches Library</h4> <div class="ui-widget-header ui-corner-top icnml_box_top">Please enter your login information</div> <div id="icnml_homepage_form" class="ui-widget-content ui-corner-bottom icnml_box_content"> <div id="icnml_box_fields" class="icnml_box_fields"> <div style="text-align: right;"> <label for="username">Username</label> </div> <div> <input id="username" name="username" type="text" /> </div> <div style="text-align: right;"> <label for="password">Password</label> </div> <div> <input id="password" name="password" type="password" /> </div> </div> <div id="icnml_login_error" class="icnml_box_error"></div> <div id="warning" class="icnml_box_warning"></div> <div class="icnml_button"> <a class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" id="login_button" role="button" aria-disabled="false"> <span class="ui-button-text">Login</span> </a> </div> <div class="icnml_shybox" id="password_reset"> <a href="{{ url_for( 'password_reset' ) }}">Forgotten password ?</a> <br> <a href="{{ url_for( 'new_user' ) }}">Sign-in</a> </div> </div> <div class="icnml_shybox" style="margin-top: 10px;"> <span id="icnml_version"></span> <br> <a id="icnml_tree_files" href="#"></a> </div> </div> </body> <script type="text/javascript"> var login_action_password = async function() { $( "#icnml_login_error" ).html( "" ); $( "#login_button > span" ).text( "Please wait..." ); var username = $( "#username" ).val(); var password = $( "#password" ).val(); var password_local = $( "#password" ).val(); password = await generateKey( password, "icnml_" + username, 20000 ); password = password.substring( 0, 128 ); password = "pbkdf2$sha512$icnml_" + username + "$20000$" + password; password_local = await generateKey( password_local, "icnml_" + username + "_localpassword", 50000 ); password_local = password_local.substring( 0, 128 ); var e = encrypt( password_local, "{{ session_security_key }}" ); sessionStorage.setItem( "session_key", e ); $.ajax( { url: "{{ url_for( 'do_login' ) }}", dataType: "json", method: "POST", data: { username: username, password: password }, success: function( data ) { if( ! data.error ) { if( data.logged ) { location.href = "{{ url_for( 'home' ) }}"; } else if( data.next_step === "totp" ) { build_totp_form(); } else if( data.next_step === "securitykey" ) { build_securitykey_form(); } else { if( typeof data.message !== "undefined" ) var message = data.message; else var message = "Invalid username/password"; $( "#icnml_login_error" ).text( message ); } $( "#login_button > span" ).text( "Login" ); } } } ); } var login_action_totp = function() { $( "#icnml_login_error" ).html( "" ); $( "#login_button > span" ).text( "Please wait..." ); $.ajax( { url: "{{ url_for( 'do_login' ) }}", dataType: "json", method: "POST", data: { totp: $( "#totp" ).val() }, success: function( data ) { if( ! data.error ) { if( data.logged ) { location.href = "{{ url_for( 'home' ) }}"; } else if( data.next_step === "securitykey" ) { build_securitykey_form(); } else { if( typeof data.message !== "undefined" ) $( "#icnml_login_error" ).text( data.message ); } } } } ); } var build_totp_form = function() { $( "#icnml_login_error" ).html( "" ); $( "#icnml_box_fields" ).html( "" ); $( "#icnml_box_fields" ) .append( $( "<div />" ) .text( "TOTP" ) .css( "text-align", "right" ) ) .append( $( "<div />" ).append( $( "<input />" ) .attr( "id", "totp" ) .attr( "name", "totp" ) .on( "keyup", function( event ) { if( event.keyCode == 13 ) { event.preventDefault(); login_action_totp(); } } ) ) ); $( "#totp" ).focus(); } var build_securitykey_form = function() { $( "#icnml_login_error" ).html( "" ); $( "#icnml_box_fields" ).html( "" ); $( "#icnml_box_fields" ) .removeClass( "icnml_box_fields" ) .addClass( "icnml_auto" ); $( "#login_button" ).remove(); $( "#password_reset" ).remove(); $( "#icnml_homepage_form" ) .prepend( $( "<div />" ) .css( "margin-bottom", "10px" ) .text( "Logging with your security key..." ) ); login_key(); } /* Events binding */ $( "#username" ).on( "keyup", function( event ) { if( event.keyCode == 13 ) { event.preventDefault(); login_action_password(); } } ); $( "#password" ).on( "keyup", function( event ) { if( event.keyCode == 13 ) { event.preventDefault(); login_action_password(); } } ); $( "#login_button" ).on( "click", login_action_password ); $( "#username" ).focus(); $( document ).ready( function() { if( !window.crypto || !window.crypto.subtle || !window.TextEncoder || !window.TextDecoder) { $( "#warning" ) .text( "Your browser does not support client-side cryptography. Please use compatible browser (Firefox, Chrome, Opera, Safari, ...) to protect your password before sending it to the ICNML server." ); $( "#username" ).prop( "disabled", true ); $( "#password" ).prop( "disabled", true ); $( "#login_button" ).remove(); } } ); setTimeout( function() { location.reload(); }, {{ session_timeout }} * 1000 ); /* Get the version of ICNML */ $.ajax( { url: "{{ url_for( 'version' ) }}", dataType: "json", method: "GET", success: function( data ){ $( "#icnml_version" ) .text( "ICNML version: " + data.version ); $( "#icnml_tree_files" ) .attr( "href", data.treeurl ) .attr( "target", "_blank" ) .css( "text-decoration", "underline" ) .text( "Download this version of ICNML here" ); } } ); </script> </html>