12 changed files with 362 additions and 315 deletions
			
			
		| @ -1,195 +0,0 @@ | |||||
| <!DOCTYPE html> |  | ||||
| <html lang="en"> |  | ||||
| 
 |  | ||||
| <head> |  | ||||
|     <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="description" content=""> |  | ||||
|     <meta name="author" content=""> |  | ||||
|     <title>Bitwarden_rs Admin Panel</title> |  | ||||
| 
 |  | ||||
|     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" |  | ||||
|         integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE=" crossorigin="anonymous" /> |  | ||||
|     <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" |  | ||||
|         crossorigin="anonymous"></script> |  | ||||
|     <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.10.0/js/md5.js" integrity="sha256-tCQ/BldMlN2vWe5gAiNoNb5svoOgVUhlUgv7UjONKKQ=" |  | ||||
|         crossorigin="anonymous"></script> |  | ||||
|     <script src="https://cdnjs.cloudflare.com/ajax/libs/identicon.js/2.3.3/identicon.min.js" integrity="sha256-nYoL3nK/HA1e1pJvLwNPnpKuKG9q89VFX862r5aohmA=" |  | ||||
|         crossorigin="anonymous"></script> |  | ||||
| 
 |  | ||||
|     <style> |  | ||||
|         body { padding-top: 70px; } |  | ||||
|         img { width: 48px; height: 48px; } |  | ||||
|     </style> |  | ||||
| 
 |  | ||||
|     <script> |  | ||||
|         let key = null; |  | ||||
| 
 |  | ||||
|         function identicon(email) { |  | ||||
|             const data = new Identicon(md5(email), { |  | ||||
|                 size: 48, format: 'svg' |  | ||||
|             }).toString(); |  | ||||
|             return "data:image/svg+xml;base64," + data; |  | ||||
|         } |  | ||||
| 
 |  | ||||
|         function setVis(elem, vis) { |  | ||||
|             if (vis) { $(elem).removeClass('d-none'); } |  | ||||
|             else { $(elem).addClass('d-none'); } |  | ||||
|         } |  | ||||
| 
 |  | ||||
|         function updateVis() { |  | ||||
|             setVis("#no-key-form", !key); |  | ||||
|             setVis("#users-block", key); |  | ||||
|             setVis("#invite-form-block", key); |  | ||||
|         } |  | ||||
| 
 |  | ||||
|         function setKey() { |  | ||||
|             key = $('#key').val() || window.location.hash.slice(1); |  | ||||
|             updateVis(); |  | ||||
|             if (key) { loadUsers(); } |  | ||||
|             return false; |  | ||||
|         } |  | ||||
| 
 |  | ||||
|         function resetKey() { |  | ||||
|             key = null; |  | ||||
|             updateVis(); |  | ||||
|         } |  | ||||
| 
 |  | ||||
|         function fillRow(data) { |  | ||||
|             for (i in data) { |  | ||||
|                 const user = data[i]; |  | ||||
|                 const row = $("#tmp-row").clone(); |  | ||||
| 
 |  | ||||
|                 row.attr("id", "user-row:" + user.Id); |  | ||||
|                 row.find(".tmp-name").text(user.Name); |  | ||||
|                 row.find(".tmp-mail").text(user.Email); |  | ||||
|                 row.find(".tmp-icon").attr("src", identicon(user.Email)) |  | ||||
| 
 |  | ||||
|                 row.find(".tmp-del").on("click", function (e) { |  | ||||
|                     var name = prompt("To delete user '" + user.Name + "', please type the name below") |  | ||||
|                     if (name) { |  | ||||
|                         if (name == user.Name) { |  | ||||
|                             deleteUser(user.Id); |  | ||||
|                         } else { |  | ||||
|                             alert("Wrong name, please try again") |  | ||||
|                         } |  | ||||
|                     } |  | ||||
|                     return false; |  | ||||
|                 }); |  | ||||
| 
 |  | ||||
|                 row.appendTo("#users-list"); |  | ||||
|                 setVis(row, true); |  | ||||
|             } |  | ||||
|         } |  | ||||
| 
 |  | ||||
