Improve profile page

This commit is contained in:
Yarmo Mackenbach 2020-06-27 00:50:21 +02:00
parent d763ea1f27
commit 6847d2a285
3 changed files with 141 additions and 51 deletions

View file

@ -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 &#10004;</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;
}
});

View file

@ -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;
}
}

View file

@ -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>