chore: Move API source code to API folder.

This commit is contained in:
greysoh 2024-04-28 14:21:47 -04:00
parent 8015b0af74
commit d3a664fea4
No known key found for this signature in database
GPG key ID: FE0F173B8FC01571
59 changed files with 43 additions and 38 deletions

View file

@ -0,0 +1,53 @@
import type { PrismaClient } from "@prisma/client";
import type { BackendBaseClass } from "../backendimpl/base.js";
import { backendProviders } from "../backendimpl/index.js";
type Backend = {
id: number;
name: string;
description: string | null;
backend: string;
connectionDetails: string;
};
export async function backendInit(backend: Backend, backends: Record<number, BackendBaseClass>, prisma: PrismaClient): Promise<boolean> {
const ourProvider = backendProviders[backend.backend];
if (!ourProvider) {
console.log(" - Error: Invalid backend recieved!");
return false;
}
console.log(" - Initializing backend...");
backends[backend.id] = new ourProvider(backend.connectionDetails);
const ourBackend = backends[backend.id];
if (!await ourBackend.start()) {
console.log(" - Error initializing backend!");
console.log(" - " + ourBackend.logs.join("\n - "));
return false;
}
console.log(" - Initializing clients...");
const clients = await prisma.forwardRule.findMany({
where: {
destProviderID: backend.id,
enabled: true
}
});
for (const client of clients) {
if (client.protocol != "tcp" && client.protocol != "udp") {
console.error(` - Error: Client with ID of '${client.id}' has an invalid protocol! (must be either TCP or UDP)`);
continue;
}
ourBackend.addConnection(client.sourceIP, client.sourcePort, client.destPort, client.protocol);
}
return true;
}

View file

@ -0,0 +1,26 @@
function getRandomInt(min: number, max: number): number {
const minCeiled = Math.ceil(min);
const maxFloored = Math.floor(max);
return Math.floor(Math.random() * (maxFloored - minCeiled) + minCeiled); // The maximum is exclusive and the minimum is inclusive
}
export function generateRandomData(length: number): string {
let newString = "";
for (let i = 0; i < length; i += 2) {
const randomNumber = getRandomInt(0, 255);
if (randomNumber == 0) {
i -= 2;
continue;
}
newString += randomNumber.toString(16);
}
return newString;
}
export function generateToken() {
return generateRandomData(128);
}

View file

@ -0,0 +1,92 @@
import type { PrismaClient } from "@prisma/client";
import type { SessionToken } from "./types.js";
export const permissionListDisabled: Record<string, boolean> = {
"routes.add": false,
"routes.remove": false,
"routes.start": false,
"routes.stop": false,
"routes.edit": false,
"routes.visible": false,
"routes.visibleConn": false,
"backends.add": false,
"backends.remove": false,
"backends.start": false,
"backends.stop": false,
"backends.edit": false,
"backends.visible": false,
"backends.secretVis": false,
"permissions.see": false,
"users.add": false,
"users.remove": false,
"users.lookup": false,
"users.edit": false,
};
// FIXME: This solution fucking sucks.
export let permissionListEnabled: Record<string, boolean> = JSON.parse(JSON.stringify(permissionListDisabled));
for (const index of Object.keys(permissionListEnabled)) {
permissionListEnabled[index] = true;
}
export async function hasPermission(permissionList: string[], uid: number, prisma: PrismaClient): Promise<boolean> {
for (const permission of permissionList) {
const permissionNode = await prisma.permission.findFirst({
where: {
userID: uid,
permission
}
});
if (!permissionNode || !permissionNode.has) return false;
}
return true;
}
export async function getUID(token: string, tokens: Record<number, SessionToken[]>, prisma: PrismaClient): Promise<number> {
let userID = -1;
// Look up in our currently authenticated users
for (const otherTokenKey of Object.keys(tokens)) {
const otherTokenList = tokens[parseInt(otherTokenKey)];
for (const otherTokenIndex in otherTokenList) {
const otherToken = otherTokenList[otherTokenIndex];
if (otherToken.token == token) {
if (otherToken.expiresAt < otherToken.createdAt + (otherToken.createdAt - Date.now())) {
otherTokenList.splice(parseInt(otherTokenIndex), 1);
continue;
} else {
userID = parseInt(otherTokenKey);
}
}
}
}
// Fine, we'll look up for global tokens...
// FIXME: Could this be more efficient? IDs are sequential in SQL I think
if (userID == -1) {
const allUsers = await prisma.user.findMany({
where: {
isRootServiceAccount: true
}
});
for (const user of allUsers) {
if (user.rootToken == token) userID = user.id;
};
}
return userID;
}
export async function hasPermissionByToken(permissionList: string[], token: string, tokens: Record<number, SessionToken[]>, prisma: PrismaClient): Promise<boolean> {
const userID = await getUID(token, tokens, prisma);
return await hasPermission(permissionList, userID, prisma);
}

28
api/src/libs/types.ts Normal file
View file

@ -0,0 +1,28 @@
import type { PrismaClient } from "@prisma/client";
import type { FastifyInstance } from "fastify";
import type { BackendBaseClass } from "../backendimpl/base.js";
export type ServerOptions = {
isSignupEnabled: boolean;
isSignupAsAdminEnabled: boolean;
allowUnsafeGlobalTokens: boolean;
}
// NOTE: Someone should probably use Redis for this, but this is fine...
export type SessionToken = {
createdAt: number,
expiresAt: number, // Should be (createdAt + (30 minutes))
token: string
};
export type RouteOptions = {
fastify: FastifyInstance,
prisma: PrismaClient,
tokens: Record<number, SessionToken[]>,
options: ServerOptions,
backends: Record<number, BackendBaseClass>
};