forked from Mirrors/keyoxide-web
Merge pull request 'configurable-scheme' (#164) from aspensmonster/keyoxide-web:configurable-scheme into dev
Reviewed-on: https://codeberg.org/keyoxide/keyoxide-web/pulls/164
This commit is contained in:
commit
1dc3a08ccc
8 changed files with 172 additions and 24 deletions
|
@ -30,6 +30,7 @@
|
||||||
"chai": "^4.3.6",
|
"chai": "^4.3.6",
|
||||||
"copy-webpack-plugin": "^11.0.0",
|
"copy-webpack-plugin": "^11.0.0",
|
||||||
"css-loader": "^6.6.0",
|
"css-loader": "^6.6.0",
|
||||||
|
"esmock": "^2.5.0",
|
||||||
"license-check-and-add": "^4.0.5",
|
"license-check-and-add": "^4.0.5",
|
||||||
"mini-css-extract-plugin": "^2.5.3",
|
"mini-css-extract-plugin": "^2.5.3",
|
||||||
"mocha": "^10.1.0",
|
"mocha": "^10.1.0",
|
||||||
|
|
|
@ -48,6 +48,7 @@ app.set('env', process.env.NODE_ENV || 'production')
|
||||||
app.engine('pug', pug.__express).set('view engine', 'pug')
|
app.engine('pug', pug.__express).set('view engine', 'pug')
|
||||||
app.set('port', process.env.PORT || 3000)
|
app.set('port', process.env.PORT || 3000)
|
||||||
app.set('domain', process.env.DOMAIN)
|
app.set('domain', process.env.DOMAIN)
|
||||||
|
app.set('scheme', process.env.SCHEME || 'https')
|
||||||
app.set('keyoxide_version', packageData.version)
|
app.set('keyoxide_version', packageData.version)
|
||||||
app.set('onion_url', process.env.ONION_URL)
|
app.set('onion_url', process.env.ONION_URL)
|
||||||
|
|
||||||
|
@ -65,7 +66,8 @@ if (app.get('onion_url')) {
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use(stringReplace({
|
app.use(stringReplace({
|
||||||
PLACEHOLDER__PROXY_HOSTNAME: process.env.PROXY_HOSTNAME || process.env.DOMAIN || 'null'
|
PLACEHOLDER__PROXY_HOSTNAME: process.env.PROXY_HOSTNAME || process.env.DOMAIN || 'null',
|
||||||
|
PLACEHOLDER__PROXY_SCHEME: process.env.PROXY_SCHEME || process.env.SCHEME || 'https'
|
||||||
}, {
|
}, {
|
||||||
contentTypeFilterRegexp: /application\/javascript/
|
contentTypeFilterRegexp: /application\/javascript/
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -38,7 +38,7 @@ const generateAspeProfile = async (id) => {
|
||||||
|
|
||||||
return doipjs.asp.fetchASPE(id)
|
return doipjs.asp.fetchASPE(id)
|
||||||
.then(profile => {
|
.then(profile => {
|
||||||
profile.addVerifier('keyoxide', `https://${process.env.DOMAIN}/${id}`)
|
profile.addVerifier('keyoxide', `${getScheme()}://${process.env.DOMAIN}/${id}`)
|
||||||
profile = processAspProfile(profile)
|
profile = processAspProfile(profile)
|
||||||
return profile
|
return profile
|
||||||
})
|
})
|
||||||
|
@ -58,7 +58,7 @@ const generateWKDProfile = async (id) => {
|
||||||
|
|
||||||
return fetchWKD(id)
|
return fetchWKD(id)
|
||||||
.then(async profile => {
|
.then(async profile => {
|
||||||
profile.addVerifier('keyoxide', `https://${process.env.DOMAIN}/wkd/${id}`)
|
profile.addVerifier('keyoxide', `${getScheme()}://${process.env.DOMAIN}/wkd/${id}`)
|
||||||
profile = processOpenPgpProfile(profile)
|
profile = processOpenPgpProfile(profile)
|
||||||
|
|
||||||
logger.debug('Generating a WKD profile',
|
logger.debug('Generating a WKD profile',
|
||||||
|
@ -84,9 +84,9 @@ const generateHKPProfile = async (id, keyserverDomain) => {
|
||||||
.then(async profile => {
|
.then(async profile => {
|
||||||
let keyoxideUrl
|
let keyoxideUrl
|
||||||
if (!keyserverDomain || keyserverDomain === 'keys.openpgp.org') {
|
if (!keyserverDomain || keyserverDomain === 'keys.openpgp.org') {
|
||||||
keyoxideUrl = `https://${process.env.DOMAIN}/hkp/${id}`
|
keyoxideUrl = `${getScheme()}://${process.env.DOMAIN}/hkp/${id}`
|
||||||
} else {
|
} else {
|
||||||
keyoxideUrl = `https://${process.env.DOMAIN}/hkp/${keyserverDomain}/${id}`
|
keyoxideUrl = `${getScheme()}://${process.env.DOMAIN}/hkp/${keyserverDomain}/${id}`
|
||||||
}
|
}
|
||||||
|
|
||||||
profile.addVerifier('keyoxide', keyoxideUrl)
|
profile.addVerifier('keyoxide', keyoxideUrl)
|
||||||
|
@ -168,7 +168,7 @@ const generateKeybaseProfile = async (username, fingerprint) => {
|
||||||
|
|
||||||
return fetchKeybase(username, fingerprint)
|
return fetchKeybase(username, fingerprint)
|
||||||
.then(async profile => {
|
.then(async profile => {
|
||||||
profile.addVerifier('keyoxide', `https://${process.env.DOMAIN}/keybase/${username}/${fingerprint}`)
|
profile.addVerifier('keyoxide', `${getScheme()}://${process.env.DOMAIN}/keybase/${username}/${fingerprint}`)
|
||||||
profile = processOpenPgpProfile(profile)
|
profile = processOpenPgpProfile(profile)
|
||||||
|
|
||||||
logger.debug('Generating a Keybase profile',
|
logger.debug('Generating a Keybase profile',
|
||||||
|
@ -254,6 +254,14 @@ const processOpenPgpProfile = async (/** @type {import('doipjs').Profile */ prof
|
||||||
return profile
|
return profile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getScheme = () => {
|
||||||
|
return process.env.PROXY_SCHEME
|
||||||
|
? process.env.PROXY_SCHEME
|
||||||
|
: process.env.SCHEME
|
||||||
|
? process.env.SCHEME
|
||||||
|
: 'https'
|
||||||
|
}
|
||||||
|
|
||||||
export { generateAspeProfile }
|
export { generateAspeProfile }
|
||||||
export { generateWKDProfile }
|
export { generateWKDProfile }
|
||||||
export { generateHKPProfile }
|
export { generateHKPProfile }
|
||||||
|
|
|
@ -49,7 +49,8 @@ export class Claim extends HTMLElement {
|
||||||
await claim.verify({
|
await claim.verify({
|
||||||
proxy: {
|
proxy: {
|
||||||
policy: 'adaptive',
|
policy: 'adaptive',
|
||||||
hostname: 'PLACEHOLDER__PROXY_HOSTNAME'
|
hostname: 'PLACEHOLDER__PROXY_HOSTNAME',
|
||||||
|
scheme: 'PLACEHOLDER__PROXY_SCHEME'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.setAttribute('data-claim', JSON.stringify(claim));
|
this.setAttribute('data-claim', JSON.stringify(claim));
|
||||||
|
@ -182,7 +183,7 @@ export class Claim extends HTMLElement {
|
||||||
const subsection_info_text = subsection_info.appendChild(document.createElement('div'));
|
const subsection_info_text = subsection_info.appendChild(document.createElement('div'));
|
||||||
|
|
||||||
const result_proxyUsed = subsection_info_text.appendChild(document.createElement('p'));
|
const result_proxyUsed = subsection_info_text.appendChild(document.createElement('p'));
|
||||||
result_proxyUsed.innerHTML = `A proxy was used to fetch the proof: <a href="https://PLACEHOLDER__PROXY_HOSTNAME" aria-label="Link to proxy server">PLACEHOLDER__PROXY_HOSTNAME</a>`;
|
result_proxyUsed.innerHTML = `A proxy was used to fetch the proof: <a href="PLACEHOLDER__PROXY_SCHEME://PLACEHOLDER__PROXY_HOSTNAME" aria-label="Link to proxy server">PLACEHOLDER__PROXY_HOSTNAME</a>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Display errors
|
// TODO Display errors
|
||||||
|
@ -207,4 +208,4 @@ export class Claim extends HTMLElement {
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,19 +46,20 @@ export async function computeWKDLocalPart(localPart) {
|
||||||
// Generate Keyoxide profile URL
|
// Generate Keyoxide profile URL
|
||||||
export async function generateProfileURL(data) {
|
export async function generateProfileURL(data) {
|
||||||
let hostname = data.hostname || window.location.hostname;
|
let hostname = data.hostname || window.location.hostname;
|
||||||
|
let scheme = data.scheme || window.location.protocol.slice(0,-1);
|
||||||
|
|
||||||
if (data.input == "") {
|
if (data.input == "") {
|
||||||
return "Waiting for input…";
|
return "Waiting for input…";
|
||||||
}
|
}
|
||||||
switch (data.source) {
|
switch (data.source) {
|
||||||
case "wkd":
|
case "wkd":
|
||||||
return `https://${hostname}/${data.input}`;
|
return `${scheme}://${hostname}/${data.input}`;
|
||||||
break;
|
break;
|
||||||
case "hkp":
|
case "hkp":
|
||||||
if (/.*@.*\..*/.test(data.input)) {
|
if (/.*@.*\..*/.test(data.input)) {
|
||||||
return `https://${hostname}/hkp/${data.input}`;
|
return `${scheme}://${hostname}/hkp/${data.input}`;
|
||||||
} else {
|
} else {
|
||||||
return `https://${hostname}/${data.input}`;
|
return `${scheme}://${hostname}/${data.input}`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "keybase":
|
case "keybase":
|
||||||
|
@ -67,7 +68,7 @@ export async function generateProfileURL(data) {
|
||||||
return "Incorrect Keybase public key URL.";
|
return "Incorrect Keybase public key URL.";
|
||||||
}
|
}
|
||||||
const match = data.input.match(re);
|
const match = data.input.match(re);
|
||||||
return `https://${hostname}/keybase/${match[1]}/${match[2]}`;
|
return `${scheme}://${hostname}/keybase/${match[1]}/${match[2]}`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,4 +230,4 @@ export async function verifyBcryptHash(input, hash) {
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,38 +66,78 @@ describe('browser', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
describe('generateProfileURL()', function () {
|
describe('generateProfileURL()', function () {
|
||||||
it('should handle a WKD URL', async function () {
|
it('should handle a https WKD URL', async function () {
|
||||||
const local = await utils.generateProfileURL({
|
const local = await utils.generateProfileURL({
|
||||||
source: 'wkd',
|
source: 'wkd',
|
||||||
input: 'test@doip.rocks',
|
input: 'test@doip.rocks',
|
||||||
hostname: 'keyoxide.instance'
|
hostname: 'keyoxide.instance',
|
||||||
|
scheme: 'https'
|
||||||
})
|
})
|
||||||
local.should.equal('https://keyoxide.instance/test@doip.rocks')
|
local.should.equal('https://keyoxide.instance/test@doip.rocks')
|
||||||
})
|
})
|
||||||
it('should handle a HKP+email URL', async function () {
|
it('should handle a http WKD URL', async function () {
|
||||||
|
const local = await utils.generateProfileURL({
|
||||||
|
source: 'wkd',
|
||||||
|
input: 'test@doip.rocks',
|
||||||
|
hostname: 'keyoxide.instance',
|
||||||
|
scheme: 'http'
|
||||||
|
})
|
||||||
|
local.should.equal('http://keyoxide.instance/test@doip.rocks')
|
||||||
|
})
|
||||||
|
it('should handle a https HKP+email URL', async function () {
|
||||||
const local = await utils.generateProfileURL({
|
const local = await utils.generateProfileURL({
|
||||||
source: 'hkp',
|
source: 'hkp',
|
||||||
input: 'test@doip.rocks',
|
input: 'test@doip.rocks',
|
||||||
hostname: 'keyoxide.instance'
|
hostname: 'keyoxide.instance',
|
||||||
|
scheme: 'https'
|
||||||
})
|
})
|
||||||
local.should.equal('https://keyoxide.instance/hkp/test@doip.rocks')
|
local.should.equal('https://keyoxide.instance/hkp/test@doip.rocks')
|
||||||
})
|
})
|
||||||
it('should handle a HKP+fingerprint URL', async function () {
|
it('should handle a http HKP+email URL', async function () {
|
||||||
|
const local = await utils.generateProfileURL({
|
||||||
|
source: 'hkp',
|
||||||
|
input: 'test@doip.rocks',
|
||||||
|
hostname: 'keyoxide.instance',
|
||||||
|
scheme: 'http'
|
||||||
|
})
|
||||||
|
local.should.equal('http://keyoxide.instance/hkp/test@doip.rocks')
|
||||||
|
})
|
||||||
|
it('should handle a https HKP+fingerprint URL', async function () {
|
||||||
const local = await utils.generateProfileURL({
|
const local = await utils.generateProfileURL({
|
||||||
source: 'hkp',
|
source: 'hkp',
|
||||||
input: '3637202523E7C1309AB79E99EF2DC5827B445F4B',
|
input: '3637202523E7C1309AB79E99EF2DC5827B445F4B',
|
||||||
hostname: 'keyoxide.instance'
|
hostname: 'keyoxide.instance',
|
||||||
|
scheme: 'https'
|
||||||
})
|
})
|
||||||
local.should.equal('https://keyoxide.instance/3637202523E7C1309AB79E99EF2DC5827B445F4B')
|
local.should.equal('https://keyoxide.instance/3637202523E7C1309AB79E99EF2DC5827B445F4B')
|
||||||
})
|
})
|
||||||
it('should handle a keybase URL', async function () {
|
it('should handle a http HKP+fingerprint URL', async function () {
|
||||||
|
const local = await utils.generateProfileURL({
|
||||||
|
source: 'hkp',
|
||||||
|
input: '3637202523E7C1309AB79E99EF2DC5827B445F4B',
|
||||||
|
hostname: 'keyoxide.instance',
|
||||||
|
scheme: 'http'
|
||||||
|
})
|
||||||
|
local.should.equal('http://keyoxide.instance/3637202523E7C1309AB79E99EF2DC5827B445F4B')
|
||||||
|
})
|
||||||
|
it('should handle a https keybase URL', async function () {
|
||||||
const local = await utils.generateProfileURL({
|
const local = await utils.generateProfileURL({
|
||||||
source: 'keybase',
|
source: 'keybase',
|
||||||
input: 'https://keybase.io/doip/pgp_keys.asc?fingerprint=3637202523E7C1309AB79E99EF2DC5827B445F4B',
|
input: 'https://keybase.io/doip/pgp_keys.asc?fingerprint=3637202523E7C1309AB79E99EF2DC5827B445F4B',
|
||||||
hostname: 'keyoxide.instance'
|
hostname: 'keyoxide.instance',
|
||||||
|
scheme: 'https'
|
||||||
})
|
})
|
||||||
local.should.equal('https://keyoxide.instance/keybase/doip/3637202523E7C1309AB79E99EF2DC5827B445F4B')
|
local.should.equal('https://keyoxide.instance/keybase/doip/3637202523E7C1309AB79E99EF2DC5827B445F4B')
|
||||||
})
|
})
|
||||||
|
it('should handle a http keybase URL', async function () {
|
||||||
|
const local = await utils.generateProfileURL({
|
||||||
|
source: 'keybase',
|
||||||
|
input: 'https://keybase.io/doip/pgp_keys.asc?fingerprint=3637202523E7C1309AB79E99EF2DC5827B445F4B',
|
||||||
|
hostname: 'keyoxide.instance',
|
||||||
|
scheme: 'http'
|
||||||
|
})
|
||||||
|
local.should.equal('http://keyoxide.instance/keybase/doip/3637202523E7C1309AB79E99EF2DC5827B445F4B')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
import 'chai/register-should.js'
|
import 'chai/register-should.js'
|
||||||
|
import esmock from 'esmock'
|
||||||
|
import * as doipjs from 'doipjs'
|
||||||
|
|
||||||
import * as utils from '../src/server/utils.js'
|
import * as utils from '../src/server/utils.js'
|
||||||
|
|
||||||
|
const _env = Object.assign({},process.env)
|
||||||
|
|
||||||
describe('server', function () {
|
describe('server', function () {
|
||||||
describe('utils', function () {
|
describe('utils', function () {
|
||||||
describe('computeWKDLocalPart()', function () {
|
describe('computeWKDLocalPart()', function () {
|
||||||
|
@ -26,4 +31,89 @@ describe('server', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
// NOTE: This is necessarily brittle. If these tests fail
|
||||||
|
// in the future, start looking here for what new behaviour
|
||||||
|
// in the implementation is or isn't getting mocked
|
||||||
|
// appropriately.
|
||||||
|
describe('index', function () {
|
||||||
|
|
||||||
|
describe('generateHKPProfile()', function() {
|
||||||
|
|
||||||
|
let index;
|
||||||
|
let fingerprint;
|
||||||
|
/** @type {import('doipjs').Profile */
|
||||||
|
let profile;
|
||||||
|
|
||||||
|
this.beforeEach(async () => {
|
||||||
|
|
||||||
|
// Common arrangement pieces that don't change per test
|
||||||
|
fingerprint = '79895B2E0F87503F1DDE80B649765D7F0DDD9BD5'
|
||||||
|
process.env.DOMAIN = "keyoxide.org"
|
||||||
|
|
||||||
|
const persona = new doipjs.Persona("test", [new doipjs.Claim('dns:domain.tld?type=TXT')])
|
||||||
|
|
||||||
|
profile = new doipjs.Profile(doipjs.enums.ProfileType.OPENPGP, fingerprint, [persona])
|
||||||
|
|
||||||
|
// mock the appropriate pieces of our dependencies so we
|
||||||
|
// can test just the `keyoxide.url` return value.
|
||||||
|
index = await esmock('../src/server/index.js', {
|
||||||
|
'../src/server/openpgpProfiles.js': {
|
||||||
|
fetchHKP: () => {
|
||||||
|
return Promise.resolve(profile)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'libravatar': {
|
||||||
|
get_avatar_url: () => {
|
||||||
|
return "example.org/avatar.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
this.afterEach(() => {
|
||||||
|
process.env = _env
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle implicit scheme for keyoxide URL', async function () {
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
// no setting process.env.SCHEME
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const local = await index.generateHKPProfile(fingerprint)
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
local.verifiers[0].url.should.equal(`https://keyoxide.org/hkp/${fingerprint}`)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle explicit http scheme for keyoxide URL', async function () {
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
process.env.SCHEME = "http"
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const local = await index.generateHKPProfile(fingerprint)
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
local.verifiers[0].url.should.equal(`http://keyoxide.org/hkp/${fingerprint}`)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle explicit https scheme for keyoxide URL', async function () {
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
process.env.SCHEME = "https"
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const local = await index.generateHKPProfile(fingerprint)
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
local.verifiers[0].url.should.equal(`https://keyoxide.org/hkp/${fingerprint}`)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
|
@ -2216,6 +2216,11 @@ eslint@^8.41.0:
|
||||||
strip-json-comments "^3.1.0"
|
strip-json-comments "^3.1.0"
|
||||||
text-table "^0.2.0"
|
text-table "^0.2.0"
|
||||||
|
|
||||||
|
esmock@^2.5.0:
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/esmock/-/esmock-2.5.1.tgz#cef05c9cd23c46edbfb2e0add34466f6c52e37f6"
|
||||||
|
integrity sha512-3pu+ri9kNrRjahR8c+FWXphK3xpKrgBwLHu+A+Xj3vw84fGsScWY3SWTH1v5nSiheYQAdlz5Ny+a319tlle1mA==
|
||||||
|
|
||||||
espree@^9.6.0:
|
espree@^9.6.0:
|
||||||
version "9.6.0"
|
version "9.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.0.tgz#80869754b1c6560f32e3b6929194a3fe07c5b82f"
|
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.0.tgz#80869754b1c6560f32e3b6929194a3fe07c5b82f"
|
||||||
|
|
Loading…
Reference in a new issue