mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-06-22 15:35:03 +00:00
userdefined api-keys
This commit is contained in:
parent
28862d70ca
commit
a884268d97
35
server-node/src/auth/apikey/apikey-controller.ts
Normal file
35
server-node/src/auth/apikey/apikey-controller.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { Error as SequelizeError } from "sequelize";
|
||||
import { APIKey } from "./apikey-model";
|
||||
import { User } from "../user/user-model";
|
||||
|
||||
export function findOne(params: {apikey?: string}, cb: (err: Error | null, apikey?: APIKey | undefined, info?: Object | undefined) => void): undefined {
|
||||
const query: any = params;
|
||||
|
||||
for (let key in query) {
|
||||
if (query[key] === undefined) {
|
||||
delete query[key];
|
||||
}
|
||||
}
|
||||
|
||||
if(Object.keys(query).length == 0) {
|
||||
cb(new Error("You need to provide at least one argument."), undefined)
|
||||
}
|
||||
|
||||
APIKey.findOne({
|
||||
where: query
|
||||
}).then(apikey => {
|
||||
if(apikey)
|
||||
cb(null, apikey);
|
||||
else
|
||||
cb(null, undefined, { message: "The requested apikey was not found."});
|
||||
}).catch(e =>
|
||||
cb(e, undefined)
|
||||
);
|
||||
}
|
||||
|
||||
export async function createAPIKey(user: User | undefined): Promise<APIKey> {
|
||||
const apikey = crypto.randomUUID(); // TODO: Is this secure enough?
|
||||
const apikeyEntry = await APIKey.create({ apikey: apikey })
|
||||
await user?.addAPIKey(apikeyEntry);
|
||||
return apikeyEntry;
|
||||
}
|
15
server-node/src/auth/apikey/apikey-model.ts
Normal file
15
server-node/src/auth/apikey/apikey-model.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { User } from '../user/user-model';
|
||||
import {
|
||||
Model, InferAttributes, InferCreationAttributes, CreationOptional, NonAttribute, ForeignKey,
|
||||
} from 'sequelize';
|
||||
|
||||
export class APIKey extends Model<InferAttributes<APIKey>, InferCreationAttributes<APIKey>> {
|
||||
declare id: CreationOptional<number>;
|
||||
declare apikey: string;
|
||||
|
||||
declare ownerId: ForeignKey<User['id']>;
|
||||
declare owner?: NonAttribute<User>;
|
||||
|
||||
declare createdAt: CreationOptional<Date>;
|
||||
declare updatedAt: CreationOptional<Date>;
|
||||
}
|
15
server-node/src/auth/authenticationMiddleware.ts
Normal file
15
server-node/src/auth/authenticationMiddleware.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
|
||||
export function isAuthorized(req: Request, res: Response, next: NextFunction) {
|
||||
if(import.meta.env.VITE_AUTH_ENABLED === "False" || req.user) {
|
||||
return next();
|
||||
}
|
||||
return res.status(403).json({"Error": "Authentication failed."});
|
||||
}
|
||||
|
||||
export function whenAuthIsEnabled(req: Request, res: Response, next: NextFunction) {
|
||||
if(import.meta.env.VITE_AUTH_ENABLED === "True") {
|
||||
return next();
|
||||
}
|
||||
return res.status(403).json({"Error": "Authentication is not enabled."});
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
|
||||
export function checkAuthorized(req: Request, res: Response, next: NextFunction) {
|
||||
if(import.meta.env.VITE_AUTH_ENABLED === "False" || req.user) {
|
||||
return next();
|
||||
}
|
||||
return res.status(403).json({"Error": "Authentication failed."});
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
import * as User from "./user/user-controller";
|
||||
|
||||
import { Strategy as LocalStrategy} from "passport-local";
|
||||
import { HeaderAPIKeyStrategy as HeaderAPIKeyStrategy } from "passport-headerapikey";
|
||||
|
||||
import * as User from "./user/user-controller";
|
||||
import * as APIKey from "./apikey/apikey-controller";
|
||||
|
||||
export function initialize(passport: typeof import("passport")) {
|
||||
passport.use("local", new LocalStrategy(
|
||||
function(username, password, done) {
|
||||
User.findOne({ username: username }, function (err, user) {
|
||||
User.findOne({username: username}, function (err, user) {
|
||||
if (err) {
|
||||
return done(err, false);
|
||||
}
|
||||
@ -29,14 +30,14 @@ export function initialize(passport: typeof import("passport")) {
|
||||
{ header: 'Authorization', prefix: 'Bearer ' },
|
||||
false,
|
||||
function(apikey, done) {
|
||||
User.findOne({ apikey: apikey }, function (err, user) {
|
||||
APIKey.findOne({ apikey: apikey }, function (err, apikey, info) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
return done(err, false);
|
||||
}
|
||||
if (!user) {
|
||||
return done(null, false);
|
||||
if (!apikey) {
|
||||
return done(null, false, info);
|
||||
}
|
||||
return done(null, user);
|
||||
return done(null, apikey.owner);
|
||||
});
|
||||
}
|
||||
));
|
||||
@ -46,7 +47,7 @@ export function initialize(passport: typeof import("passport")) {
|
||||
});
|
||||
|
||||
passport.deserializeUser((id: number, done) => {
|
||||
User.findOne({id: id}, function (err, user) {
|
||||
User.findOne({ id: id }, function (err, user) {
|
||||
done(err, user);
|
||||
});
|
||||
});
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Error as SequelizeError, Op } from "sequelize";
|
||||
import { APIKey, Password, User } from "./user-model";
|
||||
import { Password, User } from "./user-model";
|
||||
import crypto from "crypto";
|
||||
|
||||
type PickOne<T, F extends keyof T> = Pick<T, F> & { [K in keyof Omit<T, F>]?: never };
|
||||
|
||||
export function findOne(params: {id?: number, username?: string, apikey?: string}, cb: (err: Error | null, user: User | null) => void): undefined {
|
||||
export function findOne(params: {id?: number, username?: string}, cb: (err: Error | null, apikey?: User | undefined, info?: Object | undefined) => void): undefined {
|
||||
const query: any = params;
|
||||
|
||||
for (let key in query) {
|
||||
@ -14,7 +14,7 @@ export function findOne(params: {id?: number, username?: string, apikey?: string
|
||||
}
|
||||
|
||||
if(Object.keys(query).length == 0) {
|
||||
cb(new Error("You need to provide at least one argument."), null)
|
||||
cb(new Error("You need to provide at least one argument."), undefined)
|
||||
}
|
||||
|
||||
User.findOne({
|
||||
@ -23,9 +23,9 @@ export function findOne(params: {id?: number, username?: string, apikey?: string
|
||||
if(user)
|
||||
cb(null, user);
|
||||
else
|
||||
cb(new Error("The requested user was not found."), null);
|
||||
cb(null, undefined, { message: "The requested user was not found."});
|
||||
}).catch(e =>
|
||||
cb(e, null)
|
||||
cb(e, undefined)
|
||||
);
|
||||
}
|
||||
|
||||
@ -70,8 +70,4 @@ function hashPassword(password: string, salt: string, cb: (err: Error | null, de
|
||||
if (err) return cb(err, null);
|
||||
cb(null, derivedKey.toString('hex'));
|
||||
});
|
||||
}
|
||||
|
||||
export function createAPIKey(user: User, cb: (err: SequelizeError | null, apikey: APIKey | null) => void ) {
|
||||
user.addAPIKey()
|
||||
}
|
@ -10,6 +10,8 @@ import {
|
||||
HasOneGetAssociationMixin, HasOneSetAssociationMixin, HasOneCreateAssociationMixin,
|
||||
} from 'sequelize';
|
||||
|
||||
import { APIKey } from '../apikey/apikey-model';
|
||||
|
||||
export class User extends Model<InferAttributes<User>, InferCreationAttributes<User>> {
|
||||
declare id: CreationOptional<number>;
|
||||
declare username: string;
|
||||
@ -64,17 +66,6 @@ export class AccessRule extends Model<InferAttributes<AccessRule>, InferCreation
|
||||
declare ownerId: ForeignKey<User['id']>;
|
||||
declare owner?: NonAttribute<User>;
|
||||
|
||||
declare createdAt: CreationOptional<Date>;
|
||||
declare updatedAt: CreationOptional<Date>;
|
||||
}
|
||||
|
||||
export class APIKey extends Model<InferAttributes<APIKey>, InferCreationAttributes<APIKey>> {
|
||||
declare id: CreationOptional<number>;
|
||||
declare apikey: string;
|
||||
|
||||
declare ownerId: ForeignKey<User['id']>;
|
||||
declare owner?: NonAttribute<User>;
|
||||
|
||||
declare createdAt: CreationOptional<Date>;
|
||||
declare updatedAt: CreationOptional<Date>;
|
||||
}
|
@ -5,7 +5,8 @@ const sequelize = new Sequelize("sqlite::memory:", {
|
||||
logging: import.meta.env.VITE_SEQUELIZE_LOGGING === "True" ? console.log : false
|
||||
});
|
||||
|
||||
import { User, AccessRule, APIKey, Password } from "../auth/user/user-model";
|
||||
import { User, AccessRule, Password } from "../auth/user/user-model";
|
||||
import { APIKey } from "../auth/apikey/apikey-model";
|
||||
|
||||
User.init(
|
||||
{
|
||||
|
@ -1,13 +1,13 @@
|
||||
import express, { Request, Response } from "express";
|
||||
|
||||
import { checkAuthorized } from "../../auth/checkAuthorizedMiddleware";
|
||||
import { isAuthorized } from "../../auth/authenticationMiddleware";
|
||||
|
||||
import workflow from "./workflow-controller";
|
||||
import dynamicOperations from "./dynamic-operations-controller";
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.use(checkAuthorized);
|
||||
router.use(isAuthorized);
|
||||
|
||||
router.get("/", (req: Request, res: Response) => {
|
||||
// TODO: Implement root api endpoint
|
||||
|
@ -1,11 +1,10 @@
|
||||
import { checkAuthorized } from "../../auth/checkAuthorizedMiddleware";
|
||||
import { APIKey } from "../../auth/user/user-model";
|
||||
import * as APIKey from "../../auth/apikey/apikey-controller";
|
||||
import { whenAuthIsEnabled, isAuthorized } from "../../auth/authenticationMiddleware";
|
||||
import express, { Request, Response } from "express";
|
||||
const router = express.Router();
|
||||
|
||||
router.post('/create-api-key', checkAuthorized, async function(req: Request, res: Response) {
|
||||
const apikey: APIKey | undefined = await req.user?.createAPIKey({apikey: "test"}); //TODO: Replace with random string
|
||||
res.json({apikey: apikey});
|
||||
router.post('/create-api-key', whenAuthIsEnabled, isAuthorized, async function(req: Request, res: Response) {
|
||||
res.json({apikey: await APIKey.createAPIKey(req.user)});
|
||||
});
|
||||
|
||||
export default router;
|
@ -1,8 +1,8 @@
|
||||
import { checkAuthorized } from "../../auth/checkAuthorizedMiddleware";
|
||||
import { isAuthorized } from "../../auth/authenticationMiddleware";
|
||||
import express, { Request, Response } from "express";
|
||||
const router = express.Router();
|
||||
|
||||
router.get('/status', checkAuthorized, async function(req: Request, res: Response) {
|
||||
router.get('/status', isAuthorized, async function(req: Request, res: Response) {
|
||||
res.json({user: req.user});
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user