Merged v2.6.0

This commit is contained in:
Mohamed El-Kalioby
2022-10-01 12:41:15 +03:00
parent 0936ea2533
commit cb2149acf3
27 changed files with 614 additions and 119 deletions

View File

@@ -32,9 +32,14 @@
}).then(function (res)
{
if (res["status"] =='OK')
$("#res").html("<div class='alert alert-success'>Registered Successfully, <a href='{{redirect_html}}'> {{reg_success_msg}}</a></div>")
else
$("#res").html("<div class='alert alert-danger'>Registration Failed as " + res["message"] + ", <a href='javascript:void(0)' onclick='begin_reg()'> try again or <a href='{% url 'mfa_home' %}'> Go to Security Home</a></div>")
$("#res").html("<div class='alert alert-success'>Registered Successfully, <a href='{{redirect_html}}'> {{reg_success_msg}}</a></div>")
else if (res['status'] = "RECOVERY")
{
setTimeout(function (){location.href="{% url 'manage_recovery_codes' %}"},2500)
$("#res").html("<div class='alert alert-success'>Registered Successfully, but <a href='{% url 'manage_recovery_codes' %}'>redirecting to {{ RECOVERY_METHOD }} method</a></div>")
}
else
$("#res").html("<div class='alert alert-danger'>Registration Failed as " + res["message"] + ", <a href='javascript:void(0)' onclick='begin_reg()'> try again or <a href='{% url 'mfa_home' %}'> Go to Security Home</a></div>")
}, function(reason) {
@@ -61,7 +66,7 @@
<div class="container">
<div class="panel panel-default card">
<div class="panel-heading card-header">
<strong> FIDO2 Security Key</strong>
<strong> Adding a New {{ method.name }}</strong>
</div>
<div class="panel-body card-body">

View File

@@ -3,7 +3,7 @@
<script type="application/javascript" src="{% static 'mfa/js/ua-parser.min.js' %}"></script>
<div class="row">
<div class="col-sm-10 col-sm-offset-1 col-xs-12 col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2">
<div class="col-sm-10 col-sm-offset-1 col-xs-12 col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2 offset-2 col-8">
<div class="panel panel-default card">
<div class="panel-heading card-header">
<strong> Security Key</strong>
@@ -35,10 +35,10 @@
</div>
<div class="row">
<div class="col-md-12 mb-3" style="padding-left: 15px">
<div class="col-md-12 mb-3" style="padding-left: 25px">
{% if request.session.mfa_methods|length > 1 %}
<a href="{% url 'mfa_methods_list' %}">Select Another Method</a>
<a href="{% url 'mfa_methods_list' %}">Select Another Method</a>
{% endif %}
</div>
</div>

View File

@@ -45,31 +45,31 @@
<br/>
<div class="container">
<div class="row">
<div align="center">
<div class="offset-5 col-2" style="text-align: center">
<div class="btn-group">
<button class="btn btn-success dropdown-toggle" data-toggle="dropdown" data-bs-toggle="dropdown">
Add Method&nbsp;<span class="caret"></span>
</button>
<ul class="dropdown-menu">
{% if not 'TOTP' in UNALLOWED_AUTHEN_METHODS %}
<li><a class="dropdown-item" href="{% url 'start_new_otop' %}">Authenticator app</a></li>
<li><a class="dropdown-item" href="{% url 'start_new_otop' %}">{% if 'TOTP' in RENAME_METHODS.keys %}{{ RENAME_METHODS.TOTP }}{% else %}Authenticator app{% endif %}</a></li>
{% endif %}
{% if not 'Email' in UNALLOWED_AUTHEN_METHODS %}
<li><a class="dropdown-item" href="{% url 'start_email' %}">Email Token</a></li>
<li><a class="dropdown-item" href="{% url 'start_email' %}">{% if 'Email' in RENAME_METHODS.keys %}{{ RENAME_METHODS.Email }}{% else %}Email Token{% endif %}</a></li>
{% endif %}
{% if not 'U2F' in UNALLOWED_AUTHEN_METHODS %}
<li><a class="dropdown-item" href="{% url 'start_u2f' %}">Security Key</a></li>
<li><a class="dropdown-item" href="{% url 'start_u2f' %}">{% if 'U2F' in RENAME_METHODS.keys %}{{ RENAME_METHODS.U2F }}{% else %}Security Key{% endif %}</a></li>
{% endif %}
{% if not 'FIDO2' in UNALLOWED_AUTHEN_METHODS %}
<li><a class="dropdown-item" href="{% url 'start_fido2' %}">FIDO2 Security Key</a></li>
{% if not 'FIDO2' in UNALLOWED_AUTHEN_METHODS %}
<li><a class="dropdown-item" href="{% url 'start_fido2' %}">{% if 'FIDO2' in RENAME_METHODS.keys %}{{ RENAME_METHODS.FIDO2 }}{% else %}FIDO2 Security Key{% endif %}</a></li>
{% endif %}
{% if not 'Trusted_Devices' in UNALLOWED_AUTHEN_METHODS %}
<li><a class="dropdown-item" href="{% url 'start_td' %}">Trusted Device</a></li>
{% if not 'Trusted_Devices' in UNALLOWED_AUTHEN_METHODS %}
<li><a class="dropdown-item" href="{% url 'start_td' %}">{% if 'Trusted_Devices' in RENAME_METHODS.keys %}{{ RENAME_METHODS.Trusted_Devices }}{% else %}Trusted Device{% endif %}</a></li>
{% endif %}
</ul>
</div>
</div>
<br/>
</div>
<br/>
<table class="table table-striped">
<tr>
@@ -82,28 +82,42 @@
<th>Status</th>
<th>Delete</th>
</tr>
{% for key in keys %}
<tr>
{% if keys %}
{% for key in keys %}
<tr>
<td>{{ key.key_type }}</td>
<td>{{ key.added_on }}</td>
<td>{{ key.expires }}</td>
<td>{% if key.device %}{{ key.device }}{% endif %}</td>
<td>{{ key.last_used }}</td>
{% if key.key_type in HIDE_DISABLE %}
<td>{% if key.enabled %}On{% else %} Off{% endif %}</td>
{% else %}
<td><input type="checkbox" id="toggle_{{ key.id }}" {% if key.enabled %}checked{% endif %} data-onstyle="success" data-offstyle="danger" onchange="toggleKey({{ key.id }})" data-toggle="toggle" class="status_chk"></td>
{% endif %}
<td>{% if key.key_type in HIDE_DISABLE %}
----
{% else %}
<a href="javascript:void(0)" onclick="deleteKey({{ key.id }},'{{ key.key_type }}')"> <span class="fa fa-trash fa-solid fa-trash-can bi bi-trash-fill"></span></a></td>
<td>{{ key.name }}</td>
<td>{{ key.added_on }}</td>
<td>{% if key.expires %}{{ key.expires }}{% else %}N/A{% endif %}</td>
<td>{% if key.device %}{{ key.device }}{% endif %}</td>
<td>{% if key.last_used %}{{ key.last_used }}{% else %}Never{% endif %}</td>
{% if key.key_type in HIDE_DISABLE %}
<td>{% if key.enabled %}On{% else %} Off{% endif %}</td>
{% else %}
<td><input type="checkbox" id="toggle_{{ key.id }}" {% if key.enabled %}checked{% endif %} data-onstyle="success" data-offstyle="danger" onchange="toggleKey({{ key.id }})" data-toggle="toggle" class="status_chk"></td>
{% endif %}
</tr>
{% empty %}
<td>{% if key.key_type in HIDE_DISABLE %}
----
{% else %}
<a href="javascript:void(0)" onclick="deleteKey({{ key.id }},'{{ key.key_type }}')"> <span class="fa fa-trash fa-solid fa-trash-can bi bi-trash-fill"></span></a></td>
{% endif %}
</tr>
{% endfor %}
{% if "RECOVERY" not in UNALLOWED_AUTHEN_METHODS %}
<tr>
<td>{{ recovery.name }}</td>
<td>{{ recovery.added_on }}</td>
<td>N/A</td>
<td>N/A</td>
<td>{% if recovery.last_used %}{{ recovery.last_used }}{% else %}Never{% endif %}</td>
<td>On</td>
<td><a href="{% url 'manage_recovery_codes' %}"> <span class="fa fa-wrench fa-solid fa-wrench bi bi-wrench-fill"></span></a></td>
</tr>
{% endif %}
{% else %}
<tr><td colspan="7" align="center">You didn't have any keys yet.</td> </tr>
{% endfor %}
{% endif %}
</table>
</div>
</div>

View File

@@ -0,0 +1,134 @@
{% extends "base.html" %}
{% load static %}
{% block head %}
<style>
#two-factor-steps {
border: 1px solid #ccc;
border-radius: 3px;
padding: 15px;
}
.tokenrow{
margin-top: 10px;
margin-left: 5px;
}
.row{
margin: 3px;
}
.toolbtn {
border-radius: 7px;
cursor: pointer;
}
.toolbtn:hover {
background-color: gray;
transition: 0.2s;
}
.toolbtn:active {
background-color: green;
transition: 0.2s;
}
</style>
<script src="{% static 'mfa/js/qrious.min.js' %}" type="text/javascript"></script>
<script type="text/javascript">
var clearCodes;
$(document).ready(function checkTokenLeft() {
$.ajax({"url":"{% url 'get_recovery_token_left' %}", dataType:"JSON",
success:function (data) {
tokenLeft = data.left
html = ""
{% if mfa_redirect %}
html += "<div class='alert alert-success'>You have enrolled successfully in {{ mfa_redirect }} method, please generate recovery codes so that you can use in case you lost access to all your verification methods.</div>"
{% endif %}
if (tokenLeft == 0) {
html += "<h6>You don't have any backup code linked to your account, please generate new ones !</h6>"
}
else {
html += "<p>You still have "+tokenLeft+" backup code left."
}
document.getElementById('tokens').innerHTML = html
}})
});
function confirmRegenerateTokens() {
htmlModal = "<h6>Caution! you can only view these token now, else you will need to generate new ones.</h6><div align='center'><button onclick='regenerateTokens()' class='btn btn-success'>Regenerate</button></div>"
$("#modal-title").html("Regenerate your recovery Codes?")
$("#modal-body").html(htmlModal)
$("#popUpModal").modal('show')
}
function copy() {
navigator.clipboard.writeText($("#recovery_codes").text());
}
function regenerateTokens() {
$.ajax({
"url":"{% url 'regen_recovery_tokens' %}", dataType:"JSON",
success:function (data) {
let htmlkey=`<p>Here are the recovery codes, you have to save them now as you won't able to view them again.</p>
<div class='row'><div class='offset-4 col-md-4' style='background-color:#f0f0f0;padding: 10px'>
<div class='row'>
<div class="col-6 offset-6">
<span onclick='download_recovery()' class='fa fa-download toolbtn' title="Download"></span>&nbsp;&nbsp;
<span class='fa fa-clipboard toolbtn' title="Copy" onclick="copy()"></span>
</div></div><div id='recovery_codes'><pre>`;
for (let i = 0; i < data.keys.length; i++) {
htmlkey +="- " +data.keys[i] + "\n"
}
document.getElementById('tokens').innerHTML = htmlkey+"</pre></div></div></div>"
$("#popUpModal").modal('hide')
clearCodes = data.keys
}
})
}
function download_recovery() {
var element = document.createElement('a');
var text = "";
for(let i = 0; i < clearCodes.length; i++)
{
text = text + clearCodes[i]
if (i < clearCodes.length - 1) { text = text + "\n"}
}
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', 'Recovery Codes.txt');
element.style.display = 'none';
document.body.appendChild(element);
element.click();
console.log(element.innerHTML)
document.body.removeChild(element);
}
</script>
{% endblock %}
{% block content %}
<br/>
<br/>
<div class="container d-flex justify-content-center">
<div class="col-md-6 col-md-offset-3" id="two-factor-steps">
<div class="row">
<h4>Recovery Codes List</h4>
</div>
<div class="tokenrow" id="tokens">
</div>
<br/>
<br/>
<div class="row">
<div class="col-md-4 col-md-offset-4" style="padding-left: 0px" align="center">
<button onclick="confirmRegenerateTokens()" class="btn btn-success">Regenerate</button>
</div>
<div class="col-md-6" align="right" style="padding-right: 30px">
<a href="{{redirect_html}}" class="btn btn-default btn-secondary" role="button"> {{reg_success_msg}}</a>
</div>
</div>
</div>
</div>
{% include "modal.html" %}
{% endblock %}

View File

@@ -0,0 +1,14 @@
{% extends "mfa_auth_base.html" %}
{% block head %}
<style>
.row{
margin-left: 15px;
}
</style>
{% endblock %}
{% block content %}
<br/>
<br/>
{% include "RECOVERY/recheck.html" with mode='auth' %}
{% endblock %}

View File

@@ -0,0 +1,85 @@
<script type="application/javascript">
$(document).ready(function showWarningLastBackup() {
{% if lastBackup %}
$("#modal-title").html("Last backup code used !")
$("#modal-body").html("Don't forget to regenerate new backup code after login !")
$('#modal-footer').html(`<FORM METHOD="GET" ACTION="{% url 'recovery_auth' %}" Id="confirmLogin" onSubmit="" name="recoveryLastBackupConfirm">
<input type='submit'class='btn btn-lg btn-success btn-block' value='Continue'>`)
$("#popUpModal").modal('show')
{% endif %}
return
});
function send_recovery() {
$.ajax({"url":"{% url 'recovery_recheck' %}", method:"POST",dataType:"JSON",
data:{"csrfmiddlewaretoken":"{{ csrf_token }}","recovery":$("#recovery").val()},
success:function (data) {
if (data["recheck"])
mfa_success_function();
else {
mfa_failed_function();
}
}
})
}
</script>
<div class="row">
<div class="col-sm-10 col-sm-offset-1 col-xs-12 col-md-10 col-md-offset-1 col-lg-10 col-lg-offset-1">
<div class="panel panel-default card">
<div class="panel-heading card-header">
<strong> Recovery code</strong>
</div>
<div class="panel-body card-body">
<FORM METHOD="POST" ACTION="{% url 'recovery_auth' %}" Id="formLogin" onSubmit="" name="FrontPage_Form1">
{% csrf_token %}
{% if invalid %}
<div class="alert alert-danger">
Sorry, The provided code is not valid, or has already been used.
</div>
{% endif %}
{% if quota %}
<div class="alert alert-warning">
{{ quota }}
</div>
{% endif %}
<fieldset>
<div class="row">
<div class="col-sm-12 col-md-12">
<p>Enter the 11-digits on your authenticator. Or input a recovery code</p>
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12">
<div class="form-group">
<div class="input-group mb-3">
<span class="input-group-addon input-group-text">
<i class="glyphicon glyphicon-lock bi bi-lock"></i>
</span>
<input class="form-control" size="11" MaxLength="11" value="" placeholder="e.g abcde-fghij" name="recovery" type="text" id="recovery" autofocus>
</div>
</div>
<div class="form-group d-grid gap-2">
<input type="{% if mode == "auth" %}submit{% elif mode == 'recheck' %}button{% endif %}" {% if mode == "recheck" %}onclick="send_recovery()" {% endif %} class="btn btn-lg btn-success btn-block" value="Sign in">
</div>
</div>
</fieldset>
</FORM>
</div>
<div class="row">
<div class="col-md-12 mb-3" style="padding-left: 25px">
{% if request.session.mfa_methods|length > 1 %}
<a href="{% url 'mfa_methods_list' %}">Select Another Method</a>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
{% include "modal.html" %}

View File

@@ -7,10 +7,22 @@
border: 1px solid #ccc;
border-radius: 3px;
padding: 15px;
}
}
.row{
margin: 0px;
}
.toolbtn {
border-radius: 7px;
cursor: pointer;
}
.toolbtn:hover {
background-color: gray;
transition: 0.2s;
}
.toolbtn:active {
background-color: green;
transition: 0.2s;
}
</style>
<script src="{% static 'mfa/js/qrious.min.js' %}" type="text/javascript"></script>
<script type="text/javascript">
@@ -29,8 +41,17 @@
})
});
function showKey() {
const htmlkey = `
<div class="row">
<div class="col-11">
<pre id="totp_secret">`+window.key+`</pre>
</div>
<div class="col-1">
<span onclick=navigator.clipboard.writeText($("#totp_secret").text()) class="fa fa-clipboard toolbtn"></span>
</div>
</div>`
$("#modal-title").html("Your Secret Key")
$("#modal-body").html("<pre>"+window.key+"</pre")
$("#modal-body").html(htmlkey)
$("#popUpModal").modal('show')
}
function verify() {
@@ -38,13 +59,16 @@
$.ajax({
"url":"{% url 'verify_otop' %}?key="+key+ "&answer="+answer,
success:function (data) {
if (data == "Error")
alert("You entered wrong numbers, please try again")
else
{
alert("Your authenticator is added successfully.")
window.location.href="{{ redirect_html }}"
}
if (data =='Success')
$("#res").html("<div class='alert alert-success'>Your authenticator is registered successfully, <a href='{{redirect_html}}'> {{reg_success_msg}}</a></div>")
else if (data == "RECOVERY")
{
setTimeout(function (){location.href="{% url 'manage_recovery_codes' %}"},2500)
$("#res").html("<div class='alert alert-success'>Your authenticator is registered successfully, but <a href='{% url 'manage_recovery_codes' %}'>redirecting to {{ RECOVERY_METHOD }} method</a></div>")
}
else
$("#res").html("<div class='alert alert-danger'>The code provided doesn't match the key, please try again or <a href='{% url 'mfa_home' %}'> Go to Security Home</a></div>")
}
})
}
@@ -66,21 +90,24 @@
<div class="container d-flex justify-content-center">
<div class="col-md-6 col-md-offset-3" id="two-factor-steps">
<div class="row" align="center">
<h4>Adding Authenticator</h4>
<h4>Adding a new {{ method.name }}</h4>
</div>
<div class="row">
<p>Scan the image below with the two-factor authentication app on your <a href="javascript:void(0)" onclick="showTOTP()">phone/PC</a>. If you cant use a barcode,
<a href="javascript:void(0)" onclick="showKey()">enter this text</a> instead. </p>
</div>
<div id="res">
<div class="row">
</div>
<div class="row" style="text-align: center">
<div align="center" style="display: none" id="second_step">
<div align="center" style="display: none;text-align: center;align-content: center" id="second_step">
<img id="qr"/>
</div>
</div>
<div class="row">
<p><b>Enter the six-digit code from the application</b></p>
@@ -88,16 +115,13 @@
</div>
<div class="row">
<div class="offset-md-4 col-md-4">
<input style="display: inline;width: 95%" maxlength="6" size="6" class="form-control" id="answer" placeholder="e.g 785481"/>
</div>
</div>
<div class="row" style="padding-top: 10px;">
<div class="col-md-6" style="padding-left: 0px">
<div class="col-md-4 offset-md-4" style="padding-left: 0px">
<button class="btn btn-success" onclick="verify()">Enable</button>
</div>
<div class="col-md-6" align="right" style="padding-right: 30px">
<a href="{% url 'mfa_home' %}" class="btn btn-default btn-secondary" role="button">Cancel</a>
</div>
</div>