|         function _headers() { return { "Authorization": "Bearer " + key }; } |  | ||||
| 
 |  | ||||
|         function loadUsers() { |  | ||||
|             $("#users-list").empty(); |  | ||||
|             $.get({ url: "/admin/users", headers: _headers() }) |  | ||||
|                 .done(fillRow).fail(resetKey); |  | ||||
| 
 |  | ||||
|             return false; |  | ||||
|         } |  | ||||
| 
 |  | ||||
|         function _post(url, successMsg, errMsg, resetOnErr, data) { |  | ||||
|             $.post({ url: url, headers: _headers(), data: data }) |  | ||||
|                 .done(function () { |  | ||||
|                     alert(successMsg); |  | ||||
|                     loadUsers(); |  | ||||
|                 }).fail(function (e) { |  | ||||
|                     const r = e.responseJSON; |  | ||||
|                     const msg = r ? r.ErrorModel.Message : "Unknown error"; |  | ||||
|                     alert(errMsg + ": " + msg); |  | ||||
|                     if (resetOnErr) { resetKey(); } |  | ||||
|                 }); |  | ||||
|         } |  | ||||
| 
 |  | ||||
|         function deleteUser(id) { |  | ||||
|             _post("/admin/users/" + id + "/delete", |  | ||||
|                 "User deleted correctly", |  | ||||
|                 "Error deleting user", true); |  | ||||
|         } |  | ||||
| 
 |  | ||||
|         function inviteUser() { |  | ||||
|             inv = $("#email-invite"); |  | ||||
|             data = JSON.stringify({ "Email": inv.val() }); |  | ||||
|             inv.val(""); |  | ||||
|             _post("/admin/invite/", "User invited correctly", |  | ||||
|                 "Error inviting user", false, data); |  | ||||
|             return false; |  | ||||
|         } |  | ||||
| 
 |  | ||||
|         $(window).on('load', function () { |  | ||||
|             setKey(); |  | ||||
| 
 |  | ||||
|             $("#key-form").submit(setKey); |  | ||||
|             $("#reload-btn").click(loadUsers); |  | ||||
|             $("#invite-form").submit(inviteUser); |  | ||||
|         }); |  | ||||
|     </script> |  | ||||
| </head> |  | ||||
| 
 |  | ||||
| <body class="bg-light"> |  | ||||
|     <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top shadow"> |  | ||||
|         <a class="navbar-brand" href="#">Bitwarden_rs</a> |  | ||||
|         <div class="navbar-collapse"> |  | ||||
|             <ul class="navbar-nav"> |  | ||||
|                 <li class="nav-item active"> |  | ||||
|                     <a class="nav-link" href="/admin">Admin Panel</a> |  | ||||
|                 </li> |  | ||||
|                 <li class="nav-item"> |  | ||||
|                     <a class="nav-link" href="/">Vault</a> |  | ||||
|                 </li> |  | ||||
|             </ul> |  | ||||
|         </div> |  | ||||
|     </nav> |  | ||||
|     <main class="container"> |  | ||||
|         <div id="no-key-form" class="d-none align-items-center p-3 mb-3 text-white-50 bg-danger rounded shadow"> |  | ||||
|             <div> |  | ||||
|                 <h6 class="mb-0 text-white">Authentication key needed to continue</h6> |  | ||||
|                 <small>Please provide it below:</small> |  | ||||
| 
 |  | ||||
|                 <form class="form-inline" id="key-form"> |  | ||||
|                     <input type="password" class="form-control w-50 mr-2" id="key" placeholder="Enter admin key"> |  | ||||
|                     <button type="submit" class="btn btn-primary">Save</button> |  | ||||
|                 </form> |  | ||||
|             </div> |  | ||||
|         </div> |  | ||||
| 
 |  | ||||
