feature: Adds permission system.
This commit is contained in:
parent
be91aafb58
commit
0c279b459f
6 changed files with 122 additions and 8 deletions
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `permissionID` on the `Permission` table. All the data in the column will be lost.
|
||||
- Added the required column `permission` to the `Permission` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- RedefineTables
|
||||
PRAGMA foreign_keys=OFF;
|
||||
CREATE TABLE "new_Permission" (
|
||||
"permission" TEXT NOT NULL,
|
||||
"has" BOOLEAN NOT NULL,
|
||||
"userID" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
CONSTRAINT "Permission_userID_fkey" FOREIGN KEY ("userID") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
INSERT INTO "new_Permission" ("has", "userID") SELECT "has", "userID" FROM "Permission";
|
||||
DROP TABLE "Permission";
|
||||
ALTER TABLE "new_Permission" RENAME TO "Permission";
|
||||
PRAGMA foreign_key_check;
|
||||
PRAGMA foreign_keys=ON;
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- The primary key for the `Permission` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
- Added the required column `id` to the `Permission` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- RedefineTables
|
||||
PRAGMA foreign_keys=OFF;
|
||||
CREATE TABLE "new_Permission" (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"permission" TEXT NOT NULL,
|
||||
"has" BOOLEAN NOT NULL,
|
||||
"userID" INTEGER NOT NULL,
|
||||
CONSTRAINT "Permission_userID_fkey" FOREIGN KEY ("userID") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
INSERT INTO "new_Permission" ("has", "permission", "userID") SELECT "has", "permission", "userID" FROM "Permission";
|
||||
DROP TABLE "Permission";
|
||||
ALTER TABLE "new_Permission" RENAME TO "Permission";
|
||||
PRAGMA foreign_key_check;
|
||||
PRAGMA foreign_keys=ON;
|
|
@ -37,11 +37,13 @@ model ForwardRule {
|
|||
}
|
||||
|
||||
model Permission {
|
||||
permissionID String @unique
|
||||
id Int @id @default(autoincrement())
|
||||
|
||||
permission String
|
||||
has Boolean
|
||||
|
||||
user User @relation(fields: [userID], references: [id])
|
||||
userID Int @id @default(autoincrement())
|
||||
userID Int
|
||||
}
|
||||
|
||||
model User {
|
||||
|
|
|
@ -6,6 +6,14 @@ meta {
|
|||
|
||||
post {
|
||||
url: http://127.0.0.1:3000/api/v1/users/create
|
||||
body: none
|
||||
body: json
|
||||
auth: none
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"name": "Greyson Hofer",
|
||||
"email": "me@greysoh.dev",
|
||||
"password": "password"
|
||||
}
|
||||
}
|
||||
|
|
42
src/libs/permissions.ts
Normal file
42
src/libs/permissions.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
import type { PrismaClient } from "@prisma/client";
|
||||
|
||||
export const permissionListDisabled: Record<string, boolean> = {
|
||||
"routes.add": false,
|
||||
"routes.remove": false,
|
||||
"routes.start": false,
|
||||
"routes.stop": false,
|
||||
"routes.edit": false,
|
||||
"routes.visible": 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
|
||||
};
|
||||
|
||||
// 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(permission: string, uid: number, prisma: PrismaClient): Promise<boolean> {
|
||||
const permissionNode = await prisma.permission.findFirst({
|
||||
where: {
|
||||
userID: uid,
|
||||
permission
|
||||
}
|
||||
});
|
||||
|
||||
if (!permissionNode) return false;
|
||||
return permissionNode.has;
|
||||
}
|
|
@ -1,14 +1,17 @@
|
|||
import type { PrismaClient } from "@prisma/client";
|
||||
import type { FastifyInstance } from "fastify";
|
||||
|
||||
import { hash } from "bcrypt";
|
||||
|
||||
import { ServerOptions, SessionToken } from "../../libs/types.js";
|
||||
import { permissionListEnabled } from "../../libs/permissions.js";
|
||||
import { generateToken } from "../../libs/generateToken.js";
|
||||
|
||||
export function route(fastify: FastifyInstance, prisma: PrismaClient, tokens: Record<number, SessionToken[]>, options: ServerOptions) {
|
||||
// TODO: Permissions
|
||||
|
||||
/**
|
||||
* Creates a new user account to use, only if it is enabled.
|
||||
*/
|
||||
fastify.post("/api/v1/users/create", {
|
||||
schema: {
|
||||
body: {
|
||||
|
@ -16,8 +19,8 @@ export function route(fastify: FastifyInstance, prisma: PrismaClient, tokens: Re
|
|||
required: ["name", "email", "password"],
|
||||
|
||||
properties: {
|
||||
name: { type: "string" },
|
||||
email: { type: "string" },
|
||||
name: { type: "string" },
|
||||
email: { type: "string" },
|
||||
password: { type: "string" }
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +34,7 @@ export function route(fastify: FastifyInstance, prisma: PrismaClient, tokens: Re
|
|||
} = req.body;
|
||||
|
||||
if (!options.isSignupEnabled) {
|
||||
return res.status(400).send({
|
||||
return res.status(403).send({
|
||||
error: "Signing up is not enabled at this time."
|
||||
});
|
||||
};
|
||||
|
@ -50,13 +53,31 @@ export function route(fastify: FastifyInstance, prisma: PrismaClient, tokens: Re
|
|||
|
||||
const saltedPassword: string = await hash(body.password, 15);
|
||||
|
||||
let userData = {
|
||||
const userData = {
|
||||
name: body.name,
|
||||
email: body.email,
|
||||
password: saltedPassword,
|
||||
|
||||
permissions: {
|
||||
create: [] as {
|
||||
permission: string,
|
||||
has: boolean
|
||||
}[]
|
||||
},
|
||||
|
||||
rootToken: null
|
||||
};
|
||||
|
||||
// TODO: There's probably a faster way to pull this off, but I'm lazy
|
||||
for (const permissionKey of Object.keys(permissionListEnabled)) {
|
||||
if (options.isSignupAsAdminEnabled || (permissionKey.startsWith("routes") || permissionKey == "permissions.see")) {
|
||||
userData.permissions.create.push({
|
||||
permission: permissionKey,
|
||||
has: permissionListEnabled[permissionKey]
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (options.allowUnsafeGlobalTokens) {
|
||||
userData.rootToken = generateToken() as unknown as null;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue