diff --git a/assets/elements.css b/assets/elements.css index 89b9f12..03c863d 100644 --- a/assets/elements.css +++ b/assets/elements.css @@ -77,7 +77,7 @@ a { text-decoration: underline solid currentColor 1px; } -code { +code, kbd { display: inline-block; max-width: 100%; box-sizing: border-box; @@ -109,7 +109,7 @@ select { outline: 1ch solid var(--color-text); } -input[type=text], input[type=url], textarea, select { +input[type=text], input[type=url], input[type=password], textarea, select { padding-inline: 1ch; border-inline: 1ch solid var(--color-accent); background-color: var(--color-bg-scrim); diff --git a/assets/fonts/Lexend/Lexend.ttf b/assets/fonts/Lexend/Lexend.ttf new file mode 100644 index 0000000..e895baf Binary files /dev/null and b/assets/fonts/Lexend/Lexend.ttf differ diff --git a/assets/print.css b/assets/print.css new file mode 100644 index 0000000..b326180 --- /dev/null +++ b/assets/print.css @@ -0,0 +1,15 @@ +footer, +.matkap_ascii, +.noprint { + display: none !important; +} + +@font-face { + font-family: "Lexend"; + font-weight: regular; + src: url("./Lexend/Lexend.ttf"); +} + +html { + font-family: "Lexend"; +} \ No newline at end of file diff --git a/index.js b/index.js index 39bbcbd..bc5fa63 100644 --- a/index.js +++ b/index.js @@ -8,6 +8,7 @@ import { JSDOM } from "jsdom"; import Parser from "rss-parser"; import nacl from "tweetnacl"; import expressBasicAuth from "express-basic-auth"; +import crypto from "node:crypto"; import { getRelativeTime } from "./modules/relativeTime.js"; import { fromHex } from "./modules/fromHex.js"; @@ -487,6 +488,98 @@ app.get('/updates', async (req, res) => { }); }); +const enc_key = Buffer.from(process.env.RESUME_ENCRYPTION_KEY, "hex"); + +app.get('/resumeEnc', async (req, res) => { + const iv = crypto.randomBytes(16); + const cipher = crypto.createCipheriv( + "aes-256-cbc", enc_key, iv + ); + + let encrypted = cipher.update(req.query.text, 'utf8', 'hex'); + encrypted += cipher.final('hex'); + + res.send(encrypted + "\n" + iv.toString('hex')); +}); + +function decipher(file, key) { + let hexKey; + try { + hexKey = Buffer.from(key, "hex"); + } catch (err) { + throw err; + } + + const [enc, iv] = file.split("\n"); + + let decipher; + try { + decipher = crypto.createDecipheriv( + "aes-256-cbc", hexKey, Buffer.from(iv, "hex") + ); + } catch (err) { + throw err; + } + + let decrypted = decipher.update(enc, 'hex', 'utf8'); + decrypted += decipher.final('utf8'); + + let decryptedJSON; + try { + decryptedJSON = JSON.parse(decrypted); + } catch (err) { + throw err; + } + return decryptedJSON; +} + +app.get('/resume', async (req, res) => { + if (req.query.key == null || req.query.key.length < 1) return res.render('resumeEntry', { badError: false }); + const encryptedPD = await fetch(process.env.RESUME_DATA) + .catch(() => res.status(500).send()) + .then((res) => res.text()); + const encryptedJobs = await fetch(process.env.RESUME_JOBS) + .catch(() => res.status(500).send()) + .then((res) => res.text()); + const encryptedEducation = await fetch(process.env.RESUME_EDU) + .catch(() => res.status(500).send()) + .then((res) => res.text()); + const unencryptedOrgs = await fetch(process.env.RESUME_ORGS) + .catch(() => res.status(500).send()) + .then((res) => res.json()); + + let unencryptedPD; + try { + unencryptedPD = decipher(encryptedPD, req.query.key); + } catch (err) { + console.error(err); + return res.render('resumeEntry', { badError: true }); + } + let unencryptedJobs; + try { + unencryptedJobs = decipher(encryptedJobs, req.query.key); + } catch (err) { + console.error(err); + return res.render('resumeEntry', { badError: true }); + } + let unencryptedEducation; + try { + unencryptedEducation = decipher(encryptedEducation, req.query.key); + } catch (err) { + console.error(err); + return res.render('resumeEntry', { badError: true }); + } + + console.log(unencryptedOrgs) + + res.render('resume', { + pd: unencryptedPD, + jobs: unencryptedJobs, + education: unencryptedEducation, + orgs: unencryptedOrgs + }); +}); + app.get('/sites', async (req, res) => { const buttonsJson = await fetch("https://cdn.abtmtr.link/site_content/buttons.json") .catch(() => res.status(500).send()) diff --git a/sitemap.json b/sitemap.json index 517af61..102c564 100644 --- a/sitemap.json +++ b/sitemap.json @@ -23,6 +23,10 @@ "link": "sites", "description": "a collection of other sites in the form of 88x31s." }, + { + "link": "resume", + "description": "my job history, in general." + }, { "link": "about", "description": "who runs abtmtr.link?" diff --git a/views/components/page-head.ejs b/views/components/page-head.ejs index 7591766..057768b 100644 --- a/views/components/page-head.ejs +++ b/views/components/page-head.ejs @@ -4,7 +4,9 @@ abtmtr.link - + + + diff --git a/views/pages/resume.ejs b/views/pages/resume.ejs new file mode 100644 index 0000000..a69f49e --- /dev/null +++ b/views/pages/resume.ejs @@ -0,0 +1,159 @@ + + + <%- include("../components/page-head.ejs") %> + + +
+

<%= pd.name[0] %> <%= pd.name[1][0] %>. <%= pd.name[2] %>

+

+ + <%= pd.phone.region %> (<%= pd.phone.area %>) <%= pd.phone.local %> + / + + <%= pd.email %> + +

+

+ <%= pd.address.street_address %>
+ <%= pd.address.city %>, + <%= pd.address.state %> + <%= pd.address.postal %> +

+

+ + Hint: Use CTRL P to print this page and get a more readable layout. + +

+

Organizations / Volunteering

+ +

Education

+ +

Experience

+ +
+ <%- include("../components/footer.ejs") %> + <%- include("../components/post-main.ejs") %> + + \ No newline at end of file diff --git a/views/pages/resumeEntry.ejs b/views/pages/resumeEntry.ejs new file mode 100644 index 0000000..402d8ce --- /dev/null +++ b/views/pages/resumeEntry.ejs @@ -0,0 +1,27 @@ + + + <%- include("../components/page-head.ejs") %> + +
+

resume

+

my job history, in general.

+

enter a key

+

you are attempting to access my resume.
+ this information is key-protected and will remain that way for some amount of time.

+
+

+ + +

+

+ +

+ <% if (badError) { %> +

ERROR: incorrect key.

+ <% } %> +
+
+ <%- include("../components/footer.ejs") %> + <%- include("../components/post-main.ejs") %> + + \ No newline at end of file