only allow to copy the api key when it is created (#1059)
* show api key created time * only allow user to copy the api key when it is created * typo
This commit is contained in:
parent
84fcc9ddc4
commit
9cf2f44166
|
@ -50,6 +50,9 @@ def api_key():
|
||||||
)
|
)
|
||||||
Session.commit()
|
Session.commit()
|
||||||
flash(f"New API Key {new_api_key.name} has been created", "success")
|
flash(f"New API Key {new_api_key.name} has been created", "success")
|
||||||
|
return render_template(
|
||||||
|
"dashboard/new_api_key.html", api_key=new_api_key
|
||||||
|
)
|
||||||
|
|
||||||
elif request.form.get("form-name") == "delete-all":
|
elif request.form.get("form-name") == "delete-all":
|
||||||
ApiKey.delete_all(current_user.id)
|
ApiKey.delete_all(current_user.id)
|
||||||
|
|
|
@ -13,8 +13,11 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h1 class="h3"> API Keys </h1>
|
<h1 class="h3"> API Keys </h1>
|
||||||
<div class="small-text">
|
|
||||||
API keys are used by the SimpleLogin browser extensions or mobile apps.
|
<div class="alert alert-info">
|
||||||
|
When you log in on a SimpleLogin mobile app or browser extension,
|
||||||
|
a new API Key is automatically created and stored on your device.
|
||||||
|
It's usually named after the device where it was created, e.g. Samsung S8, John's iPhone, etc.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,8 +33,10 @@
|
||||||
<h5 class="card-title">{{ api_key.name or "N/A" }}</h5>
|
<h5 class="card-title">{{ api_key.name or "N/A" }}</h5>
|
||||||
<h6 class="card-subtitle mb-2 text-muted">
|
<h6 class="card-subtitle mb-2 text-muted">
|
||||||
{% if api_key.last_used %}
|
{% if api_key.last_used %}
|
||||||
Last used: {{ api_key.last_used | dt }} <br>
|
Created {{ api_key.created_at | dt }}.
|
||||||
Used: {{ api_key.times }} times.
|
Used {{ api_key.times }} times.
|
||||||
|
Was last used {{ api_key.last_used | dt }}.
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
Never used
|
Never used
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -39,24 +44,11 @@
|
||||||
|
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input class="form-control" id="apikey-{{ api_key.id }}" readonly value="**********">
|
<input class="form-control" id="apikey-{{ api_key.id }}" readonly value="**********">
|
||||||
<div class="input-group-append">
|
|
||||||
<span class="input-group-text">
|
|
||||||
<i class="fe fe-eye toggle-api-key" data-show="off" data-secret="{{ api_key.code }}"
|
|
||||||
></i>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
|
||||||
<button class="clipboard btn btn-primary" data-clipboard-action="copy"
|
|
||||||
data-clipboard-text="{{ api_key.code }}"
|
|
||||||
data-clipboard-target="#apikey-{{ api_key.id }}">
|
|
||||||
Copy <i class="fe fe-clipboard"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<form method="post">
|
<form method="post">
|
||||||
|
@ -78,13 +70,15 @@
|
||||||
{% if api_keys|length > 0 %}
|
{% if api_keys|length > 0 %}
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<input type="hidden" name="form-name" value="delete-all">
|
<input type="hidden" name="form-name" value="delete-all">
|
||||||
<span class="delete btn btn-danger delete-all-api-keys">
|
<span class="delete btn btn-outline-danger delete-all-api-keys float-right">
|
||||||
Delete All <i class="fe fe-trash"></i>
|
Delete All <i class="fe fe-trash"></i>
|
||||||
</span>
|
</span>
|
||||||
</form>
|
</form>
|
||||||
<br>
|
<br>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
<form method="post">
|
<form method="post">
|
||||||
{{ new_api_key_form.csrf_token }}
|
{{ new_api_key_form.csrf_token }}
|
||||||
<input type="hidden" name="form-name" value="create">
|
<input type="hidden" name="form-name" value="create">
|
||||||
|
@ -109,7 +103,7 @@
|
||||||
let that = $(this);
|
let that = $(this);
|
||||||
|
|
||||||
bootbox.confirm({
|
bootbox.confirm({
|
||||||
message: "If this api key is currently in use, you need to replace it with another api key, please confirm.",
|
message: "If this API Key is currently in use, you might need to login again on the corresponding device, please confirm.",
|
||||||
buttons: {
|
buttons: {
|
||||||
confirm: {
|
confirm: {
|
||||||
label: 'Yes, delete it',
|
label: 'Yes, delete it',
|
||||||
|
@ -131,46 +125,29 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".delete-all-api-keys").on("click", function (e) {
|
$(".delete-all-api-keys").on("click", function (e) {
|
||||||
let that = $(this);
|
|
||||||
|
|
||||||
bootbox.confirm({
|
|
||||||
message: "This will delete all API Keys, they will all stop working, are you sure?",
|
|
||||||
buttons: {
|
|
||||||
confirm: {
|
|
||||||
label: 'Delete All',
|
|
||||||
className: 'btn-danger'
|
|
||||||
},
|
|
||||||
cancel: {
|
|
||||||
label: 'Cancel',
|
|
||||||
className: 'btn-outline-primary'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
callback: function (result) {
|
|
||||||
if (result) {
|
|
||||||
that.closest("form").submit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
$(".toggle-api-key").on('click', function (event) {
|
|
||||||
let that = $(this);
|
let that = $(this);
|
||||||
let apiInput = that.parent().parent().parent().find("input");
|
|
||||||
if (that.attr("data-show") === "off") {
|
bootbox.confirm({
|
||||||
let apiKey = $(this).attr("data-secret");
|
message: "This will delete all API Keys, they will all stop working, are you sure?",
|
||||||
apiInput.val(apiKey);
|
buttons: {
|
||||||
that.addClass("fe-eye-off");
|
confirm: {
|
||||||
that.removeClass("fe-eye");
|
label: 'Delete All',
|
||||||
that.attr("data-show", "on");
|
className: 'btn-danger'
|
||||||
} else {
|
},
|
||||||
that.removeClass("fe-eye-off");
|
cancel: {
|
||||||
that.addClass("fe-eye");
|
label: 'Cancel',
|
||||||
apiInput.val("**********");
|
className: 'btn-outline-primary'
|
||||||
that.attr("data-show", "off");
|
}
|
||||||
}
|
},
|
||||||
|
callback: function (result) {
|
||||||
|
if (result) {
|
||||||
|
that.closest("form").submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
60
templates/dashboard/new_api_key.html
Normal file
60
templates/dashboard/new_api_key.html
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
{% extends 'default.html' %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
API Key
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% set active_page = "api_key" %}
|
||||||
|
|
||||||
|
{% block default_content %}
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h1 class="h3">New API Key {{ api_key.name }} is created </h1>
|
||||||
|
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
For security reasons, API Key is only visible when it is created.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input-group mb-2">
|
||||||
|
<input class="form-control" id="apikey-{{ api_key.id }}" readonly value="**********">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<span class="input-group-text">
|
||||||
|
<i class="fe fe-eye toggle-api-key" data-show="off" data-secret="{{ api_key.code }}"
|
||||||
|
></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="clipboard btn btn-primary" data-clipboard-action="copy"
|
||||||
|
data-clipboard-text="{{ api_key.code }}"
|
||||||
|
data-clipboard-target="#apikey-{{ api_key.id }}">
|
||||||
|
Copy <i class="fe fe-clipboard"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block script %}
|
||||||
|
<script>
|
||||||
|
|
||||||
|
$(".toggle-api-key").on('click', function (event) {
|
||||||
|
let that = $(this);
|
||||||
|
let apiInput = that.parent().parent().parent().find("input");
|
||||||
|
if (that.attr("data-show") === "off") {
|
||||||
|
let apiKey = $(this).attr("data-secret");
|
||||||
|
apiInput.val(apiKey);
|
||||||
|
that.addClass("fe-eye-off");
|
||||||
|
that.removeClass("fe-eye");
|
||||||
|
that.attr("data-show", "on");
|
||||||
|
} else {
|
||||||
|
that.removeClass("fe-eye-off");
|
||||||
|
that.addClass("fe-eye");
|
||||||
|
apiInput.val("**********");
|
||||||
|
that.attr("data-show", "off");
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
Loading…
Reference in a new issue