mirror of
https://codeberg.org/keyoxide/keyoxide-web.git
synced 2024-12-22 23:09:29 -07:00
Improve profile page
This commit is contained in:
parent
d763ea1f27
commit
6847d2a285
3 changed files with 141 additions and 51 deletions
|
@ -172,8 +172,7 @@ async function displayProfile(opts) {
|
|||
let userData = keyData.user.user.userId;
|
||||
let feedback = "", notation, isVerified, verifications = [];
|
||||
|
||||
document.body.querySelector('#profile--name').innerHTML = userData.name;
|
||||
document.body.querySelector('#profile--email').innerHTML = userData.email;
|
||||
document.body.querySelector('#profileName').innerHTML = userData.name;
|
||||
|
||||
for (var i = 0; i < keyData.notations.length; i++) {
|
||||
notation = keyData.notations[i];
|
||||
|
@ -182,27 +181,55 @@ async function displayProfile(opts) {
|
|||
}
|
||||
|
||||
// Generate feedback
|
||||
feedback += `<div class="profileDataItem profileDataItem--separator">`;
|
||||
feedback += `<div class="profileDataItem__label"></div>`;
|
||||
feedback += `<div class="profileDataItem__value">general information</div>`;
|
||||
feedback += `</div>`;
|
||||
feedback += `<div class="profileDataItem">`;
|
||||
feedback += `<div class="profileDataItem__label">email</div>`;
|
||||
feedback += `<div class="profileDataItem__value"><a href="mailto:${userData.email}">${userData.email}</a></div>`;
|
||||
feedback += `</div>`;
|
||||
feedback += `<div class="profileDataItem">`;
|
||||
feedback += `<div class="profileDataItem__label">fingerprint</div>`;
|
||||
feedback += `<div class="profileDataItem__value"><a href="https://keys.openpgp.org/pks/lookup?op=get&options=mr&search=0x${keyData.fingerprint}">${keyData.fingerprint}</a></div>`;
|
||||
feedback += `</div>`;
|
||||
|
||||
feedback += `<div class="profileDataItem profileDataItem--separator">`;
|
||||
feedback += `<div class="profileDataItem__label"></div>`;
|
||||
feedback += `<div class="profileDataItem__value">proofs</div>`;
|
||||
feedback += `</div>`;
|
||||
for (var i = 0; i < verifications.length; i++) {
|
||||
feedback += `${verifications[i].type}: <a href="${verifications[i].url}">${verifications[i].display}</a>: ${verifications[i].isVerified}<br>`;
|
||||
// feedback += `${verifications[i].type}: <a href="${verifications[i].url}">${verifications[i].display}</a>: ${verifications[i].isVerified}<br>`;
|
||||
feedback += `<div class="profileDataItem">`;
|
||||
feedback += `<div class="profileDataItem__label">${verifications[i].type}</div>`;
|
||||
feedback += `<div class="profileDataItem__value">`;
|
||||
feedback += `<a class="proofDisplay" href="${verifications[i].url}">${verifications[i].display}</a>`;
|
||||
if (verifications[i].isVerified) {
|
||||
feedback += `<a class="proofUrl proofUrl--verified" href="${verifications[i].proofUrl}">verified ✔</a>`;
|
||||
} else {
|
||||
feedback += `<a class="proofUrl" href="${verifications[i].proofUrl}">proof</a>`;
|
||||
}
|
||||
feedback += `</div>`;
|
||||
feedback += `</div>`;
|
||||
}
|
||||
|
||||
// Display feedback
|
||||
document.body.querySelector('#profile--proofs').innerHTML = feedback;
|
||||
document.body.querySelector('#profileData').innerHTML = feedback;
|
||||
}
|
||||
|
||||
async function verifyProof(url, fingerprint) {
|
||||
// Init
|
||||
let reVerify, urlFetch, output = {url: url, type: null, isVerified: false, display: null};
|
||||
let reVerify, output = {url: url, type: null, proofUrl: url, proofUrlFetch: null, isVerified: false, display: null};
|
||||
|
||||
// DNS
|
||||
if (/^dns:/.test(url)) {
|
||||
output.type = "dns";
|
||||
let domain = url.replace(/dns:/, '').replace(/\?type=TXT/, '');
|
||||
urlFetch = `https://dns.google.com/resolve?name=${domain}&type=TXT`;
|
||||
output.display = domain;
|
||||
output.type = "website";
|
||||
output.display = url.replace(/dns:/, '').replace(/\?type=TXT/, '');
|
||||
output.proofUrlFetch = `https://dns.google.com/resolve?name=${output.display}&type=TXT`;
|
||||
output.url = `https://${output.display}`;
|
||||
|
||||
try {
|
||||
response = await fetch(urlFetch, {
|
||||
response = await fetch(output.proofUrlFetch, {
|
||||
headers: {
|
||||
Accept: 'application/json'
|
||||
},
|
||||
|
@ -226,8 +253,10 @@ async function verifyProof(url, fingerprint) {
|
|||
// HN
|
||||
if (/^https:\/\/news.ycombinator.com/.test(url)) {
|
||||
output.type = "hn";
|
||||
output.display = url.replace(/https:\/\/news.ycombinator.com\/user\?id=/, "");
|
||||
output.proofUrlFetch = `https://hacker-news.firebaseio.com/v0/user/${output.display}.json`;
|
||||
try {
|
||||
response = await fetch(urlFetch, {
|
||||
response = await fetch(output.proofUrlFetch, {
|
||||
headers: {
|
||||
Accept: 'application/json'
|
||||
},
|
||||
|
@ -238,11 +267,9 @@ async function verifyProof(url, fingerprint) {
|
|||
}
|
||||
json = await response.json();
|
||||
reVerify = new RegExp(`openpgp4fpr:${fingerprint}`);
|
||||
json.Answer.forEach((item, i) => {
|
||||
if (reVerify.test(item.data)) {
|
||||
output.isVerified = true;
|
||||
}
|
||||
});
|
||||
if (reVerify.test(json.about)) {
|
||||
output.isVerified = true;
|
||||
}
|
||||
} catch (e) {
|
||||
} finally {
|
||||
return output;
|
||||
|
@ -251,8 +278,11 @@ async function verifyProof(url, fingerprint) {
|
|||
// Reddit
|
||||
if (/^https:\/\/www.reddit.com\/user/.test(url)) {
|
||||
output.type = "reddit";
|
||||
output.display = url.replace(/^https:\/\/www.reddit.com\/user\//, "").replace(/\/comments\/.*/, "");
|
||||
output.url = `https://www.reddit.com/user/${output.display}`;
|
||||
output.proofUrlFetch = url.replace(/\/[a-zA-Z0-9_]*\/$/, ".json");
|
||||
try {
|
||||
response = await fetch(urlFetch, {
|
||||
response = await fetch(output.proofUrlFetch, {
|
||||
headers: {
|
||||
Accept: 'application/json'
|
||||
},
|
||||
|
@ -262,7 +292,8 @@ async function verifyProof(url, fingerprint) {
|
|||
throw new Error('Response failed: ' + response.status);
|
||||
}
|
||||
json = await response.json();
|
||||
reVerify = new RegExp(`openpgp4fpr:${fingerprint}`);
|
||||
console.log(json);
|
||||
reVerify = new RegExp(`Verifying my OpenPGP key: openpgp4fpr:${fingerprint}`);
|
||||
json.Answer.forEach((item, i) => {
|
||||
if (reVerify.test(item.data)) {
|
||||
output.isVerified = true;
|
||||
|
@ -276,8 +307,12 @@ async function verifyProof(url, fingerprint) {
|
|||
// Github
|
||||
if (/^https:\/\/gist.github.com/.test(url)) {
|
||||
output.type = "github";
|
||||
output.display = url.replace(/^https:\/\/gist.github.com\//, "").replace(/\/[a-zA-Z0-9]*$/, "");
|
||||
output.url = `https://github.com/${output.display}`;
|
||||
let gistId = url.replace(/^https:\/\/gist.github.com\/[a-zA-Z0-9_-]*\//, "");
|
||||
output.proofUrlFetch = `https://api.github.com/gists/${gistId}`;
|
||||
try {
|
||||
response = await fetch(urlFetch, {
|
||||
response = await fetch(output.proofUrlFetch, {
|
||||
headers: {
|
||||
Accept: 'application/json'
|
||||
},
|
||||
|
@ -287,12 +322,10 @@ async function verifyProof(url, fingerprint) {
|
|||
throw new Error('Response failed: ' + response.status);
|
||||
}
|
||||
json = await response.json();
|
||||
reVerify = new RegExp(`openpgp4fpr:${fingerprint}`);
|
||||
json.Answer.forEach((item, i) => {
|
||||
if (reVerify.test(item.data)) {
|
||||
output.isVerified = true;
|
||||
}
|
||||
});
|
||||
reVerify = new RegExp(`[Verifying my OpenPGP key: openpgp4fpr:${fingerprint}]`);
|
||||
if (reVerify.test(json.files["openpgp.md"].content)) {
|
||||
output.isVerified = true;
|
||||
}
|
||||
} catch (e) {
|
||||
} finally {
|
||||
return output;
|
||||
|
@ -316,6 +349,7 @@ async function verifyProof(url, fingerprint) {
|
|||
if (item.value === fingerprint) {
|
||||
output.type = "mastodon";
|
||||
output.display = json.url;
|
||||
output.proofUrlFetch = json.url;
|
||||
output.isVerified = true;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -20,7 +20,7 @@ nav a {
|
|||
footer {
|
||||
color: #777;
|
||||
margin: 64px 0;
|
||||
padding: 32px;
|
||||
padding: 0 32px;
|
||||
}
|
||||
.container {
|
||||
max-width: 720px;
|
||||
|
@ -91,3 +91,78 @@ input[type="submit"] {
|
|||
display: inline-block;
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
|
||||
.container--profile {
|
||||
margin-top: 64px;
|
||||
}
|
||||
.container--profile .content {
|
||||
padding-top: 32px;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
.container--profile footer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.profileDataItem {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.profileDataItem--separator {
|
||||
margin-top: 1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.profileDataItem__label {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
flex: 1;
|
||||
min-height: 32px;
|
||||
padding: 0 8px;
|
||||
max-width: 20%;
|
||||
color: #777;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.profileDataItem__value {
|
||||
display: inline-block;
|
||||
flex: 1;
|
||||
min-height: 32px;
|
||||
max-width: 100%;
|
||||
padding: 0 8px;
|
||||
}
|
||||
.profileDataItem__value a {
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.profileDataItem__value a.proofDisplay {
|
||||
margin-right: 16px;
|
||||
}
|
||||
.profileDataItem__value a.proofUrl {
|
||||
color: #777;
|
||||
/* text-decoration: none; */
|
||||
}
|
||||
.profileDataItem__value a.proofUrl.proofUrl--verified {
|
||||
color: #499539;
|
||||
}
|
||||
.profileDataItem__value a.proofUrl:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
@media (max-width: 680px) {
|
||||
.profileDataItem {
|
||||
flex-direction: column;
|
||||
}
|
||||
.profileDataItem__label {
|
||||
max-width: 100%;
|
||||
min-height: 28px;
|
||||
text-align: left;
|
||||
}
|
||||
.profileDataItem__value {
|
||||
min-height: 28px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,41 +3,22 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Encrypt - Keyoxide</title>
|
||||
<title>Keyoxide</title>
|
||||
<script async defer data-domain="keyoxide.org" src="https://plausible.io/js/plausible.js"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/normalize.css@8.0.1/normalize.css">
|
||||
<link rel="stylesheet" href="/assets/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="container">
|
||||
<a href="/">Keyoxide</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
<h1>Profile</h1>
|
||||
<div class="container container--profile">
|
||||
<h1 id="profileName"></h1>
|
||||
<div class="content">
|
||||
<h3></h3>
|
||||
<p>Input: <span id="profileUid">%UID%</span></p>
|
||||
<p>Name: <span id="profile--name"></span></p>
|
||||
<p>Email address: <span id="profile--email">/span></p>
|
||||
<p>Proofs: <span id="profile--proofs">/span></p>
|
||||
<span id="profileUid" style="display: none;">%UID%</span>
|
||||
<div id="profileData"></div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<p>
|
||||
<a href="/">Keyoxide</a> makes basic cryptography operations accessible to regular humans.
|
||||
<br>
|
||||
Made by <a href="https://yarmo.eu">Yarmo Mackenbach</a>.
|
||||
<br>
|
||||
Code hosted on <a href="https://codeberg.org/yarmo/keyoxide">Codeberg</a> (<a href="https://drone.private.foss.best/yarmo/keyoxide/">drone CI/CD</a>).
|
||||
<br>
|
||||
Uses <a href="https://github.com/openpgpjs/openpgpjs">openpgp.js</a> (version <a href="https://github.com/openpgpjs/openpgpjs/releases/tag/v4.10.4">4.10.4</a>).
|
||||
<br>
|
||||
Privacy-friendly public usage stats by <a href="https://plausible.io/keyoxide.org">Plausible.io</a>.
|
||||
<br>
|
||||
Because SO2 + 2NaOH → Na2SO3 + H2O
|
||||
Page generated by <a href="/">Keyoxide</a>.
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue