mirror of
https://github.com/fosrl/pangolin.git
synced 2026-07-18 19:46:39 +02:00
add persistent session and users to access tokens
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import { hash } from "@node-rs/argon2";
|
||||
import {
|
||||
generateId,
|
||||
generateIdFromEntropySize,
|
||||
@@ -8,18 +7,18 @@ import { db } from "@server/db";
|
||||
import {
|
||||
ResourceAccessToken,
|
||||
resourceAccessToken,
|
||||
resources
|
||||
resources,
|
||||
userOrgs
|
||||
} from "@server/db";
|
||||
import HttpCode from "@server/types/HttpCode";
|
||||
import response from "@server/lib/response";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import createHttpError from "http-errors";
|
||||
import { z } from "zod";
|
||||
import { fromError } from "zod-validation-error";
|
||||
import logger from "@server/logger";
|
||||
import { createDate, TimeSpan } from "oslo";
|
||||
import { hashPassword } from "@server/auth/password";
|
||||
import { encodeHexLowerCase } from "@oslojs/encoding";
|
||||
import { sha256 } from "@oslojs/crypto/sha2";
|
||||
import { OpenAPITags, registry } from "@server/openApi";
|
||||
@@ -28,7 +27,9 @@ export const generateAccessTokenBodySchema = z.strictObject({
|
||||
validForSeconds: z.int().positive().optional(), // seconds
|
||||
title: z.string().optional(),
|
||||
path: z.string().optional(),
|
||||
description: z.string().optional()
|
||||
description: z.string().optional(),
|
||||
persistSession: z.boolean().optional().default(false),
|
||||
userId: z.string().optional()
|
||||
});
|
||||
|
||||
export const generateAccssTokenParamsSchema = z.strictObject({
|
||||
@@ -101,7 +102,14 @@ export async function generateAccessToken(
|
||||
}
|
||||
|
||||
const { resourceId } = parsedParams.data;
|
||||
const { validForSeconds, title, path, description } = parsedBody.data;
|
||||
const {
|
||||
validForSeconds,
|
||||
title,
|
||||
path,
|
||||
description,
|
||||
persistSession,
|
||||
userId
|
||||
} = parsedBody.data;
|
||||
|
||||
const [resource] = await db
|
||||
.select()
|
||||
@@ -112,6 +120,28 @@ export async function generateAccessToken(
|
||||
return next(createHttpError(HttpCode.NOT_FOUND, "Resource not found"));
|
||||
}
|
||||
|
||||
if (userId) {
|
||||
const [membership] = await db
|
||||
.select()
|
||||
.from(userOrgs)
|
||||
.where(
|
||||
and(
|
||||
eq(userOrgs.userId, userId),
|
||||
eq(userOrgs.orgId, resource.orgId)
|
||||
)
|
||||
)
|
||||
.limit(1);
|
||||
|
||||
if (!membership) {
|
||||
return next(
|
||||
createHttpError(
|
||||
HttpCode.BAD_REQUEST,
|
||||
"User is not a member of this organization"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const sessionLength = validForSeconds
|
||||
? validForSeconds * 1000
|
||||
@@ -133,23 +163,27 @@ export async function generateAccessToken(
|
||||
accessTokenId: id,
|
||||
orgId: resource.orgId,
|
||||
resourceId,
|
||||
userId: userId || null,
|
||||
tokenHash,
|
||||
expiresAt: expiresAt || null,
|
||||
sessionLength: sessionLength,
|
||||
title: title || null,
|
||||
path: path || null,
|
||||
description: description || null,
|
||||
persistSession,
|
||||
createdAt: new Date().getTime()
|
||||
})
|
||||
.returning({
|
||||
accessTokenId: resourceAccessToken.accessTokenId,
|
||||
orgId: resourceAccessToken.orgId,
|
||||
resourceId: resourceAccessToken.resourceId,
|
||||
userId: resourceAccessToken.userId,
|
||||
expiresAt: resourceAccessToken.expiresAt,
|
||||
sessionLength: resourceAccessToken.sessionLength,
|
||||
title: resourceAccessToken.title,
|
||||
path: resourceAccessToken.path,
|
||||
description: resourceAccessToken.description,
|
||||
persistSession: resourceAccessToken.persistSession,
|
||||
createdAt: resourceAccessToken.createdAt
|
||||
})
|
||||
.execute();
|
||||
|
||||
@@ -6,12 +6,13 @@ import {
|
||||
userResources,
|
||||
roleResources,
|
||||
resourceAccessToken,
|
||||
sites
|
||||
sites,
|
||||
users
|
||||
} from "@server/db";
|
||||
import response from "@server/lib/response";
|
||||
import HttpCode from "@server/types/HttpCode";
|
||||
import createHttpError from "http-errors";
|
||||
import { sql, eq, or, inArray, and, count, isNull, lt, gt } from "drizzle-orm";
|
||||
import { sql, eq, or, inArray, and, count, isNull, gt } from "drizzle-orm";
|
||||
import logger from "@server/logger";
|
||||
import stoi from "@server/lib/stoi";
|
||||
import { fromZodError } from "zod-validation-error";
|
||||
@@ -55,11 +56,16 @@ function queryAccessTokens(
|
||||
accessTokenId: resourceAccessToken.accessTokenId,
|
||||
orgId: resourceAccessToken.orgId,
|
||||
resourceId: resourceAccessToken.resourceId,
|
||||
userId: resourceAccessToken.userId,
|
||||
userName: users.name,
|
||||
username: users.username,
|
||||
userEmail: users.email,
|
||||
sessionLength: resourceAccessToken.sessionLength,
|
||||
expiresAt: resourceAccessToken.expiresAt,
|
||||
tokenHash: resourceAccessToken.tokenHash,
|
||||
title: resourceAccessToken.title,
|
||||
description: resourceAccessToken.description,
|
||||
persistSession: resourceAccessToken.persistSession,
|
||||
createdAt: resourceAccessToken.createdAt,
|
||||
resourceName: resources.name,
|
||||
resourceNiceId: resources.niceId,
|
||||
@@ -75,6 +81,7 @@ function queryAccessTokens(
|
||||
eq(resourceAccessToken.resourceId, resources.resourceId)
|
||||
)
|
||||
.leftJoin(sites, eq(resources.resourceId, sites.siteId))
|
||||
.leftJoin(users, eq(resourceAccessToken.userId, users.userId))
|
||||
.where(
|
||||
and(
|
||||
inArray(
|
||||
@@ -97,6 +104,7 @@ function queryAccessTokens(
|
||||
eq(resourceAccessToken.resourceId, resources.resourceId)
|
||||
)
|
||||
.leftJoin(sites, eq(resources.resourceId, sites.siteId))
|
||||
.leftJoin(users, eq(resourceAccessToken.userId, users.userId))
|
||||
.where(
|
||||
and(
|
||||
inArray(
|
||||
|
||||
Reference in New Issue
Block a user