diff --git a/.env b/.env
new file mode 100644
index 0000000..1effdc1
--- /dev/null
+++ b/.env
@@ -0,0 +1,2 @@
+export DATABASE_SECRET_PATH=/home/Rory/.config/SafeNSound/mongodb
+export JWT_SECRET_PATH=/home/Rory/.config/SafeNSound
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 35eb1dd..f9c95a4 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,5 +2,6 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
+ <mapping directory="$PROJECT_DIR$/testFrontend/SafeNSound" vcs="Git" />
</component>
</project>
\ No newline at end of file
diff --git a/README.md b/README.md
index 6386c3a..a3069c3 100644
--- a/README.md
+++ b/README.md
@@ -13,3 +13,4 @@ Environment variables:
| `PORT` | `3000` | The port the server will run on. |
| `LOG_REQUESTS` | `-` | Requests to log to the console by status, `-` to invert. |
| `DATABASE_SECRET_PATH` | `` | The path to the mongodb connection string. |
+| `JWT_SECRET_PATH` | `` | The path to the JWT secret certificate. |
\ No newline at end of file
diff --git a/src/api/routes/auth/registerRoute.js b/src/api/routes/auth/registerRoute.js
index 8ad4f07..f2befd8 100644
--- a/src/api/routes/auth/registerRoute.js
+++ b/src/api/routes/auth/registerRoute.js
@@ -1,4 +1,4 @@
-import { User } from '#db/index.js';
+import { DbUser } from '#db/index.js';
export const registerRoute = {
route: '/auth/register',
diff --git a/src/api/routes/statusRoute.js b/src/api/routes/statusRoute.js
index 41208a4..5c3231b 100644
--- a/src/api/routes/statusRoute.js
+++ b/src/api/routes/statusRoute.js
@@ -1,4 +1,4 @@
-import { User } from '#db/schemas/user.js';
+import { DbUser } from '#db/index.js';
export const statusRoute = {
route: '/status',
diff --git a/src/api/start.js b/src/api/start.js
index 6aa4567..6f57afd 100644
--- a/src/api/start.js
+++ b/src/api/start.js
@@ -2,12 +2,14 @@ import express from 'express';
import { registerRoutes } from './routes.js';
import { useCors, useLogging } from './middlewares/index.js';
import { initDb } from '#db/index.js';
+import {initJwt} from "#util/index.js";
const app = express();
const PORT = process.env.PORT ?? 3000;
const logRequests = process.env['LOG_REQUESTS'] ?? '-';
await initDb();
+await initJwt();
// Configure Express
app.use(express.json());
diff --git a/src/db/db.js b/src/db/db.js
index 9a7b50e..b9a425c 100644
--- a/src/db/db.js
+++ b/src/db/db.js
@@ -3,6 +3,7 @@ import { readSecret } from '#util/secretUtils.js';
export async function initDb() {
const connectionString = await readSecret(
+ "MongoDB connection string",
process.env['DATABASE_SECRET_PATH']
);
try {
diff --git a/src/db/schemas/user.js b/src/db/schemas/user.js
index 22856b2..1a7e048 100644
--- a/src/db/schemas/user.js
+++ b/src/db/schemas/user.js
@@ -23,7 +23,7 @@ export const userSchema = new Schema({
},
type: {
type: String,
- enum: ['user', 'admin'],
+ enum: ['user', 'monitor', 'admin'],
default: 'user'
},
createdAt: {
diff --git a/src/util/index.js b/src/util/index.js
index 6b51d7b..e5f345c 100644
--- a/src/util/index.js
+++ b/src/util/index.js
@@ -1 +1,2 @@
export * from './secretUtils.js';
+export * from './jwtUtils.js';
\ No newline at end of file
diff --git a/src/util/jwtUtils.js b/src/util/jwtUtils.js
new file mode 100644
index 0000000..115c9c5
--- /dev/null
+++ b/src/util/jwtUtils.js
@@ -0,0 +1,63 @@
+import {existsSync} from 'fs';
+import {readFile, writeFile} from "node:fs/promises";
+import {generateKeyPairSync, createHash, createPublicKey, createPrivateKey} from 'node:crypto';
+
+let privateKey, publicKey, fingerprint;
+
+export async function initJwt() {
+ const secretPath = process.env.JWT_SECRET_PATH;
+ if (!secretPath || !existsSync(secretPath)) {
+ throw new Error('JWT secret path is not defined in environment variables, or the directory does not exist.');
+ }
+
+ const privateKeyPath = `${secretPath}/jwt.key`;
+ const publicKeyPath = `${secretPath}/jwt.key.pub`;
+
+ if (!existsSync(privateKeyPath)) {
+ console.log("[JWT] Generating new keypair");
+ const keyPair = generateKeyPairSync("ec", {
+ namedCurve: "secp521r1",
+ });
+
+ privateKey = keyPair.privateKey;
+ publicKey = keyPair.publicKey;
+
+ await Promise.all([
+ writeFile(
+ privateKeyPath,
+ privateKey.export({format: "pem", type: "sec1"}),
+ ),
+ writeFile(
+ publicKeyPath,
+ publicKey.export({format: "pem", type: "spki"}),
+ ),
+ ]);
+ console.log("[JWT] Keypair generated successfully.");
+ } else {
+ console.log("[JWT] Using existing keypair");
+ const loadedPrivateKey = await readFile(privateKeyPath, 'utf8');
+ const loadedPublicKey = await readFile(publicKeyPath, 'utf8');
+
+ privateKey = createPrivateKey(loadedPrivateKey);
+ publicKey = createPublicKey(loadedPublicKey);
+ }
+
+ fingerprint = createHash("sha256")
+ .update(publicKey.export({format: "pem", type: "spki"}))
+ .digest("hex");
+}
+
+/**
+ * @type {import('jsonwebtoken').JwtOptions}
+ */
+const jwtOptions = {
+ algorithm: 'ES512',
+}
+
+export async function generateJwtToken(user) {
+
+}
+
+export async function validateJwtToken(token) {
+
+}
\ No newline at end of file
diff --git a/src/util/secretUtils.js b/src/util/secretUtils.js
index bbad8ca..92e1b1c 100644
--- a/src/util/secretUtils.js
+++ b/src/util/secretUtils.js
@@ -1,6 +1,7 @@
import fs from 'node:fs/promises';
-export async function readSecret(path) {
+export async function readSecret(name, path) {
+ console.log(`[SECRET] Reading secret "${name}" from path: ${path}`);
if (!path) {
throw new Error('Path to secret file is required');
}
|