Skip to content

Commit 4363f93

Browse files
authored
Merge pull request #1432 from rit-construct-makerspace/main
Cert Serving and UI Tweaks
2 parents 83f5c71 + 4c310ac commit 4363f93

4 files changed

Lines changed: 59 additions & 11 deletions

File tree

client/src/pages/makerspace_page/ExpandableHeader.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { isManagerFor } from "../../common/PrivilegeUtils";
55
import EditIcon from "@mui/icons-material/Edit";
66
import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
77
import { FullMakerspace } from "../../queries/makerspaceQueries";
8-
import { useNavigate } from "react-router-dom";
8+
import { useNavigate, useSearchParams } from "react-router-dom";
99
import { useCurrentUser } from "../../common/CurrentUserProvider";
1010
import MakerspaceHours from "../../types/MakerspaceHours";
1111
import MakerspaceHoursSection from "./MakerspaceHours";
@@ -127,10 +127,12 @@ export default function ExpandableHeader({ makerspace, makerspaceTrainings }: Ex
127127
const navigate = useNavigate();
128128
const isMobile = useIsMobile();
129129

130-
const [expanded, setExpanded] = useState<boolean>(user.visitor);
130+
const [searchParams, setSearchParams] = useSearchParams()
131+
const startOpen = searchParams.get("o") == "1"
132+
const [expanded, setExpanded] = useState<boolean>(user.visitor || startOpen);
131133

132134
return (
133-
<Accordion expanded={expanded} sx={{ border: "none" }} elevation={0} onChange={() => setExpanded(!expanded)}>
135+
<Accordion expanded={expanded} sx={{ border: "none" }} elevation={0} onChange={() => {setExpanded(!expanded); setSearchParams({"o":(!expanded) ? "1" : "0"})}}>
134136
<AccordionSummary>
135137
{TitleRow(
136138
navigate,

client/src/pages/makerspace_page/device_pages/DevicesPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export default function DevicesPage() {
3838
const cores: Core[] = makerspaceWithDevicesResult.data?.makerspaceByID.cores ?? [];
3939
const _dispensers: Dispenser[] = makerspaceWithDevicesResult.data?.makerspaceByID.dispensers ?? [];
4040

41-
const filteredCores: Core[] = cores.filter((core) => core.device.name.includes(searchText))
41+
const filteredCores: Core[] = cores.filter((core) => core.device.name.toLowerCase().includes(searchText.toLowerCase()))
4242

4343
return (
4444
<Stack padding={"10px"} spacing={1}>

server/src/graphql/resolvers/maintenanceTicketResolver.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,18 +165,20 @@ const MaintenanceTicketResolver = {
165165
if (args.assignedID) {
166166
const assigned = await UserRepo.getUserByID(args.assignedID);
167167
await AuditLogRepo.createAuditLog(
168-
`{user} assigned ticket #${args.id} to {user}`,
168+
`{user} assigned ticket #${args.id} for {equipment} to {user}`,
169169
"admin",
170170
makerspaceID,
171171
{ id: user.id, label: UserRepo.getUsersFullName(user) },
172+
{ id: equipRow?.id ?? 0, label: equipRow?.name ?? "unknown equipment" },
172173
{ id: assigned.id, label: UserRepo.getUsersFullName(assigned) }
173174
);
174175
} else {
175176
await AuditLogRepo.createAuditLog(
176-
`{user} unassigned ticket #${args.id}`,
177+
`{user} unassigned ticket #${args.id} for {equipment}`,
177178
"admin",
178179
makerspaceID,
179-
{ id: user.id, label: UserRepo.getUsersFullName(user) }
180+
{ id: user.id, label: UserRepo.getUsersFullName(user) },
181+
{ id: equipRow?.id ?? 0, label: equipRow?.name ?? "unknown equipment" }
180182
);
181183
}
182184
}),

server/src/server.ts

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import path from "path";
1616
import * as schedule from "node-schedule";
1717
import { getUserByCardTagID, getUsersFullName } from "./database/repositories/Users/UserRepository.js";
1818
import { createUnassocaitedAuditLog } from "./database/repositories/AuditLogs/AuditLogRepository.js";
19-
import { getReaderCertCA } from "./database/repositories/Readers/ReaderRepository.js";
19+
import { getReaderCertCA, setReaderCertCA } from "./database/repositories/Readers/ReaderRepository.js";
2020
import morgan from "morgan"; //Log provider
2121
import { createRequire } from "module";
2222
import { setDataPointValue } from "./database/repositories/DataPoints/DataPointsRepository.js";
@@ -43,10 +43,10 @@ import fs from "node:fs";
4343
import { ViteDevServer } from "vite";
4444
import { SiteSettings } from "./database/models/site_settings/SiteSettings.js";
4545
import * as ThemeRepo from "./database/repositories/SiteSettings/ThemesRepository.js";
46+
import { createHash } from 'node:crypto';
4647

4748
const require = createRequire(import.meta.url);
4849

49-
const allowed_origins = [process.env.VITE_ORIGIN, "https://studio.apollographql.com", "https://make.rit.edu", "https://shibboleth.main.ad.rit.edu"];
5050
const SECURE_ORIGIN = (process.env.VITE_ORIGIN ?? "");
5151
const __dirname = import.meta.dirname;
5252

@@ -249,12 +249,32 @@ async function startServer() {
249249
});
250250
app.use("/api/files/", express.static(path.join(__dirname, '../../client/shlug-files/')));
251251

252-
app.get("/api/files/certCA", async function (req, res) {
252+
app.get("/api/rootCA", async function (req, res) {
253+
const SNHeader = 'shlug-sn';
254+
if (!req.headers[SNHeader]) {
255+
return res.status(401).send();
256+
}
257+
const SN = req.headers[SNHeader];
258+
if (typeof SN !== "string") {
259+
return res.status(401).send();
260+
}
261+
262+
const device = await getDeviceBySN(SN);
263+
if (device == null) {
264+
return res.status(404).send();
265+
}
266+
253267
const certca = (await getReaderCertCA())?.value;
254268
if (certca == null) {
255269
return res.status(404).send();
256270
}
257-
return res.send(certca);
271+
const textForSha = `${device.SN}:${await device.generateKey()}:${certca}`
272+
const sha = createHash('sha256').update(textForSha).digest('hex')
273+
const result = {
274+
cert: certca,
275+
sha: sha,
276+
}
277+
return res.json(result);
258278
})
259279

260280
app.get('/api/files/ota/:tagname', async function (req, res) {
@@ -542,6 +562,27 @@ async function startServer() {
542562
createUnassocaitedAuditLog(`Trainings: Sent ${numNotified} expiry notices, and purged ${numPurged} expired trainings.`, "server")
543563

544564
}
565+
async function updateRootCert() {
566+
try {
567+
const url = process.env.READER_CERT_URL;
568+
if (url == undefined || url == "") {
569+
console.error("Can not update root cert. No download URL provided");
570+
return
571+
}
572+
const response = await fetch(url);
573+
574+
if (!response.ok) {
575+
console.error(`Could not download new root cert. HTTP error: ${response.status}`)
576+
return;
577+
}
578+
579+
const certString = await response.text();
580+
// normalize \r\n to \n
581+
setReaderCertCA(certString.replace(/\r/g,""));
582+
} catch (error) {
583+
console.error(`Failed to update root cert: ${error}`)
584+
}
585+
}
545586
/**
546587
Cron Format:
547588
* * * * * *
@@ -574,6 +615,9 @@ async function startServer() {
574615
// Advance any time-based maintennace tickets from UPCOMING -> TODO
575616
await advanceTimeTickets();
576617

618+
// Get a new root certificate for readers
619+
await updateRootCert();
620+
577621
// Command all cores to restart for the periodic restart
578622
await scheduledRestartAllCores();
579623
});

0 commit comments

Comments
 (0)