View File

@@ -10,7 +10,6 @@
}
}
})
}
</script>
<div class='container'>
@@ -40,7 +39,7 @@
<fieldset>
<div class="row">
<div class="col-sm-12 col-md-12">
<p>Enter the 6-digits on your authenticator.</p>
<p>Enter the 6-digits on your authenticator</p>
</div>
</div>
@@ -58,8 +57,7 @@
<div class="form-group d-grid gap-2">
<input type="{% if mode == "auth" %}submit{% elif mode == 'recheck' %}button{% endif %}" {% if mode == "recheck" %}onclick="send_totp()" {% endif %} class="btn btn-lg btn-success btn-block" value="Sign in">
</div>
<input type="{% if mode == "auth" %}submit{% elif mode == 'recheck' %}button{% endif %}" {% if mode == "recheck" %}onclick="send_totp()" {% endif %} class="btn btn-lg btn-success btn-block" value="Sign in"> </div>
</div>
</fieldset>
</FORM>
@@ -76,3 +74,4 @@
</div>
</div>
</div>
{% include "modal.html" %}

View File

@@ -13,7 +13,7 @@
</style>
<script src="{% static 'mfa/js/u2f-api.js' %}" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function addToken() {
function addToken() {
data=JSON.parse('{{ token|safe }}')
console.log(data)
u2f.register(data.appId,data.registerRequests,data.registeredKeys,function (response) {
@@ -21,15 +21,24 @@
"url":"{% url 'bind_u2f' %}",method:"POST",
data:{"csrfmiddlewaretoken":"{{ csrf_token }}","response":JSON.stringify(response)},
success:function (data) {
if (data == "OK")
{
alert("Your device is added successfully.")
window.location.href="{{ redirect_html }}"
}
if (data =='OK')
$("#res").html("<div class='alert alert-success'>Your device is registered successfully, <a href='{{redirect_html}}'> {{reg_success_msg}}</a></div>")
else if (data == "RECOVERY")
{
setTimeout(function (){location.href="{% url 'manage_recovery_codes' %}"},2500)
$("#res").html("<div class='alert alert-success'>Your device is registered successfully, but <a href='{% url 'manage_recovery_codes' %}'>redirecting to {{ RECOVERY_METHOD }} method</a></div>")
}
else
$("#res").html("<div class='alert alert-danger'>Registration failed, please <a href='javascript:void(0)' onclick='addToken()'>try again</a> or <a href='{% url 'mfa_home' %}'> Go to Security Home</a></div>")
},
error: function (data)
{
$("#res").html("<div class='alert alert-danger'>Registration failed, please <a href='javascript:void(0)' onclick='addToken()'>try again</a> or <a href='{% url 'mfa_home' %}'> Go to Security Home</a></div>")
}
})
},5000)
})
}
$(document).ready(addToken())
</script>
{% endblock %}
@@ -37,9 +46,11 @@
<br/>
<br/>
<div class="container">
<div class="col-md-6 col-md-offset-3" id="two-factor-steps">
<div id="res"></div>
<div class="row" align="center">
<h4>Adding Security Key</h4>
<h4>Adding {{ method.name}}</h4>
</div>
<div class="row">
<p style="color: green">Your secure Key should be flashing now, please press on button.</p>

