diff --git a/api/v0/index.js b/api/v0/index.js
index b7dd71d..54c3de5 100644
--- a/api/v0/index.js
+++ b/api/v0/index.js
@@ -27,12 +27,14 @@ You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see .
*/
-const router = require('express').Router()
-const { check, validationResult } = require('express-validator')
-const Ajv = require("ajv")
+import express from 'express'
+import { check, validationResult } from 'express-validator'
+import Ajv from 'ajv'
+import { generateWKDProfile, generateHKPProfile } from '../../server/index.js'
+import 'dotenv/config.js'
+
+const router = express.Router()
const ajv = new Ajv({coerceTypes: true})
-const kx = require('../../server')
-require('dotenv').config()
const apiProfileSchema = {
type: "object",
@@ -251,16 +253,16 @@ router.get('/profile/fetch',
let data
switch (req.query.protocol) {
case 'wkd':
- data = await kx.generateWKDProfile(req.query.query)
+ data = await generateWKDProfile(req.query.query)
break;
case 'hkp':
- data = await kx.generateHKPProfile(req.query.query)
+ data = await generateHKPProfile(req.query.query)
break;
default:
if (req.query.query.includes('@')) {
- data = await kx.generateWKDProfile(req.query.query)
+ data = await generateWKDProfile(req.query.query)
} else {
- data = await kx.generateHKPProfile(req.query.query)
+ data = await generateHKPProfile(req.query.query)
}
break;
}
@@ -329,4 +331,4 @@ router.get('/profile/verify',
}
)
-module.exports = router
+export default router
diff --git a/index.js b/index.js
index 1e4df78..e515bfd 100644
--- a/index.js
+++ b/index.js
@@ -27,13 +27,19 @@ You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see .
*/
-const express = require('express')
-const fs = require('fs')
-const app = express()
-const { stringReplace } = require('string-replace-middleware')
-require('dotenv').config()
+import express from 'express'
+import { readFileSync } from 'fs'
+import { stringReplace } from 'string-replace-middleware'
+import 'dotenv/config.js'
-const packageData = JSON.parse(fs.readFileSync('package.json'))
+import apiRoute from './routes/api.js'
+import mainRoute from './routes/main.js'
+import profileRoute from './routes/profile.js'
+import staticRoute from './routes/static.js'
+import utilRoute from './routes/util.js'
+
+const app = express()
+const packageData = JSON.parse(readFileSync('package.json'))
app.set('env', process.env.NODE_ENV || "production")
app.set('view engine', 'pug')
@@ -65,12 +71,14 @@ app.use(stringReplace({
app.use('/favicon.svg', express.static('favicon.svg'))
app.use('/robots.txt', express.static('robots.txt'))
-app.use('/', require('./routes/main'))
-app.use('/api', require('./routes/api'))
-app.use('/static', require('./routes/static'))
-app.use('/util', require('./routes/util'))
-app.use('/', require('./routes/profile'))
+app.use('/', mainRoute)
+app.use('/api', apiRoute)
+app.use('/static', staticRoute)
+app.use('/util', utilRoute)
+app.use('/', profileRoute)
app.listen(app.get('port'), () => {
console.log(`Node server listening at http://localhost:${app.get('port')}`)
})
+
+export default app
diff --git a/package.json b/package.json
index 9d0ce1b..53fd2c7 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,7 @@
"version": "3.2.0",
"description": "A modern, secure and privacy-friendly platform to establish your decentralized online identity",
"main": "index.js",
+ "type": "module",
"dependencies": {
"ajv": "^8.6.3",
"bent": "^7.3.12",
diff --git a/routes/api.js b/routes/api.js
index 352da6e..1aa2e42 100644
--- a/routes/api.js
+++ b/routes/api.js
@@ -27,8 +27,11 @@ You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see .
*/
-const router = require('express').Router()
+import express from 'express'
+import apiRouter0 from '../api/v0/index.js'
-router.use('/0', require('../api/v0/index.js'))
+const router = express.Router()
-module.exports = router
+router.use('/0', apiRouter0)
+
+export default router
diff --git a/routes/main.js b/routes/main.js
index 4da9d88..cacf057 100644
--- a/routes/main.js
+++ b/routes/main.js
@@ -27,9 +27,13 @@ You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see .
*/
-const router = require('express').Router()
-const md = require('markdown-it')({typographer: true})
-const fs = require('fs')
+import express from 'express'
+import markdownImport from 'markdown-it'
+import { readFileSync } from 'fs'
+import demoData from '../server/demo.js'
+
+const router = express.Router()
+const md = markdownImport({typographer: true})
router.get('/', (req, res) => {
let highlights = []
@@ -44,13 +48,13 @@ router.get('/', (req, res) => {
}
}
- res.render('index', { highlights: highlights, demoData: require('../server/demo.js').data })
+ res.render('index', { highlights: highlights, demoData: demoData })
})
router.get('/privacy', (req, res) => {
- let rawContent = fs.readFileSync(`./content/privacy-policy.md`, "utf8")
+ let rawContent = readFileSync(`./content/privacy-policy.md`, "utf8")
const content = md.render(rawContent)
res.render(`article`, { title: `Privacy policy`, content: content })
})
-module.exports = router
+export default router
diff --git a/routes/profile.js b/routes/profile.js
index a8e8e72..67cd5d3 100644
--- a/routes/profile.js
+++ b/routes/profile.js
@@ -27,53 +27,56 @@ You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see .
*/
-const router = require('express').Router()
-const bodyParser = require('body-parser').urlencoded({ extended: false })
-const kx = require('../server')
+import express from 'express'
+import bodyParserImport from 'body-parser'
+import { generateSignatureProfile, utils, generateWKDProfile, generateHKPProfile, generateKeybaseProfile } from '../server/index.js'
+
+const router = express.Router()
+const bodyParser = bodyParserImport.urlencoded({ extended: false })
router.get('/sig', (req, res) => {
res.render('profile', { isSignature: true, signature: null })
})
router.post('/sig', bodyParser, async (req, res) => {
- const data = await kx.generateSignatureProfile(req.body.signature)
- const title = kx.utils.generatePageTitle('profile', data)
+ const data = await generateSignatureProfile(req.body.signature)
+ const title = utils.generatePageTitle('profile', data)
res.render('profile', { title: title, data: data, isSignature: true, signature: req.body.signature })
})
router.get('/wkd/:id', async (req, res) => {
- const data = await kx.generateWKDProfile(req.params.id)
- const title = kx.utils.generatePageTitle('profile', data)
+ const data = await generateWKDProfile(req.params.id)
+ const title = utils.generatePageTitle('profile', data)
res.render('profile', { title: title, data: data })
})
router.get('/hkp/:id', async (req, res) => {
- const data = await kx.generateHKPProfile(req.params.id)
- const title = kx.utils.generatePageTitle('profile', data)
+ const data = await generateHKPProfile(req.params.id)
+ const title = utils.generatePageTitle('profile', data)
res.render('profile', { title: title, data: data })
})
router.get('/hkp/:server/:id', async (req, res) => {
- const data = await kx.generateHKPProfile(req.params.id, req.params.server)
- const title = kx.utils.generatePageTitle('profile', data)
+ const data = await generateHKPProfile(req.params.id, req.params.server)
+ const title = utils.generatePageTitle('profile', data)
res.render('profile', { title: title, data: data })
})
router.get('/keybase/:username/:fingerprint', async (req, res) => {
- const data = await kx.generateKeybaseProfile(req.params.username, req.params.fingerprint)
- const title = kx.utils.generatePageTitle('profile', data)
+ const data = await generateKeybaseProfile(req.params.username, req.params.fingerprint)
+ const title = utils.generatePageTitle('profile', data)
res.render('profile', { title: title, data: data })
})
router.get('/:id', async (req, res) => {
let data
if (req.params.id.includes('@')) {
- data = await kx.generateWKDProfile(req.params.id)
+ data = await generateWKDProfile(req.params.id)
} else {
- data = await kx.generateHKPProfile(req.params.id)
+ data = await generateHKPProfile(req.params.id)
}
- const title = kx.utils.generatePageTitle('profile', data)
+ const title = utils.generatePageTitle('profile', data)
res.render('profile', { title: title, data: data })
})
-module.exports = router
+export default router
diff --git a/routes/static.js b/routes/static.js
index 2a7782f..ba3b800 100644
--- a/routes/static.js
+++ b/routes/static.js
@@ -27,9 +27,10 @@ You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see .
*/
-const express = require('express')
-const router = require('express').Router()
+import express from 'express'
+
+const router = express.Router()
router.use('/', express.static('static'))
-module.exports = router
+export default router
diff --git a/routes/util.js b/routes/util.js
index 24b2dd1..fb14437 100644
--- a/routes/util.js
+++ b/routes/util.js
@@ -27,7 +27,9 @@ You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see .
*/
-const router = require('express').Router()
+import express from 'express'
+
+const router = express.Router()
router.get('/profile-url', function(req, res) {
res.render('util/profile-url')
@@ -57,4 +59,4 @@ router.get('/wkd/:input', function(req, res) {
res.render('util/wkd', { input: req.params.input })
})
-module.exports = router
+export default router
diff --git a/server/demo.js b/server/demo.js
index 5b64875..2be5113 100644
--- a/server/demo.js
+++ b/server/demo.js
@@ -27,7 +27,7 @@ You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see .
*/
-exports.data = {
+export default {
"claimVersion": 1,
"uri": "https://fosstodon.org/@keyoxide",
"fingerprint": "9f0048ac0b23301e1f77e994909f6bd6f80f485d",
diff --git a/server/index.js b/server/index.js
index 67c0a11..2a816b5 100644
--- a/server/index.js
+++ b/server/index.js
@@ -27,14 +27,14 @@ You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see .
*/
-const doip = require('doipjs')
-const keys = require('./keys')
-const libravatar = require('libravatar')
+import * as doipjs from 'doipjs'
+import { fetchWKD, fetchHKP, fetchSignature, fetchKeybase } from './keys.js'
+import libravatar from 'libravatar'
const generateWKDProfile = async (id) => {
- return keys.fetchWKD(id)
+ return fetchWKD(id)
.then(async key => {
- let keyData = await doip.keys.process(key.publicKey)
+ let keyData = await doipjs.keys.process(key.publicKey)
keyData.openpgp4fpr = `openpgp4fpr:${keyData.fingerprint.toLowerCase()}`
keyData.key.fetchMethod = 'wkd'
keyData.key.uri = key.fetchURL
@@ -59,9 +59,9 @@ const generateWKDProfile = async (id) => {
}
const generateHKPProfile = async (id, keyserverDomain) => {
- return keys.fetchHKP(id, keyserverDomain)
+ return fetchHKP(id, keyserverDomain)
.then(async key => {
- let keyData = await doip.keys.process(key.publicKey)
+ let keyData = await doipjs.keys.process(key.publicKey)
keyData.openpgp4fpr = `openpgp4fpr:${keyData.fingerprint.toLowerCase()}`
keyData.key.fetchMethod = 'hkp'
keyData.key.uri = key.fetchURL
@@ -86,7 +86,7 @@ const generateHKPProfile = async (id, keyserverDomain) => {
}
const generateSignatureProfile = async (signature) => {
- return keys.fetchSignature(signature)
+ return fetchSignature(signature)
.then(async key => {
let keyData = key.keyData
keyData.openpgp4fpr = `openpgp4fpr:${keyData.fingerprint.toLowerCase()}`
@@ -112,9 +112,9 @@ const generateSignatureProfile = async (signature) => {
}
const generateKeybaseProfile = async (username, fingerprint) => {
- return keys.fetchKeybase(id, keyserverDomain)
+ return fetchKeybase(id, keyserverDomain)
.then(async key => {
- let keyData = await doip.keys.process(key.publicKey)
+ let keyData = await doipjs.keys.process(key.publicKey)
keyData.openpgp4fpr = `openpgp4fpr:${keyData.fingerprint.toLowerCase()}`
keyData.key.fetchMethod = 'hkp'
keyData.key.uri = key.fetchURL
@@ -142,7 +142,7 @@ const processKeyData = (keyData) => {
keyData.users.forEach(user => {
// Remove faulty claims
user.claims = user.claims.filter(claim => {
- return claim instanceof doip.Claim
+ return claim instanceof doipjs.Claim
})
// Match claims
@@ -178,9 +178,9 @@ const computeExtraData = async (key, keyData) => {
}
}
-exports.generateWKDProfile = generateWKDProfile
-exports.generateHKPProfile = generateHKPProfile
-exports.generateKeybaseProfile = generateKeybaseProfile
-exports.generateSignatureProfile = generateSignatureProfile
+export { generateWKDProfile }
+export { generateHKPProfile }
+export { generateKeybaseProfile }
+export { generateSignatureProfile }
-exports.utils = require('./utils')
+export * as utils from './utils.js'
diff --git a/server/keys.js b/server/keys.js
index d336179..aa24f67 100644
--- a/server/keys.js
+++ b/server/keys.js
@@ -27,10 +27,10 @@ You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see .
*/
-const got = require('got')
-const doip = require('doipjs')
-const openpgp = require('openpgp')
-const utils = require('./utils')
+import got from 'got'
+import * as doipjs from 'doipjs'
+import { readKey, readCleartextMessage, verify } from 'openpgp'
+import { computeWKDLocalPart } from './utils.js'
const fetchWKD = (id) => {
return new Promise(async (resolve, reject) => {
@@ -47,7 +47,7 @@ const fetchWKD = (id) => {
if (!localPart || !domain) {
reject(new Error(`The WKD identifier "${id}" is invalid`));
}
- const localEncoded = await utils.computeWKDLocalPart(localPart)
+ const localEncoded = await computeWKDLocalPart(localPart)
const urlAdvanced = `https://openpgpkey.${domain}/.well-known/openpgpkey/${domain}/hu/${localEncoded}`
const urlDirect = `https://${domain}/.well-known/openpgpkey/hu/${localEncoded}`
let plaintext
@@ -81,7 +81,7 @@ const fetchWKD = (id) => {
}
try {
- output.publicKey = await openpgp.readKey({
+ output.publicKey = await readKey({
binaryKey: plaintext
})
} catch(error) {
@@ -113,7 +113,7 @@ const fetchHKP = (id, keyserverDomain) => {
}
try {
- output.publicKey = await doip.keys.fetchHKP(id, keyserverDomain)
+ output.publicKey = await doipjs.keys.fetchHKP(id, keyserverDomain)
output.fetchURL = `https://${keyserverDomain}/pks/lookup?op=get&options=mr&search=${query}`
} catch(error) {
reject(new Error(`No public keys could be fetched using HKP`))
@@ -138,7 +138,7 @@ const fetchSignature = (signature) => {
// Check validity of signature
let signatureData
try {
- signatureData = await openpgp.readCleartextMessage({
+ signatureData = await readCleartextMessage({
cleartextMessage: signature
})
} catch (error) {
@@ -147,7 +147,7 @@ const fetchSignature = (signature) => {
// Process the signature
try {
- output.keyData = await doip.signatures.process(signature)
+ output.keyData = await doipjs.signatures.process(signature)
output.publicKey = output.keyData.key.data
// TODO Find the URL to the key
output.fetchURL = null
@@ -161,7 +161,7 @@ const fetchSignature = (signature) => {
}
// Check validity of signature
- const verified = await openpgp.verify({
+ const verified = await verify({
message: signatureData,
verificationKeys: output.publicKey
})
@@ -182,7 +182,7 @@ const fetchKeybase = (username, fingerprint) => {
}
try {
- output.publicKey = await doip.keys.fetchKeybase(username, fingerprint)
+ output.publicKey = await doipjs.keys.fetchKeybase(username, fingerprint)
output.fetchURL = `https://keybase.io/${username}/pgp_keys.asc?fingerprint=${fingerprint}`
} catch(error) {
reject(new Error(`No public keys could be fetched from Keybase`))
@@ -196,7 +196,11 @@ const fetchKeybase = (username, fingerprint) => {
})
}
-exports.fetchWKD = fetchWKD
-exports.fetchHKP = fetchHKP
-exports.fetchSignature = fetchSignature
-exports.fetchKeybase = fetchKeybase
+const _fetchWKD = fetchWKD
+export { _fetchWKD as fetchWKD }
+const _fetchHKP = fetchHKP
+export { _fetchHKP as fetchHKP }
+const _fetchSignature = fetchSignature
+export { _fetchSignature as fetchSignature }
+const _fetchKeybase = fetchKeybase
+export { _fetchKeybase as fetchKeybase }
diff --git a/server/utils.js b/server/utils.js
index 8848e9c..306b282 100644
--- a/server/utils.js
+++ b/server/utils.js
@@ -27,15 +27,15 @@ You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see .
*/
-const crypto = require('crypto').webcrypto
+import { webcrypto as crypto } from 'crypto'
-exports.computeWKDLocalPart = async (localPart) => {
+export async function computeWKDLocalPart(localPart) {
const localPartEncoded = new TextEncoder().encode(localPart.toLowerCase());
const localPartHashed = new Uint8Array(await crypto.subtle.digest('SHA-1', localPartEncoded));
return encodeZBase32(localPartHashed);
}
-exports.generatePageTitle = (type, data) => {
+export function generatePageTitle(type, data) {
switch (type) {
case 'profile':
try {
diff --git a/static-src/index.js b/static-src/index.js
index 8e8ff4b..10d9bbe 100644
--- a/static-src/index.js
+++ b/static-src/index.js
@@ -28,11 +28,11 @@ if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see .
*/
// Import JS libraries
-import * as kx from'./keyoxide'
-import * as kxKey from'./kx-key'
-import * as kxClaim from'./kx-claim'
-import * as ui from'./ui'
-import * as utils from'./utils'
+import * as kx from './keyoxide.js'
+import * as kxKey from './kx-key.js'
+import * as kxClaim from './kx-claim.js'
+import * as ui from './ui.js'
+import * as utils from './utils.js'
// Import CSS files
import './styles.css'
diff --git a/static-src/kx-claim.js b/static-src/kx-claim.js
index 6549e18..f8f6dc5 100644
--- a/static-src/kx-claim.js
+++ b/static-src/kx-claim.js
@@ -27,7 +27,7 @@ You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see .
*/
-import * as doip from "doipjs"
+import * as doipjs from 'doipjs';
export class Claim extends HTMLElement {
// Specify the attributes to observe
@@ -45,7 +45,7 @@ export class Claim extends HTMLElement {
}
async verify() {
- const claim = new doip.Claim(JSON.parse(this.getAttribute('data-claim')));
+ const claim = new doipjs.Claim(JSON.parse(this.getAttribute('data-claim')));
await claim.verify({
proxy: {
policy: 'adaptive',
@@ -57,7 +57,7 @@ export class Claim extends HTMLElement {
updateContent(value) {
const root = this;
- const claim = new doip.Claim(JSON.parse(value));
+ const claim = new doipjs.Claim(JSON.parse(value));
switch (claim.matches[0].serviceprovider.name) {
case 'dns':
diff --git a/static-src/ui.js b/static-src/ui.js
index 712510d..1fb873c 100644
--- a/static-src/ui.js
+++ b/static-src/ui.js
@@ -30,7 +30,7 @@ more information on this, and how to apply and follow the GNU AGPL, see {
+ return crypto.webcrypto
+ })
+ // import { webcrypto as crypto } from 'crypto'
+}
// Compute local part of Web Key Directory URL
export async function computeWKDLocalPart(localPart) {
const localPartEncoded = new TextEncoder().encode(localPart.toLowerCase());
- const localPartHashed = new Uint8Array(await crypto.subtle.digest('SHA-1', localPartEncoded));
+ const localPartHashed = new Uint8Array(await _crypto.subtle.digest('SHA-1', localPartEncoded));
return encodeZBase32(localPartHashed);
}
diff --git a/webpack.config.js b/webpack.config.js
index 2e92849..3cc166a 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,8 +1,11 @@
-const path = require('path')
-const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
-const MiniCssExtractPlugin = require("mini-css-extract-plugin")
+import { dirname, resolve } from 'path'
+import { fileURLToPath } from 'url'
+import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
+import MiniCssExtractPlugin from "mini-css-extract-plugin"
-module.exports = (env) => {
+const __dirname = dirname(fileURLToPath(import.meta.url));
+
+export default (env) => {
let config
if (env.static) {
config = {
@@ -16,7 +19,7 @@ module.exports = (env) => {
},
output: {
filename: '[name].js',
- path: path.resolve(__dirname, 'static'),
+ path: resolve(__dirname, 'static'),
},
watch: env.mode == "development",
module: {
@@ -30,6 +33,11 @@ module.exports = (env) => {
}
]
},
+ resolve: {
+ fallback: {
+ crypto: false,
+ }
+ },
plugins: [
new MiniCssExtractPlugin(),
],