|         <div id="users-block" class="d-none my-3 p-3 bg-white rounded shadow"> |  | ||||
|             <h6 class="border-bottom pb-2 mb-0">Registered Users</h6> |  | ||||
| 
 |  | ||||
|             <div id="users-list"></div> |  | ||||
| 
 |  | ||||
|             <small class="d-block text-right mt-3"> |  | ||||
|                 <a id="reload-btn" href="#">Reload users</a> |  | ||||
|             </small> |  | ||||
|         </div> |  | ||||
| 
 |  | ||||
|         <div id="invite-form-block" class="d-none align-items-center p-3 mb-3 text-white-50 bg-secondary rounded shadow"> |  | ||||
|             <div> |  | ||||
|                 <h6 class="mb-0 text-white">Invite User</h6> |  | ||||
|                 <small>Email:</small> |  | ||||
| 
 |  | ||||
|                 <form class="form-inline" id="invite-form"> |  | ||||
|                     <input type="email" class="form-control w-50 mr-2" id="email-invite" placeholder="Enter email"> |  | ||||
|                     <button type="submit" class="btn btn-primary">Invite</button> |  | ||||
|                 </form> |  | ||||
|             </div> |  | ||||
|         </div> |  | ||||
| 
 |  | ||||
|         <div id="tmp-row" class="d-none media pt-3"> |  | ||||
|             <img class="mr-2 rounded tmp-icon"> |  | ||||
|             <div class="media-body pb-3 mb-0 small border-bottom"> |  | ||||
|                 <div class="d-flex justify-content-between"> |  | ||||
|                     <strong class="tmp-name">Full Name</strong> |  | ||||
|                     <a class="tmp-del mr-3" href="#">Delete User</a> |  | ||||
|                 </div> |  | ||||
|                 <span class="d-block tmp-mail">Email</span> |  | ||||
|             </div> |  | ||||
|         </div> |  | ||||
|     </main> |  | ||||
| </body> |  | ||||
| 
 |  | ||||
| </html> |  | ||||
| @ -0,0 +1,54 @@ | |||||
|  | <!DOCTYPE html> | ||||
|  | <html lang="en"> | ||||
|  | 
 | ||||
|  | <head> | ||||
|  |     <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"> | ||||
|  |     <title>Bitwarden_rs Admin Panel</title> | ||||
|  | 
 | ||||
|  |     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha256-azvvU9xKluwHFJ0Cpgtf0CYzK7zgtOznnzxV4924X1w=" crossorigin="anonymous" /> | ||||
|  |     <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> | ||||
|  | 
 | ||||
|  |     <style> | ||||
|  |         body { padding-top: 70px; } | ||||
|  |     </style> | ||||
|  | </head> | ||||
|  | 
 | ||||
