aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Crute <mike@crute.us>2021-11-24 12:00:07 -0800
committerMike Crute <mike@crute.us>2021-11-24 12:10:53 -0800
commita7646122d8e0a82cbf9c8b81451c28fbc650c8f6 (patch)
tree622d21740b2aa0fe29ee81b56aa43a59fe8b89d0
parentbb96127a71d3d22825a35ffc6b6c8bea0590f202 (diff)
downloadcloud-identity-broker-a7646122d8e0a82cbf9c8b81451c28fbc650c8f6.tar.bz2
cloud-identity-broker-a7646122d8e0a82cbf9c8b81451c28fbc650c8f6.tar.xz
cloud-identity-broker-a7646122d8e0a82cbf9c8b81451c28fbc650c8f6.zip
Cleanup index template
-rw-r--r--templates/assets/site.css46
-rw-r--r--templates/assets/site.js51
-rw-r--r--templates/index.tpl17
3 files changed, 79 insertions, 35 deletions
diff --git a/templates/assets/site.css b/templates/assets/site.css
index 65fb4ce..df1bab8 100644
--- a/templates/assets/site.css
+++ b/templates/assets/site.css
@@ -35,6 +35,15 @@ tt {
35 border: 1px solid #999; 35 border: 1px solid #999;
36 padding: 0.25em; 36 padding: 0.25em;
37} 37}
38#username {
39 font-weight: bolder;
40}
41#login-row {
42 text-align: right;
43}
44#api-key-block {
45 display: none;
46}
38#api-key { 47#api-key {
39 margin: auto; 48 margin: auto;
40} 49}
@@ -43,13 +52,26 @@ tt {
43} 52}
44#api-error { 53#api-error {
45 border: 0.25em solid red; 54 border: 0.25em solid red;
46 color: white; 55 color: yellow;
47 font-size: 2em; 56 font-size: 2em;
48 background-color: #ff8080; 57 background-color: #ff8080;
49 padding: 1em; 58 padding: 1em;
50 text-align: center; 59 text-align: center;
51 display: none; 60 display: none;
52} 61}
62#api-error .sub-message {
63 font-size: 1rem;
64 color: white;
65}
66#api-success {
67 border: 0.25em solid green;
68 color: green;
69 font-size: 2em;
70 background-color: #00ff80;
71 padding: 1em;
72 text-align: center;
73 display: none;
74}
53#account-table tr td:nth-child(2), 75#account-table tr td:nth-child(2),
54#account-table tr td:nth-child(3) { 76#account-table tr td:nth-child(3) {
55 text-align: center; 77 text-align: center;
@@ -60,3 +82,25 @@ tt {
60body.isAdmin .admin { 82body.isAdmin .admin {
61 display: initial; 83 display: initial;
62} 84}
85.tag {
86 display: block;
87 float: right;
88 color: white;
89 font-size: 0.8em;
90 border-radius: 0.3em;
91 padding: 0.2em 0.5em;
92 cursor: default;
93}
94.vendor-aws {
95 background-color: orange;
96}
97.vendor-gcp {
98 background-color: blue;
99}
100.vendor-oci {
101 background-color: red;
102}
103.vendor-azure {
104 color: black;
105 background-color: lightblue;
106}
diff --git a/templates/assets/site.js b/templates/assets/site.js
index ebf9f5f..7ba4b15 100644
--- a/templates/assets/site.js
+++ b/templates/assets/site.js
@@ -1,12 +1,12 @@
1function fillTemplate(templateId, values) { 1function fillTemplate(templateId, values) {
2 var tpl = document.getElementById(templateId).text; 2 var tpl = document.getElementById(templateId).text;
3 3
4 Object.keys(values).forEach(function(key) { 4 Object.keys(values).forEach(key => {
5 tpl = tpl.replace(new RegExp("\\[\\[ \\." + key + " \\]\\]", "g"), values[key]); 5 tpl = tpl.replace(new RegExp("\\[\\[ \\." + key + " \\]\\]", "g"), values[key]);
6 }); 6 });
7 7
8 var out = []; 8 var out = [];
9 tpl.split("\n").forEach(function(line) { 9 tpl.split("\n").forEach(line => {
10 line = line.replace(/^\s+/, "").replace(/\s+$/, ""); 10 line = line.replace(/^\s+/, "").replace(/\s+$/, "");
11 if (line !== "") { 11 if (line !== "") {
12 out.push(line); 12 out.push(line);
@@ -43,7 +43,7 @@ function accountTableLinkClick(event) {
43 "headers": { 43 "headers": {
44 "Accept": event.target.dataset["contentType"] 44 "Accept": event.target.dataset["contentType"]
45 } 45 }
46 }).then(r => r.text()).then(function(text) { 46 }).then(r => r.text()).then(text => {
47 var newTr = fillTemplate("credential_row_template", { 47 var newTr = fillTemplate("credential_row_template", {
48 "Account": account, 48 "Account": account,
49 "Content": text, 49 "Content": text,
@@ -51,25 +51,19 @@ function accountTableLinkClick(event) {
51 51
52 event.target.text = oldText; 52 event.target.text = oldText;
53 thisRow.insertAdjacentHTML("afterend", newTr); 53 thisRow.insertAdjacentHTML("afterend", newTr);
54 thisRow.nextElementSibling.getElementsByTagName("button")[0].addEventListener("click", function(event) { 54 thisRow.nextElementSibling.getElementsByTagName("button")[0].addEventListener("click", e => {
55 event.target.parentNode.parentNode.remove(); 55 e.target.parentNode.parentNode.remove();
56 }); 56 });
57 }); 57 });
58 58
59 return false; 59 return false;
60} 60}
61 61
62function populateAccountTable() {
63 fetch("/api/account").then(getJSON).then(function(response) {
64 response.forEach(populateAccountRow);
65 });
66}
67
68function populateAccountRow(row) { 62function populateAccountRow(row) {
69 var out = fillTemplate("account_row_template", row); 63 document.querySelector("#account-table tr").insertAdjacentHTML("afterend",
70 document.querySelector("#account-table tr").insertAdjacentHTML("afterend", out); 64 fillTemplate(row["vendor"] + "_account_row_template", row));
71 65
72 document.querySelectorAll(".account-row a[data-content-type]").forEach(function(e) { 66 document.querySelectorAll(".account-row a[data-content-type]").forEach(e => {
73 e.addEventListener("click", accountTableLinkClick); 67 e.addEventListener("click", accountTableLinkClick);
74 }); 68 });
75} 69}
@@ -78,25 +72,30 @@ function getCookie(name) {
78 return document.cookie.match(new RegExp(name + "=\"?([^;\"]*)\"?;?"))[1]; 72 return document.cookie.match(new RegExp(name + "=\"?([^;\"]*)\"?;?"))[1];
79} 73}
80 74
81function parseJWT(token) { 75function parseJWT() {
82 return JSON.parse(atob(token.split(".")[1])); 76 return JSON.parse(atob(getCookie("github-token").split(".")[1]));
83} 77}
84 78
85function parseJWTExpires(token) { 79function parseJWTExpires() {
86 return new Date(parseJWT(token)["exp"] * 1000); 80 return new Date(parseJWT()["exp"] * 1000);
87} 81}
88 82
89function isAdmin(token) { 83function isAdmin() {
90 return parseJWT(token)["admin"]; 84 return parseJWT()["admin"];
91} 85}
92 86
93function populateAPIKey() { 87function setupHomePage() {
94 document.querySelector("#api-key textarea").innerText = getCookie("github-token"); 88 fetch("/api/account").then(getJSON).then(r => r.forEach(populateAccountRow));
95 document.querySelector("#session-expires").innerText = parseJWTExpires(getCookie("github-token"));
96}
97 89
98function setAdminClass() { 90 document.getElementById("username").innerText = parseJWT()["sub"];
99 if (isAdmin(getCookie("github-token"))) { 91
92 if (isAdmin()) {
100 document.body.classList.add("isAdmin"); 93 document.body.classList.add("isAdmin");
101 } 94 }
95
96 document.getElementById("show-api-key").addEventListener("click", _ => {
97 document.querySelector("#api-key textarea").innerText = getCookie("github-token");
98 document.querySelector("#session-expires").innerText = parseJWTExpires();
99 document.getElementById("api-key-block").style.display = "block";
100 });
102} 101}
diff --git a/templates/index.tpl b/templates/index.tpl
index c8c95d4..9baef2a 100644
--- a/templates/index.tpl
+++ b/templates/index.tpl
@@ -12,10 +12,9 @@
12 </td> 12 </td>
13 </tr> 13 </tr>
14 </script> 14 </script>
15 <script id="account_row_template" type="text/template"> 15 <script id="aws_account_row_template" type="text/template">
16 <tr id="account-row-[[ .short_name ]]" class="account-row" data-account-name="[[ .short_name ]]" data-global-credential-endpoint="[[ .global_credential_url ]]"> 16 <tr id="account-row-[[ .short_name ]]" class="account-row" data-account-name="[[ .short_name ]]" data-global-credential-endpoint="[[ .global_credential_url ]]">
17 <td>[[ .name ]]</td> 17 <td>[[ .name ]] <span class="vendor-tag vendor-[[ .vendor ]]" alt="[[ .vendor ]]" title="[[ .vendor ]]">[[ .vendor ]]</span></td>
18 <td>[[ .vendor ]]</td>
19 <td> 18 <td>
20 <a href="[[ .console_redirect_url ]]">Console</a> | 19 <a href="[[ .console_redirect_url ]]">Console</a> |
21 <a data-content-type="application/vnd.broker.v2.credential.aws.ini" href="#/cli/[[ .short_name ]]">AWS CLI</a> | 20 <a data-content-type="application/vnd.broker.v2.credential.aws.ini" href="#/cli/[[ .short_name ]]">AWS CLI</a> |
@@ -27,29 +26,31 @@
27 </script> 26 </script>
28 <script type="text/javascript" src="/assets/site.js"></script> 27 <script type="text/javascript" src="/assets/site.js"></script>
29 <script type="text/javascript"> 28 <script type="text/javascript">
30 window.addEventListener('load', populateAPIKey); 29 window.addEventListener('load', setupHomePage);
31 window.addEventListener('load', populateAccountTable);
32 window.addEventListener('load', setAdminClass);
33 </script> 30 </script>
34 </head> 31 </head>
35 <body> 32 <body>
36 <p id="api-error">Error communicating with the API.</p> 33 <p id="api-error">Error communicating with the API.</p>
37 34
35 <div id="login-row">
36 Hello <span id="username"></span>! (<a href="/api">API</a> | <a href="#" id="show-api-key">API Key</a> | <a href="/logout">Logout</a>)
37 </div>
38
38 <h1>Cloud Accounts</h1> 39 <h1>Cloud Accounts</h1>
39 <table id="account-table"> 40 <table id="account-table">
40 <tr> 41 <tr>
41 <th>Console Login</th> 42 <th>Console Login</th>
42 <th>Vendor</th>
43 <th>Credentials</th> 43 <th>Credentials</th>
44 </tr> 44 </tr>
45 </table> 45 </table>
46 <p><button class="admin">Add Account</button></p>
47 46
47 <div id="api-key-block">
48 <h1>API Key</h1> 48 <h1>API Key</h1>
49 <div id="api-key"> 49 <div id="api-key">
50 <p>To access <a href="/api/account">the API</a> set the header <tt>Authorization: Bearer {token}</tt> to the token below:</p> 50 <p>To access <a href="/api/account">the API</a> set the header <tt>Authorization: Bearer {token}</tt> to the token below:</p>
51 <textarea>Bearer {token}</textarea> 51 <textarea>Bearer {token}</textarea>
52 <p><b>Token Expires:</b> <span id="session-expires"></span></p> 52 <p><b>Token Expires:</b> <span id="session-expires"></span></p>
53 </div> 53 </div>
54 </div>
54 </body> 55 </body>
55</html> 56</html>