View File

@@ -4,7 +4,7 @@
<div class="col-sm-10 col-sm-offset-1 col-xs-12 col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2">
<div class="panel panel-default card">
<div class="panel-heading card-header">
<strong> Security Key</strong>
<strong> Verify your identity using {{ method.name }}</strong>
</div>
<div class="panel-body card-body">

View File

@@ -1,11 +1,10 @@
{% extends "mfa_auth_base.html" %}
{% block content %}
<br/>
<br/>
<div class='container'>
<div class="row">
<div class="col-sm-10 col-sm-offset-1 col-xs-12 col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2">
<div class="col-sm-10 col-sm-offset-1 col-xs-12 col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2 offset-2 col-8">
<div class="panel panel-default card">
<div class="panel-heading card-header">
<strong> Select Second Verification Method</strong>
@@ -15,10 +14,11 @@
{% for method in request.session.mfa_methods %}
<li><a href="{% url "mfa_goto" method %}">
{% if method == "TOTP" %}Authenticator App
{% elif method == "Email" %}Send OTP by Email
{% elif method == "U2F" %}Secure Key
{% elif method == "FIDO2" %}FIDO2 Secure Key
{% if method == "TOTP" %}{% if 'TOTP' in RENAME_METHODS %}{{ RENAME_METHODS.TOTP }}{% else %}Authenticator App{% endif %}
{% elif method == "Email" %}{% if 'Email' in RENAME_METHODS %}{{ RENAME_METHODS.Email }}{% else %}Send OTP by Email{% endif %}
{% elif method == "U2F" %}{% if 'U2F' in RENAME_METHODS %}{{ RENAME_METHODS.U2F }}{% else %}Secure Key{% endif %}
{% elif method == "FIDO2" %}{% if 'FIDO2' in RENAME_METHODS %}{{ RENAME_METHODS.FIDO2 }}{% else %}FIDO2 Secure Key{% endif %}
{% elif method == "RECOVERY" %}{% if 'RECOVERY' in RENAME_METHODS %}{{ RENAME_METHODS.RECOVERY }}{% else %}Recovery Code{% endif %}
{% endif %}
</a> </li>
{% endfor %}