|  | <body class="bg-light"> | ||||
|  |     <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top shadow"> | ||||
|  |         <a class="navbar-brand" href="#">Bitwarden_rs</a> | ||||
|  |         <div class="navbar-collapse"> | ||||
|  |             <ul class="navbar-nav"> | ||||
|  |                 <li class="nav-item active"> | ||||
|  |                     <a class="nav-link" href="/admin">Admin Panel</a> | ||||
|  |                 </li> | ||||
|  |                 <li class="nav-item"> | ||||
|  |                     <a class="nav-link" href="/">Vault</a> | ||||
|  |                 </li> | ||||
|  |             </ul> | ||||
|  |         </div> | ||||
|  |     </nav> | ||||
|  |     <main class="container"> | ||||
|  |         {{#if error}} | ||||
|  |         <div class="align-items-center p-3 mb-3 text-white-50 bg-warning rounded shadow"> | ||||
|  |             <div> | ||||
|  |                 <h6 class="mb-0 text-white">{{error}}</h6> | ||||
|  |             </div> | ||||
|  |         </div> | ||||
|  |         {{/if}} | ||||
|  | 
 | ||||
|  |         <div class="align-items-center p-3 mb-3 text-white-50 bg-danger rounded shadow"> | ||||
|  |             <div> | ||||
|  |                 <h6 class="mb-0 text-white">Authentication key needed to continue</h6> | ||||
|  |                 <small>Please provide it below:</small> | ||||
|  | 
 | ||||
|  |                 <form class="form-inline" method="post"> | ||||
|  |                     <input type="password" class="form-control w-50 mr-2" name="token" placeholder="Enter admin token"> | ||||
|  |                     <button type="submit" class="btn btn-primary">Save</button> | ||||
|  |                 </form> | ||||
|  |             </div> | ||||
|  |         </div> | ||||
|  |     </main> | ||||
|  | </body> | ||||
|  | 
 | ||||
|  | </html> | ||||
| @ -0,0 +1,124 @@ | |||||
|  | <!DOCTYPE html> | ||||
|  | <html lang="en"> | ||||
|  | 
 | ||||
|  | <head> | ||||
|  |     <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"> | ||||
|  |     <title>Bitwarden_rs Admin Panel</title> | ||||
|  | 
 | ||||
|  |     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.min.css" | ||||
|  |         integrity="sha256-azvvU9xKluwHFJ0Cpgtf0CYzK7zgtOznnzxV4924X1w=" crossorigin="anonymous" /> | ||||
|  |     <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" | ||||
|  |         crossorigin="anonymous"></script> | ||||
|  |     <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.10.0/js/md5.js" integrity="sha256-tCQ/BldMlN2vWe5gAiNoNb5svoOgVUhlUgv7UjONKKQ=" | ||||
|  |         crossorigin="anonymous"></script> | ||||
|  |     <script src="https://cdnjs.cloudflare.com/ajax/libs/identicon.js/2.3.3/identicon.min.js" integrity="sha256-nYoL3nK/HA1e1pJvLwNPnpKuKG9q89VFX862r5aohmA=" | ||||
|  |         crossorigin="anonymous"></script> | ||||
|  | 
 | ||||
|  |     <style> | ||||
|  |         body { padding-top: 70px; } | ||||
|  |         img { width: 48px; height: 48px; } | ||||
|  |     </style> | ||||
|  | 
 | ||||
|  |     <script> | ||||
|  |         function reload() { window.location.reload(); } | ||||
|  |         function identicon(email) { | ||||
|  |             const data = new Identicon(md5(email), { size: 48, format: 'svg' }); | ||||
|  |             return "data:image/svg+xml;base64," + data.toString(); | ||||
|  |         } | ||||
|  |         function _post(url, successMsg, errMsg, data) { | ||||
|  |             $.post({ url: url, data: data }) | ||||
|  |                 .done(function () { | ||||
|  |                     alert(successMsg); | ||||
|  |                     reload(); | ||||
|  |                 }).fail(function (e) { | ||||
|  |                     const r = e.responseJSON; | ||||
|  |                     const msg = r ? r.ErrorModel.Message : "Unknown error"; | ||||
|  |                     alert(errMsg + ": " + msg); | ||||
|  |                 }); | ||||
|  |         } | ||||
|  |         function deleteUser(id, mail) { | ||||
|  |             var input_mail = prompt("To delete user '" + mail + "', please type the name below") | ||||
|  |             if (input_mail) { | ||||
|  |                 if (input_mail == mail) { | ||||
|  |                     _post("/admin/users/" + id + "/delete", | ||||
|  |                         "User deleted correctly", | ||||
|  |                         "Error deleting user"); | ||||
|  |                 } else { | ||||
|  |                     alert("Wrong email, please try again") | ||||
|  |                 } | ||||
|  |             } | ||||
|  |         } | ||||
|  |         function inviteUser() { | ||||
|  |             inv = $("#email-invite"); | ||||
|  |             data = JSON.stringify({ "Email": inv.val() }); | ||||
|  |             inv.val(""); | ||||
|  |             _post("/admin/invite/", "User invited correctly", | ||||
|  |                 "Error inviting user", data); | ||||
|  |         } | ||||
|  | 
 | ||||
|  |         $(window).on('load', function () { | ||||
|  |             //$("#reload-btn").click(reload); | ||||
|  |             $("#invite-form").submit(inviteUser); | ||||
|  |             $("img.identicon").each(function (i, e) { | ||||
|  |                 e.src = identicon(e.dataset.src); | ||||
|  |             }); | ||||
|  |         }); | ||||
|  |     </script> | ||||
|  | </head> | ||||
|  | 
 | ||||
|  | <body class="bg-light"> | ||||
|  |     <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top shadow"> | ||||
|  |         <a class="navbar-brand" href="#">Bitwarden_rs</a> | ||||
|  |         <div class="navbar-collapse"> | ||||
|  |             <ul class="navbar-nav"> | ||||
|  |                 <li class="nav-item active"> | ||||
|  |                     <a class="nav-link" href="/admin">Admin Panel</a> | ||||
|  |                 </li> | ||||
|  |                 <li class="nav-item"> | ||||
|  |                     <a class="nav-link" href="/">Vault</a> | ||||
|  |                 </li> | ||||
|  |             </ul> | ||||
|  |         </div> | ||||
|  |     </nav> | ||||
|  |     <main class="container"> | ||||
|  |         <div id="users-block" class="my-3 p-3 bg-white rounded shadow"> | ||||
|  |             <h6 class="border-bottom pb-2 mb-0">Registered Users</h6> | ||||
|  | 
 | ||||
|  |             <div id="users-list"> | ||||
|  |                 {{#each users}} | ||||
|  |                 <div class="media pt-3"> | ||||
|  |                     {{!-- row.find(".tmp-icon").attr("src", identicon(user.Email)) --}} | ||||
|  |                     <img class="mr-2 rounded identicon" data-src="{{Email}}"> | ||||
|  |                     <div class="media-body pb-3 mb-0 small border-bottom"> | ||||
|  |                         <div class="d-flex justify-content-between"> | ||||
|  |                             <strong>{{Name}}</strong> | ||||
|  |                             <a class="tmp-del mr-3" href="" onclick='deleteUser("{{Id}}", "{{Email}}");'>Delete User</a> | ||||
|  |                         </div> | ||||
|  |                         <span class="d-block">{{Email}}</span> | ||||
|  |                     </div> | ||||
|  |                 </div> | ||||
|  |                 {{/each}} | ||||
|  | 
 | ||||
|  |             </div> | ||||
|  | 
 | ||||
|  |             <small class="d-block text-right mt-3"> | ||||
|  |                 <a id="reload-btn" href="">Reload users</a> | ||||
|  |             </small> | ||||
|  |         </div> | ||||
|  | 
 | ||||
|  |         <div id="invite-form-block" class="align-items-center p-3 mb-3 text-white-50 bg-secondary rounded shadow"> | ||||
|  |             <div> | ||||
|  |                 <h6 class="mb-0 text-white">Invite User</h6> | ||||
|  |                 <small>Email:</small> | ||||
|  | 
 | ||||
|  |                 <form class="form-inline" id="invite-form"> | ||||
|  |                     <input type="email" class="form-control w-50 mr-2" id="email-invite" placeholder="Enter email"> | ||||
|  |                     <button type="submit" class="btn btn-primary">Invite</button> | ||||
|  |                 </form> | ||||
|  |             </div> | ||||
|  |         </div> | ||||
|  |     </main> | ||||
|  | </body> | ||||
|  | 
 | ||||
|  | </html> | ||||
					Loading…
					
					
				
		Reference in new issue