2019-01-19 22:12:52 +01:00
|
|
|
<!DOCTYPE html>
|
|
|
|
<html lang="en">
|
|
|
|
<head>
|
2020-06-01 18:58:38 +02:00
|
|
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
|
|
|
<meta name="robots" content="noindex,nofollow" />
|
2021-05-08 17:46:31 +02:00
|
|
|
<link rel="icon" type="image/png" href="{{urlpath}}/bwrs_static/vaultwarden-icon.png">
|
2021-04-27 23:18:32 +02:00
|
|
|
<title>Vaultwarden Admin Panel</title>
|
2020-02-22 17:49:33 +01:00
|
|
|
<link rel="stylesheet" href="{{urlpath}}/bwrs_static/bootstrap.css" />
|
2019-01-19 22:12:52 +01:00
|
|
|
<style>
|
|
|
|
body {
|
2020-06-01 18:58:38 +02:00
|
|
|
padding-top: 75px;
|
2019-02-18 20:33:32 +01:00
|
|
|
}
|
2019-01-19 22:12:52 +01:00
|
|
|
img {
|
|
|
|
width: 48px;
|
|
|
|
height: 48px;
|
|
|
|
}
|
2021-06-19 19:22:19 +02:00
|
|
|
.vaultwarden-icon {
|
2021-05-08 17:46:31 +02:00
|
|
|
height: 32px;
|
2020-05-28 10:42:36 +02:00
|
|
|
width: auto;
|
2021-06-19 19:22:19 +02:00
|
|
|
margin: -5px 0 0 0;
|
2020-05-28 10:42:36 +02:00
|
|
|
}
|
2019-01-19 22:12:52 +01:00
|
|
|
</style>
|
2020-06-01 18:58:38 +02:00
|
|
|
<script src="{{urlpath}}/bwrs_static/identicon.js"></script>
|
2020-05-28 10:42:36 +02:00
|
|
|
<script>
|
2021-06-19 19:22:19 +02:00
|
|
|
'use strict';
|
|
|
|
|
2020-05-28 10:42:36 +02:00
|
|
|
function reload() { window.location.reload(); }
|
|
|
|
function msg(text, reload_page = true) {
|
|
|
|
text && alert(text);
|
|
|
|
reload_page && reload();
|
|
|
|
}
|
2021-02-27 06:48:01 +01:00
|
|
|
async function sha256(message) {
|
|
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest
|
|
|
|
const msgUint8 = new TextEncoder().encode(message);
|
|
|
|
const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8);
|
|
|
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
|
|
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
|
|
|
return hashHex;
|
|
|
|
}
|
|
|
|
async function identicon(email) {
|
|
|
|
const hash = await sha256(email);
|
|
|
|
const data = new Identicon(hash, { size: 48, format: 'svg' });
|
2020-05-28 10:42:36 +02:00
|
|
|
return "data:image/svg+xml;base64," + data.toString();
|
|
|
|
}
|
|
|
|
function toggleVis(input_id) {
|
|
|
|
const elem = document.getElementById(input_id);
|
|
|
|
const type = elem.getAttribute("type");
|
|
|
|
if (type === "text") {
|
|
|
|
elem.setAttribute("type", "password");
|
|
|
|
} else {
|
|
|
|
elem.setAttribute("type", "text");
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
function _post(url, successMsg, errMsg, body, reload_page = true) {
|
|
|
|
fetch(url, {
|
|
|
|
method: 'POST',
|
|
|
|
body: body,
|
|
|
|
mode: "same-origin",
|
|
|
|
credentials: "same-origin",
|
|
|
|
headers: { "Content-Type": "application/json" }
|
|
|
|
}).then( resp => {
|
|
|
|
if (resp.ok) { msg(successMsg, reload_page); return Promise.reject({error: false}); }
|
2021-10-08 00:01:24 +02:00
|
|
|
const respStatus = resp.status;
|
|
|
|
const respStatusText = resp.statusText;
|
2020-05-28 10:42:36 +02:00
|
|
|
return resp.text();
|
|
|
|
}).then( respText => {
|
|
|
|
try {
|
|
|
|
const respJson = JSON.parse(respText);
|
|
|
|
return respJson ? respJson.ErrorModel.Message : "Unknown error";
|
|
|
|
} catch (e) {
|
|
|
|
return Promise.reject({body:respStatus + ' - ' + respStatusText, error: true});
|
|
|
|
}
|
|
|
|
}).then( apiMsg => {
|
|
|
|
msg(errMsg + "\n" + apiMsg, reload_page);
|
|
|
|
}).catch( e => {
|
|
|
|
if (e.error === false) { return true; }
|
|
|
|
else { msg(errMsg + "\n" + e.body, reload_page); }
|
|
|
|
});
|
|
|
|
}
|
|
|
|
</script>
|
2019-01-19 22:12:52 +01:00
|
|
|
</head>
|
|
|
|
|
|
|
|
<body class="bg-light">
|
2020-06-01 18:58:38 +02:00
|
|
|
<nav class="navbar navbar-expand-md navbar-dark bg-dark mb-4 shadow fixed-top">
|
2021-01-19 17:55:21 +01:00
|
|
|
<div class="container-xl">
|
2021-06-19 19:22:19 +02:00
|
|
|
<a class="navbar-brand" href="{{urlpath}}/admin"><img class="vaultwarden-icon" src="{{urlpath}}/bwrs_static/vaultwarden-icon.png" alt="V">aultwarden Admin</a>
|
|
|
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse"
|
2020-06-01 18:58:38 +02:00
|
|
|
aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
|
|
|
|
<span class="navbar-toggler-icon"></span>
|
|
|
|
</button>
|
|
|
|
<div class="collapse navbar-collapse" id="navbarCollapse">
|
2021-06-19 19:22:19 +02:00
|
|
|
<ul class="navbar-nav me-auto">
|
2020-06-01 18:58:38 +02:00
|
|
|
{{#if logged_in}}
|
|
|
|
<li class="nav-item">
|
|
|
|
<a class="nav-link" href="{{urlpath}}/admin">Settings</a>
|
|
|
|
</li>
|
|
|
|
<li class="nav-item">
|
|
|
|
<a class="nav-link" href="{{urlpath}}/admin/users/overview">Users</a>
|
|
|
|
</li>
|
|
|
|
<li class="nav-item">
|
|
|
|
<a class="nav-link" href="{{urlpath}}/admin/organizations/overview">Organizations</a>
|
|
|
|
</li>
|
|
|
|
<li class="nav-item">
|
|
|
|
<a class="nav-link" href="{{urlpath}}/admin/diagnostics">Diagnostics</a>
|
|
|
|
</li>
|
|
|
|
{{/if}}
|
|
|
|
<li class="nav-item">
|
2021-01-19 17:55:21 +01:00
|
|
|
<a class="nav-link" href="{{urlpath}}/" target="_blank" rel="noreferrer">Vault</a>
|
2020-06-01 18:58:38 +02:00
|
|
|
</li>
|
|
|
|
</ul>
|
2019-12-01 21:15:14 +01:00
|
|
|
|
2020-06-01 18:58:38 +02:00
|
|
|
{{#if logged_in}}
|
|
|
|
<a class="btn btn-sm btn-secondary" href="{{urlpath}}/admin/logout">Log Out</a>
|
|
|
|
{{/if}}
|
|
|
|
</div>
|
|
|
|
</div>
|
2019-01-19 22:12:52 +01:00
|
|
|
</nav>
|
2019-02-05 22:17:02 +01:00
|
|
|
|
2021-06-16 22:57:28 +02:00
|
|
|
{{> (lookup this "page_content") }}
|
2020-05-28 10:42:36 +02:00
|
|
|
|
2020-06-01 18:58:38 +02:00
|
|
|
<!-- This script needs to be at the bottom, else it will fail! -->
|
2020-05-28 10:42:36 +02:00
|
|
|
<script>
|
2021-06-19 19:22:19 +02:00
|
|
|
'use strict';
|
|
|
|
|
2020-05-28 10:42:36 +02:00
|
|
|
// get current URL path and assign 'active' class to the correct nav-item
|
2021-06-19 19:22:19 +02:00
|
|
|
(() => {
|
2021-10-08 00:01:24 +02:00
|
|
|
const pathname = window.location.pathname;
|
2020-05-28 10:42:36 +02:00
|
|
|
if (pathname === "") return;
|
2021-10-08 00:01:24 +02:00
|
|
|
let navItem = document.querySelectorAll('.navbar-nav .nav-item a[href="'+pathname+'"]');
|
2020-05-28 10:42:36 +02:00
|
|
|
if (navItem.length === 1) {
|
2021-06-19 19:22:19 +02:00
|
|
|
navItem[0].className = navItem[0].className + ' active';
|
|
|
|
navItem[0].setAttribute('aria-current', 'page');
|
2020-05-28 10:42:36 +02:00
|
|
|
}
|
|
|
|
})();
|
|
|
|
</script>
|
2020-08-31 16:40:21 +02:00
|
|
|
<script src="{{urlpath}}/bwrs_static/bootstrap-native.js"></script>
|
2019-01-19 22:12:52 +01:00
|
|
|
</body>
|
2021-02-27 06:48:01 +01:00
|
|
|
</html>
|