fuck it, we resume

This commit is contained in:
MeowcaTheoRange 2024-10-08 21:35:14 -05:00
parent 6f00e10641
commit bfae46c42f
8 changed files with 303 additions and 3 deletions

View file

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

Binary file not shown.

15
assets/print.css Normal file
View file

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

View file

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

View file

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

View file

@ -4,7 +4,9 @@
<title>abtmtr.link</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="abtmtr-mininq-key" content="cf28339198953cab0c635c03030fa23d63e88db92126fab5d358b7cb1aded015">
<link rel="stylesheet" href="/assets/style.css" />
<link rel="stylesheet" media="screen" href="/assets/style.css" />
<link rel="stylesheet" media="print" href="/assets/print.css" />
<!-- <link rel="stylesheet" href="/assets/print.css" /> -->
<link rel="me" href="https://abtmtr.link/about">
<link rel="me" href="https://abtmtr.link/blurbs/#Hx7CuB4_zIWMAsOZlyyqsUm2upXEEYEl">
<link rel="me" href="https://abtmtr.link/blurbs/#aQArHxCaViG-Qw0aFkBRhQWbRsoxUqsB">

159
views/pages/resume.ejs Normal file
View file

@ -0,0 +1,159 @@
<!DOCTYPE html>
<html>
<%- include("../components/page-head.ejs") %>
<body>
<style>
@media print {
:root {
--color: #FF4000;
}
body {
margin: 1rem;
}
h1, h2 {
opacity: 0.8;
font-weight: normal;
padding-left: 0.5rem;
border-left: 4px solid var(--color);
}
a {
color: black;
text-decoration: none;
}
p.address {
opacity: 0.5;
}
p.pd {
margin-top: -0.5em;
}
p.address,
p.pd {
margin-left: 1rem;
}
}
</style>
<main>
<h1><%= pd.name[0] %> <%= pd.name[1][0] %>. <%= pd.name[2] %></h1>
<p class="pd">
<a href="tel:<%= pd.phone.region %><%= pd.phone.area %>-<%= pd.phone.local %>">
<%= pd.phone.region %> (<%= pd.phone.area %>) <%= pd.phone.local %></a>
/
<a href="mailto:<%= pd.email %>">
<%= pd.email %>
</a>
</p>
<p class="address">
<%= pd.address.street_address %><br />
<%= pd.address.city %>,
<%= pd.address.state %>
<%= pd.address.postal %>
</p>
<p class="noprint">
<span style="opacity: 0.5;">
Hint: Use <kbd>CTRL</kbd> <kbd>P</kbd> to print this page and get a more readable layout.
</span>
</p>
<h2>Organizations / Volunteering</h2>
<ul>
<% orgs.forEach((org) => { %>
<li>
<h3><a href="<%= org.url %>" target="_blank"><%= org.name %></a></h3>
<p>
<% if (org.main && org.main.url) { %>
<a href="<%= org.main.url %>" target="_blank"><%= org.main.title %></a>
<% } else if (org.main) { %>
<%= org.main.title %>
<% } %>
<% if (org.main && org.main.email) { %>
/ <span>
<a href="mailto:<%= org.main.email %>">
<%= org.main.email %>
</a>
</span>
<% } %>
</p>
<ul>
<% org.involvement.forEach((period) => { %>
<li>
<h4><%= period.description %></h4>
<p>
<% if (period.supervisor) { %>
<span style="opacity: 0.5;">Supervised by <%= period.supervisor %></span>
<% } %>
</p>
<p>
<% if (period.date) { %>
<span>Done <%= period.date %></span>
<% } else if (period.start) { %>
<%= period.start %> - <%= period.end || "Present" %>
<% } %>
</p>
</li>
<% }); %>
</ul>
</li>
<% }); %>
</ul>
<h2>Education</h2>
<ul>
<% education.forEach((school) => { %>
<li>
<h3><a href="<%= school.url %>" target="_blank"><%= school.name %></a></h3>
<p>
<span style="opacity: 0.5;" class="address">
<%= school.address.street_address %>,
<%= school.address.city %>,
<%= school.address.state %>
<%= school.address.postal %>
</span>
</p>
<p>
<%= school.start || "???" %> - <%= school.end || "Present" %><br />
<span style="opacity: 0.5;">Learned <%= school.experience.join(", ") %></span>
</p>
</li>
<% }); %>
</ul>
<h2>Experience</h2>
<ul>
<% jobs.forEach((job) => { %>
<li>
<h3><a href="<%= job.url %>" target="_blank"><%= job.name %></a></h3>
<p>
<span style="opacity: 0.5;" class="address">
<%= job.address.street_address %>,
<%= job.address.city %>,
<%= job.address.state %>
<%= job.address.postal %>
</span>
</p>
<ul>
<% job.involvement.forEach((period) => { %>
<li>
<h4><%= period.description %></h4>
<p>
<span style="opacity: 0.5;">Supervised by <%= period.supervisor %></span>
</p>
<p>
<%= period.start || "???" %> - <%= period.end || "Present" %>
</p>
</li>
<% }); %>
</ul>
<p>
<span style="opacity: 0.5;">Learned <%= job.experience.join(", ") %></span>
</p>
</li>
<% }); %>
</ul>
</main>
<%- include("../components/footer.ejs") %>
<%- include("../components/post-main.ejs") %>
</body>
</html>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<%- include("../components/page-head.ejs") %>
<body>
<main>
<h1>resume</h1>
<p>my job history, in general.</p>
<h2>enter a key</h2>
<p>you are attempting to access my resume.<br />
this information is key-protected and will remain that way for some amount of time.</p>
<form action="/resume" method="get">
<p>
<label for="key">Key:</label>
<input type="password" name="key" id="key" />
</p>
<p>
<input type="submit" value="Test Access" />
</p>
<% if (badError) { %>
<p style="opacity: 0.5;">ERROR: incorrect key.</p>
<% } %>
</form>
</main>
<%- include("../components/footer.ejs") %>
<%- include("../components/post-main.ejs") %>
</body>
</html>