Merge branch 'fosrl:main' into fix-crowdsec-config

This commit is contained in:
Marvin 2025-04-06 19:31:54 +02:00 committed by GitHub
commit a33ebe5bc5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
175 changed files with 1123 additions and 553 deletions

37
.github/workflows/stale-bot.yml vendored Normal file
View file

@ -0,0 +1,37 @@
name: Mark and Close Stale Issues
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch: # Allow manual trigger
permissions:
contents: write # only for delete-branch option
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
with:
days-before-stale: 30
days-before-close: 14
stale-issue-message: 'This issue has been automatically marked as stale due to 30 days of inactivity. It will be closed in 14 days if no further activity occurs.'
close-issue-message: 'This issue has been automatically closed due to inactivity. If you believe this is still relevant, please open a new issue with up-to-date information.'
stale-issue-label: 'stale'
exempt-issue-labels: 'needs investigating, networking, new feature, reverse proxy, bug, api, authentication, documentation, enhancement, help wanted, good first issue, question'
exempt-all-issue-assignees: true
only-labels: ''
exempt-pr-labels: ''
days-before-pr-stale: -1
days-before-pr-close: -1
operations-per-run: 100
remove-stale-when-updated: true
delete-branch: false
enable-statistics: true

View file

@ -7,7 +7,7 @@ RUN npm ci
COPY . . COPY . .
RUN npx drizzle-kit generate --dialect sqlite --schema ./server/db/schema.ts --out init RUN npx drizzle-kit generate --dialect sqlite --schema ./server/db/schemas/ --out init
RUN npm run build RUN npm run build

View file

@ -18,6 +18,9 @@ server:
internal_hostname: "pangolin" internal_hostname: "pangolin"
session_cookie_name: "p_session_token" session_cookie_name: "p_session_token"
resource_access_token_param: "p_token" resource_access_token_param: "p_token"
resource_access_token_headers:
id: "P-Access-Token-Id"
token: "P-Access-Token"
resource_session_request_param: "p_session_request" resource_session_request_param: "p_session_request"
traefik: traefik:
@ -35,7 +38,7 @@ gerbil:
rate_limits: rate_limits:
global: global:
window_minutes: 1 window_minutes: 1
max_requests: 100 max_requests: 500
users: users:
server_admin: server_admin:

View file

@ -4,10 +4,10 @@ import path from "path";
export default defineConfig({ export default defineConfig({
dialect: "sqlite", dialect: "sqlite",
schema: path.join("server", "db", "schema.ts"), schema: path.join("server", "db", "schemas"),
out: path.join("server", "migrations"), out: path.join("server", "migrations"),
verbose: true, verbose: true,
dbCredentials: { dbCredentials: {
url: path.join(APP_PATH, "db", "db.sqlite"), url: path.join(APP_PATH, "db", "db.sqlite")
}, }
}); });

View file

@ -18,6 +18,9 @@ server:
internal_hostname: "pangolin" internal_hostname: "pangolin"
session_cookie_name: "p_session_token" session_cookie_name: "p_session_token"
resource_access_token_param: "p_token" resource_access_token_param: "p_token"
resource_access_token_headers:
id: "P-Access-Token-Id"
token: "P-Access-Token"
resource_session_request_param: "p_session_request" resource_session_request_param: "p_session_request"
cors: cors:
origins: ["https://{{.DashboardDomain}}"] origins: ["https://{{.DashboardDomain}}"]

View file

@ -14,7 +14,7 @@ import { logIncomingMiddleware } from "./middlewares/logIncoming";
import { csrfProtectionMiddleware } from "./middlewares/csrfProtection"; import { csrfProtectionMiddleware } from "./middlewares/csrfProtection";
import helmet from "helmet"; import helmet from "helmet";
const dev = process.env.ENVIRONMENT !== "prod"; const dev = config.isDev;
const externalPort = config.getRawConfig().server.external_port; const externalPort = config.getRawConfig().server.external_port;
export function createApiServer() { export function createApiServer() {

View file

@ -1,6 +1,6 @@
import { Request } from "express"; import { Request } from "express";
import { db } from "@server/db"; import { db } from "@server/db";
import { userActions, roleActions, userOrgs } from "@server/db/schema"; import { userActions, roleActions, userOrgs } from "@server/db/schemas";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
@ -63,6 +63,7 @@ export enum ActionsEnum {
listResourceRules = "listResourceRules", listResourceRules = "listResourceRules",
updateResourceRule = "updateResourceRule", updateResourceRule = "updateResourceRule",
listOrgDomains = "listOrgDomains", listOrgDomains = "listOrgDomains",
createNewt = "createNewt",
} }
export async function checkUserActionPermission( export async function checkUserActionPermission(

View file

@ -1,6 +1,6 @@
import db from "@server/db"; import db from "@server/db";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import { roleResources, userResources } from "@server/db/schema"; import { roleResources, userResources } from "@server/db/schemas";
export async function canUserAccessResource({ export async function canUserAccessResource({
userId, userId,

View file

@ -1,5 +1,5 @@
import db from "@server/db"; import db from "@server/db";
import { UserInvite, userInvites } from "@server/db/schema"; import { UserInvite, userInvites } from "@server/db/schemas";
import { isWithinExpirationDate } from "oslo"; import { isWithinExpirationDate } from "oslo";
import { verifyPassword } from "./password"; import { verifyPassword } from "./password";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";

View file

@ -1,5 +1,5 @@
import { db } from '@server/db'; import { db } from '@server/db';
import { limitsTable } from '@server/db/schema'; import { limitsTable } from '@server/db/schemas';
import { and, eq } from 'drizzle-orm'; import { and, eq } from 'drizzle-orm';
import createHttpError from 'http-errors'; import createHttpError from 'http-errors';
import HttpCode from '@server/types/HttpCode'; import HttpCode from '@server/types/HttpCode';

View file

@ -1,5 +1,5 @@
import db from "@server/db"; import db from "@server/db";
import { resourceOtp } from "@server/db/schema"; import { resourceOtp } from "@server/db/schemas";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import { createDate, isWithinExpirationDate, TimeSpan } from "oslo"; import { createDate, isWithinExpirationDate, TimeSpan } from "oslo";
import { alphabet, generateRandomString, sha256 } from "oslo/crypto"; import { alphabet, generateRandomString, sha256 } from "oslo/crypto";

View file

@ -1,7 +1,7 @@
import { TimeSpan, createDate } from "oslo"; import { TimeSpan, createDate } from "oslo";
import { generateRandomString, alphabet } from "oslo/crypto"; import { generateRandomString, alphabet } from "oslo/crypto";
import db from "@server/db"; import db from "@server/db";
import { users, emailVerificationCodes } from "@server/db/schema"; import { users, emailVerificationCodes } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { sendEmail } from "@server/emails"; import { sendEmail } from "@server/emails";
import config from "@server/lib/config"; import config from "@server/lib/config";

View file

@ -9,7 +9,7 @@ import {
sessions, sessions,
User, User,
users users
} from "@server/db/schema"; } from "@server/db/schemas";
import db from "@server/db"; import db from "@server/db";
import { eq, inArray } from "drizzle-orm"; import { eq, inArray } from "drizzle-orm";
import config from "@server/lib/config"; import config from "@server/lib/config";

View file

@ -2,7 +2,7 @@ import {
encodeHexLowerCase, encodeHexLowerCase,
} from "@oslojs/encoding"; } from "@oslojs/encoding";
import { sha256 } from "@oslojs/crypto/sha2"; import { sha256 } from "@oslojs/crypto/sha2";
import { Newt, newts, newtSessions, NewtSession } from "@server/db/schema"; import { Newt, newts, newtSessions, NewtSession } from "@server/db/schemas";
import db from "@server/db"; import db from "@server/db";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";

View file

@ -1,6 +1,6 @@
import { encodeHexLowerCase } from "@oslojs/encoding"; import { encodeHexLowerCase } from "@oslojs/encoding";
import { sha256 } from "@oslojs/crypto/sha2"; import { sha256 } from "@oslojs/crypto/sha2";
import { resourceSessions, ResourceSession } from "@server/db/schema"; import { resourceSessions, ResourceSession } from "@server/db/schemas";
import db from "@server/db"; import db from "@server/db";
import { eq, and } from "drizzle-orm"; import { eq, and } from "drizzle-orm";
import config from "@server/lib/config"; import config from "@server/lib/config";

View file

@ -1,6 +1,6 @@
import { verify } from "@node-rs/argon2"; import { verify } from "@node-rs/argon2";
import db from "@server/db"; import db from "@server/db";
import { twoFactorBackupCodes } from "@server/db/schema"; import { twoFactorBackupCodes } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { decodeHex } from "oslo/encoding"; import { decodeHex } from "oslo/encoding";
import { TOTPController } from "oslo/otp"; import { TOTPController } from "oslo/otp";

View file

@ -3,45 +3,63 @@ import {
Resource, Resource,
ResourceAccessToken, ResourceAccessToken,
resourceAccessToken, resourceAccessToken,
} from "@server/db/schema"; resources
} from "@server/db/schemas";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import { isWithinExpirationDate } from "oslo"; import { isWithinExpirationDate } from "oslo";
import { verifyPassword } from "./password"; import { verifyPassword } from "./password";
import { encodeHexLowerCase } from "@oslojs/encoding";
import { sha256 } from "@oslojs/crypto/sha2";
export async function verifyResourceAccessToken({ export async function verifyResourceAccessToken({
resource, accessToken,
accessTokenId, accessTokenId,
accessToken resourceId
}: { }: {
resource: Resource;
accessTokenId: string;
accessToken: string; accessToken: string;
accessTokenId?: string;
resourceId?: number; // IF THIS IS NOT SET, THE TOKEN IS VALID FOR ALL RESOURCES
}): Promise<{ }): Promise<{
valid: boolean; valid: boolean;
error?: string; error?: string;
tokenItem?: ResourceAccessToken; tokenItem?: ResourceAccessToken;
resource?: Resource;
}> { }> {
const [result] = await db const accessTokenHash = encodeHexLowerCase(
sha256(new TextEncoder().encode(accessToken))
);
let tokenItem: ResourceAccessToken | undefined;
let resource: Resource | undefined;
if (!accessTokenId) {
const [res] = await db
.select() .select()
.from(resourceAccessToken) .from(resourceAccessToken)
.where( .where(and(eq(resourceAccessToken.tokenHash, accessTokenHash)))
and( .innerJoin(
eq(resourceAccessToken.resourceId, resource.resourceId), resources,
eq(resourceAccessToken.accessTokenId, accessTokenId) eq(resourceAccessToken.resourceId, resources.resourceId)
) );
)
.limit(1);
const tokenItem = result; tokenItem = res?.resourceAccessToken;
resource = res?.resources;
} else {
const [res] = await db
.select()
.from(resourceAccessToken)
.where(and(eq(resourceAccessToken.accessTokenId, accessTokenId)))
.innerJoin(
resources,
eq(resourceAccessToken.resourceId, resources.resourceId)
);
if (!tokenItem) { if (res && res.resourceAccessToken) {
return { if (res.resourceAccessToken.tokenHash?.startsWith("$argon")) {
valid: false, const validCode = await verifyPassword(
error: "Access token does not exist for resource" accessToken,
}; res.resourceAccessToken.tokenHash
} );
const validCode = await verifyPassword(accessToken, tokenItem.tokenHash);
if (!validCode) { if (!validCode) {
return { return {
@ -49,6 +67,30 @@ export async function verifyResourceAccessToken({
error: "Invalid access token" error: "Invalid access token"
}; };
} }
} else {
const tokenHash = encodeHexLowerCase(
sha256(new TextEncoder().encode(accessToken))
);
if (res.resourceAccessToken.tokenHash !== tokenHash) {
return {
valid: false,
error: "Invalid access token"
};
}
}
}
tokenItem = res?.resourceAccessToken;
resource = res?.resources;
}
if (!tokenItem || !resource) {
return {
valid: false,
error: "Access token does not exist for resource"
};
}
if ( if (
tokenItem.expiresAt && tokenItem.expiresAt &&
@ -60,8 +102,16 @@ export async function verifyResourceAccessToken({
}; };
} }
if (resourceId && resource.resourceId !== resourceId) {
return {
valid: false,
error: "Resource ID does not match"
};
}
return { return {
valid: true, valid: true,
tokenItem tokenItem,
resource
}; };
} }

View file

@ -1,6 +1,6 @@
import { drizzle } from "drizzle-orm/better-sqlite3"; import { drizzle } from "drizzle-orm/better-sqlite3";
import Database from "better-sqlite3"; import Database from "better-sqlite3";
import * as schema from "@server/db/schema"; import * as schema from "@server/db/schemas";
import path from "path"; import path from "path";
import fs from "fs/promises"; import fs from "fs/promises";
import { APP_PATH } from "@server/lib/consts"; import { APP_PATH } from "@server/lib/consts";

View file

@ -1,7 +1,7 @@
import { join } from "path"; import { join } from "path";
import { readFileSync } from "fs"; import { readFileSync } from "fs";
import { db } from "@server/db"; import { db } from "@server/db";
import { exitNodes, sites } from "./schema"; import { exitNodes, sites } from "./schemas/schema";
import { eq, and } from "drizzle-orm"; import { eq, and } from "drizzle-orm";
import { __DIRNAME } from "@server/lib/consts"; import { __DIRNAME } from "@server/lib/consts";

View file

@ -0,0 +1 @@
export * from "./schema";

View file

@ -76,7 +76,8 @@ export const resources = sqliteTable("resources", {
isBaseDomain: integer("isBaseDomain", { mode: "boolean" }), isBaseDomain: integer("isBaseDomain", { mode: "boolean" }),
applyRules: integer("applyRules", { mode: "boolean" }) applyRules: integer("applyRules", { mode: "boolean" })
.notNull() .notNull()
.default(false) .default(false),
enabled: integer("enabled", { mode: "boolean" }).notNull().default(true)
}); });
export const targets = sqliteTable("targets", { export const targets = sqliteTable("targets", {

View file

@ -2,7 +2,7 @@ import { runSetupFunctions } from "./setup";
import { createApiServer } from "./apiServer"; import { createApiServer } from "./apiServer";
import { createNextServer } from "./nextServer"; import { createNextServer } from "./nextServer";
import { createInternalServer } from "./internalServer"; import { createInternalServer } from "./internalServer";
import { Session, User, UserOrg } from "./db/schema"; import { Session, User, UserOrg } from "./db/schemas/schema";
async function startServers() { async function startServers() {
await runSetupFunctions(); await runSetupFunctions();

View file

@ -1,6 +1,6 @@
import db from "@server/db"; import db from "@server/db";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import { roleResources, userResources } from "@server/db/schema"; import { roleResources, userResources } from "@server/db/schemas";
export async function canUserAccessResource({ export async function canUserAccessResource({
userId, userId,

View file

@ -11,7 +11,7 @@ import {
import { passwordSchema } from "@server/auth/passwordSchema"; import { passwordSchema } from "@server/auth/passwordSchema";
import stoi from "./stoi"; import stoi from "./stoi";
import db from "@server/db"; import db from "@server/db";
import { SupporterKey, supporterKey } from "@server/db/schema"; import { SupporterKey, supporterKey } from "@server/db/schemas";
import { suppressDeprecationWarnings } from "moment"; import { suppressDeprecationWarnings } from "moment";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
@ -66,6 +66,10 @@ const configSchema = z.object({
internal_hostname: z.string().transform((url) => url.toLowerCase()), internal_hostname: z.string().transform((url) => url.toLowerCase()),
session_cookie_name: z.string(), session_cookie_name: z.string(),
resource_access_token_param: z.string(), resource_access_token_param: z.string(),
resource_access_token_headers: z.object({
id: z.string(),
token: z.string()
}),
resource_session_request_param: z.string(), resource_session_request_param: z.string(),
dashboard_session_length_hours: z dashboard_session_length_hours: z
.number() .number()
@ -163,6 +167,8 @@ export class Config {
supporterHiddenUntil: number | null = null; supporterHiddenUntil: number | null = null;
isDev: boolean = process.env.ENVIRONMENT !== "prod";
constructor() { constructor() {
this.loadConfig(); this.loadConfig();
} }
@ -237,6 +243,10 @@ export class Config {
: "false"; : "false";
process.env.RESOURCE_ACCESS_TOKEN_PARAM = process.env.RESOURCE_ACCESS_TOKEN_PARAM =
parsedConfig.data.server.resource_access_token_param; parsedConfig.data.server.resource_access_token_param;
process.env.RESOURCE_ACCESS_TOKEN_HEADERS_ID =
parsedConfig.data.server.resource_access_token_headers.id;
process.env.RESOURCE_ACCESS_TOKEN_HEADERS_TOKEN =
parsedConfig.data.server.resource_access_token_headers.token;
process.env.RESOURCE_SESSION_REQUEST_PARAM = process.env.RESOURCE_SESSION_REQUEST_PARAM =
parsedConfig.data.server.resource_session_request_param; parsedConfig.data.server.resource_session_request_param;
process.env.FLAGS_ALLOW_BASE_DOMAIN_RESOURCES = parsedConfig.data.flags process.env.FLAGS_ALLOW_BASE_DOMAIN_RESOURCES = parsedConfig.data.flags
@ -245,7 +255,9 @@ export class Config {
: "false"; : "false";
process.env.DASHBOARD_URL = parsedConfig.data.app.dashboard_url; process.env.DASHBOARD_URL = parsedConfig.data.app.dashboard_url;
if (!this.isDev) {
this.checkSupporterKey(); this.checkSupporterKey();
}
this.rawConfig = parsedConfig.data; this.rawConfig = parsedConfig.data;
} }

View file

@ -2,7 +2,7 @@ import path from "path";
import { fileURLToPath } from "url"; import { fileURLToPath } from "url";
// This is a placeholder value replaced by the build process // This is a placeholder value replaced by the build process
export const APP_VERSION = "1.1.0"; export const APP_VERSION = "1.2.0";
export const __FILENAME = fileURLToPath(import.meta.url); export const __FILENAME = fileURLToPath(import.meta.url);
export const __DIRNAME = path.dirname(__FILENAME); export const __DIRNAME = path.dirname(__FILENAME);

View file

@ -1,6 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { db } from "@server/db"; import { db } from "@server/db";
import { userOrgs, orgs } from "@server/db/schema"; import { userOrgs, orgs } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,6 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { db } from "@server/db"; import { db } from "@server/db";
import { resourceAccessToken, resources, userOrgs } from "@server/db/schema"; import { resourceAccessToken, resources, userOrgs } from "@server/db/schemas";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,6 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { db } from "@server/db"; import { db } from "@server/db";
import { roles, userOrgs } from "@server/db/schema"; import { roles, userOrgs } from "@server/db/schemas";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,6 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { db } from "@server/db"; import { db } from "@server/db";
import { userOrgs } from "@server/db/schema"; import { userOrgs } from "@server/db/schemas";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -5,7 +5,7 @@ import {
userOrgs, userOrgs,
userResources, userResources,
roleResources, roleResources,
} from "@server/db/schema"; } from "@server/db/schemas";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,6 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { db } from "@server/db"; import { db } from "@server/db";
import { roles, userOrgs } from "@server/db/schema"; import { roles, userOrgs } from "@server/db/schemas";
import { and, eq, inArray } from "drizzle-orm"; import { and, eq, inArray } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
@ -44,6 +44,8 @@ export async function verifyRoleAccess(
); );
} }
const orgIds = new Set(rolesData.map((role) => role.orgId));
// Check user access to each role's organization // Check user access to each role's organization
for (const role of rolesData) { for (const role of rolesData) {
const userOrgRole = await db const userOrgRole = await db
@ -69,7 +71,16 @@ export async function verifyRoleAccess(
req.userOrgId = role.orgId; req.userOrgId = role.orgId;
} }
const orgId = req.userOrgId; if (orgIds.size > 1) {
return next(
createHttpError(
HttpCode.FORBIDDEN,
"Roles must belong to the same organization"
)
);
}
const orgId = orgIds.values().next().value;
if (!orgId) { if (!orgId) {
return next( return next(
@ -105,3 +116,4 @@ export async function verifyRoleAccess(
); );
} }
} }

View file

@ -1,7 +1,7 @@
import { NextFunction, Response } from "express"; import { NextFunction, Response } from "express";
import ErrorResponse from "@server/types/ErrorResponse"; import ErrorResponse from "@server/types/ErrorResponse";
import { db } from "@server/db"; import { db } from "@server/db";
import { users } from "@server/db/schema"; import { users } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,6 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { db } from "@server/db"; import { db } from "@server/db";
import { userOrgs } from "@server/db/schema"; import { userOrgs } from "@server/db/schemas";
import { and, eq, inArray, or } from "drizzle-orm"; import { and, eq, inArray, or } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -6,7 +6,7 @@ import {
userSites, userSites,
roleSites, roleSites,
roles, roles,
} from "@server/db/schema"; } from "@server/db/schemas";
import { and, eq, or } from "drizzle-orm"; import { and, eq, or } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,6 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { db } from "@server/db"; import { db } from "@server/db";
import { resources, targets, userOrgs } from "@server/db/schema"; import { resources, targets, userOrgs } from "@server/db/schemas";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,7 +1,7 @@
import { NextFunction, Response } from "express"; import { NextFunction, Response } from "express";
import ErrorResponse from "@server/types/ErrorResponse"; import ErrorResponse from "@server/types/ErrorResponse";
import { db } from "@server/db"; import { db } from "@server/db";
import { users } from "@server/db/schema"; import { users } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,6 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { db } from "@server/db"; import { db } from "@server/db";
import { userOrgs } from "@server/db/schema"; import { userOrgs } from "@server/db/schemas";
import { and, eq, or } from "drizzle-orm"; import { and, eq, or } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,6 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { db } from "@server/db"; import { db } from "@server/db";
import { userOrgs } from "@server/db/schema"; import { userOrgs } from "@server/db/schemas";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -5,7 +5,7 @@ import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import logger from "@server/logger"; import logger from "@server/logger";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { resourceAccessToken } from "@server/db/schema"; import { resourceAccessToken } from "@server/db/schemas";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import db from "@server/db"; import db from "@server/db";

View file

@ -9,7 +9,7 @@ import {
ResourceAccessToken, ResourceAccessToken,
resourceAccessToken, resourceAccessToken,
resources resources
} from "@server/db/schema"; } from "@server/db/schemas";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import response from "@server/lib/response"; import response from "@server/lib/response";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
@ -20,6 +20,8 @@ import { fromError } from "zod-validation-error";
import logger from "@server/logger"; import logger from "@server/logger";
import { createDate, TimeSpan } from "oslo"; import { createDate, TimeSpan } from "oslo";
import { hashPassword } from "@server/auth/password"; import { hashPassword } from "@server/auth/password";
import { encodeHexLowerCase } from "@oslojs/encoding";
import { sha256 } from "@oslojs/crypto/sha2";
export const generateAccessTokenBodySchema = z export const generateAccessTokenBodySchema = z
.object({ .object({
@ -90,11 +92,13 @@ export async function generateAccessToken(
? createDate(new TimeSpan(validForSeconds, "s")).getTime() ? createDate(new TimeSpan(validForSeconds, "s")).getTime()
: undefined; : undefined;
const token = generateIdFromEntropySize(25); const token = generateIdFromEntropySize(16);
const tokenHash = await hashPassword(token); const tokenHash = encodeHexLowerCase(
sha256(new TextEncoder().encode(token))
);
const id = generateId(15); const id = generateId(8);
const [result] = await db const [result] = await db
.insert(resourceAccessToken) .insert(resourceAccessToken)
.values({ .values({

View file

@ -7,13 +7,14 @@ import {
roleResources, roleResources,
resourceAccessToken, resourceAccessToken,
sites sites
} from "@server/db/schema"; } from "@server/db/schemas";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; 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, lt, gt } from "drizzle-orm";
import logger from "@server/logger"; import logger from "@server/logger";
import stoi from "@server/lib/stoi"; import stoi from "@server/lib/stoi";
import { fromZodError } from "zod-validation-error";
const listAccessTokensParamsSchema = z const listAccessTokensParamsSchema = z
.object({ .object({
@ -133,7 +134,7 @@ export async function listAccessTokens(
return next( return next(
createHttpError( createHttpError(
HttpCode.BAD_REQUEST, HttpCode.BAD_REQUEST,
parsedQuery.error.errors.map((e) => e.message).join(", ") fromZodError(parsedQuery.error)
) )
); );
} }
@ -144,7 +145,7 @@ export async function listAccessTokens(
return next( return next(
createHttpError( createHttpError(
HttpCode.BAD_REQUEST, HttpCode.BAD_REQUEST,
parsedParams.error.errors.map((e) => e.message).join(", ") fromZodError(parsedParams.error)
) )
); );
} }

View file

@ -4,7 +4,7 @@ import HttpCode from "@server/types/HttpCode";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { User, users } from "@server/db/schema"; import { User, users } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { response } from "@server/lib"; import { response } from "@server/lib";
import { import {

View file

@ -4,7 +4,7 @@ import HttpCode from "@server/types/HttpCode";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { User, users } from "@server/db/schema"; import { User, users } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { response } from "@server/lib"; import { response } from "@server/lib";
import { verifyPassword } from "@server/auth/password"; import { verifyPassword } from "@server/auth/password";

View file

@ -4,7 +4,7 @@ import {
serializeSessionCookie serializeSessionCookie
} from "@server/auth/sessions/app"; } from "@server/auth/sessions/app";
import db from "@server/db"; import db from "@server/db";
import { users } from "@server/db/schema"; import { users } from "@server/db/schemas";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import response from "@server/lib/response"; import response from "@server/lib/response";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";

View file

@ -2,7 +2,7 @@ import { Request, Response, NextFunction } from "express";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import { response } from "@server/lib"; import { response } from "@server/lib";
import { User } from "@server/db/schema"; import { User } from "@server/db/schemas";
import { sendEmailVerificationCode } from "../../auth/sendEmailVerificationCode"; import { sendEmailVerificationCode } from "../../auth/sendEmailVerificationCode";
import config from "@server/lib/config"; import config from "@server/lib/config";
import logger from "@server/logger"; import logger from "@server/logger";

View file

@ -5,7 +5,7 @@ import { fromError } from "zod-validation-error";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import { response } from "@server/lib"; import { response } from "@server/lib";
import { db } from "@server/db"; import { db } from "@server/db";
import { passwordResetTokens, users } from "@server/db/schema"; import { passwordResetTokens, users } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { alphabet, generateRandomString, sha256 } from "oslo/crypto"; import { alphabet, generateRandomString, sha256 } from "oslo/crypto";
import { createDate } from "oslo"; import { createDate } from "oslo";

View file

@ -6,7 +6,7 @@ import { encodeHex } from "oslo/encoding";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import { response } from "@server/lib"; import { response } from "@server/lib";
import { db } from "@server/db"; import { db } from "@server/db";
import { User, users } from "@server/db/schema"; import { User, users } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { createTOTPKeyURI } from "oslo/otp"; import { createTOTPKeyURI } from "oslo/otp";
import logger from "@server/logger"; import logger from "@server/logger";

View file

@ -6,7 +6,7 @@ import { fromError } from "zod-validation-error";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import { response } from "@server/lib"; import { response } from "@server/lib";
import { db } from "@server/db"; import { db } from "@server/db";
import { passwordResetTokens, users } from "@server/db/schema"; import { passwordResetTokens, users } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { hashPassword, verifyPassword } from "@server/auth/password"; import { hashPassword, verifyPassword } from "@server/auth/password";
import { verifyTotpCode } from "@server/auth/totp"; import { verifyTotpCode } from "@server/auth/totp";

View file

@ -2,7 +2,7 @@ import { NextFunction, Request, Response } from "express";
import db from "@server/db"; import db from "@server/db";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import { z } from "zod"; import { z } from "zod";
import { users } from "@server/db/schema"; import { users } from "@server/db/schemas";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import response from "@server/lib/response"; import response from "@server/lib/response";

View file

@ -5,7 +5,7 @@ import { fromError } from "zod-validation-error";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import { response } from "@server/lib"; import { response } from "@server/lib";
import { db } from "@server/db"; import { db } from "@server/db";
import { User, emailVerificationCodes, users } from "@server/db/schema"; import { User, emailVerificationCodes, users } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { isWithinExpirationDate } from "oslo"; import { isWithinExpirationDate } from "oslo";
import config from "@server/lib/config"; import config from "@server/lib/config";

View file

@ -5,7 +5,7 @@ import { fromError } from "zod-validation-error";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import { response } from "@server/lib"; import { response } from "@server/lib";
import { db } from "@server/db"; import { db } from "@server/db";
import { twoFactorBackupCodes, User, users } from "@server/db/schema"; import { twoFactorBackupCodes, User, users } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { alphabet, generateRandomString } from "oslo/crypto"; import { alphabet, generateRandomString } from "oslo/crypto";
import { hashPassword } from "@server/auth/password"; import { hashPassword } from "@server/auth/password";

View file

@ -4,7 +4,7 @@ import createHttpError from "http-errors";
import { z } from "zod"; import { z } from "zod";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import logger from "@server/logger"; import logger from "@server/logger";
import { resourceAccessToken, resources, sessions } from "@server/db/schema"; import { resourceAccessToken, resources, sessions } from "@server/db/schemas";
import db from "@server/db"; import db from "@server/db";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { import {

View file

@ -21,7 +21,7 @@ import {
userOrgs, userOrgs,
userResources, userResources,
users users
} from "@server/db/schema"; } from "@server/db/schemas";
import config from "@server/lib/config"; import config from "@server/lib/config";
import { isIpInCidr } from "@server/lib/ip"; import { isIpInCidr } from "@server/lib/ip";
import { response } from "@server/lib/response"; import { response } from "@server/lib/response";
@ -41,12 +41,13 @@ const cache = new NodeCache({
const verifyResourceSessionSchema = z.object({ const verifyResourceSessionSchema = z.object({
sessions: z.record(z.string()).optional(), sessions: z.record(z.string()).optional(),
headers: z.record(z.string()).optional(),
query: z.record(z.string()).optional(),
originalRequestURL: z.string().url(), originalRequestURL: z.string().url(),
scheme: z.string(), scheme: z.string(),
host: z.string(), host: z.string(),
path: z.string(), path: z.string(),
method: z.string(), method: z.string(),
accessToken: z.string().optional(),
tls: z.boolean(), tls: z.boolean(),
requestIp: z.string().optional() requestIp: z.string().optional()
}); });
@ -85,7 +86,8 @@ export async function verifyResourceSession(
originalRequestURL, originalRequestURL,
requestIp, requestIp,
path, path,
accessToken: token headers,
query
} = parsedBody.data; } = parsedBody.data;
const clientIp = requestIp?.split(":")[0]; const clientIp = requestIp?.split(":")[0];
@ -183,12 +185,33 @@ export async function verifyResourceSession(
resource.resourceId resource.resourceId
)}?redirect=${encodeURIComponent(originalRequestURL)}`; )}?redirect=${encodeURIComponent(originalRequestURL)}`;
// check for access token // check for access token in headers
let validAccessToken: ResourceAccessToken | undefined; if (
if (token) { headers &&
const [accessTokenId, accessToken] = token.split("."); headers[
config.getRawConfig().server.resource_access_token_headers.id
] &&
headers[
config.getRawConfig().server.resource_access_token_headers.token
]
) {
const accessTokenId =
headers[
config.getRawConfig().server.resource_access_token_headers
.id
];
const accessToken =
headers[
config.getRawConfig().server.resource_access_token_headers
.token
];
const { valid, error, tokenItem } = await verifyResourceAccessToken( const { valid, error, tokenItem } = await verifyResourceAccessToken(
{ resource, accessTokenId, accessToken } {
accessToken,
accessTokenId,
resourceId: resource.resourceId
}
); );
if (error) { if (error) {
@ -206,16 +229,44 @@ export async function verifyResourceSession(
} }
if (valid && tokenItem) { if (valid && tokenItem) {
validAccessToken = tokenItem; return allowed(res);
}
}
if (!sessions) { if (
return await createAccessTokenSession( query &&
res, query[config.getRawConfig().server.resource_access_token_param]
resource, ) {
tokenItem const token =
query[config.getRawConfig().server.resource_access_token_param];
const [accessTokenId, accessToken] = token.split(".");
const { valid, error, tokenItem } = await verifyResourceAccessToken(
{
accessToken,
accessTokenId,
resourceId: resource.resourceId
}
);
if (error) {
logger.debug("Access token invalid: " + error);
}
if (!valid) {
if (config.getRawConfig().app.log_failed_attempts) {
logger.info(
`Resource access token is invalid. Resource ID: ${
resource.resourceId
}. IP: ${clientIp}.`
); );
} }
} }
if (valid && tokenItem) {
return allowed(res);
}
} }
if (!sessions) { if (!sessions) {
@ -321,16 +372,6 @@ export async function verifyResourceSession(
} }
} }
// At this point we have checked all sessions, but since the access token is
// valid, we should allow access and create a new session.
if (validAccessToken) {
return await createAccessTokenSession(
res,
resource,
validAccessToken
);
}
logger.debug("No more auth to check, resource not allowed"); logger.debug("No more auth to check, resource not allowed");
if (config.getRawConfig().app.log_failed_attempts) { if (config.getRawConfig().app.log_failed_attempts) {
@ -360,8 +401,7 @@ function extractResourceSessionToken(
ssl ? "_s" : "" ssl ? "_s" : ""
}`; }`;
const all: { cookieName: string; token: string; priority: number }[] = const all: { cookieName: string; token: string; priority: number }[] = [];
[];
for (const [key, value] of Object.entries(sessions)) { for (const [key, value] of Object.entries(sessions)) {
const parts = key.split("."); const parts = key.split(".");

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { domains, orgDomains, users } from "@server/db/schema"; import { domains, orgDomains, users } from "@server/db/schemas";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
@ -80,15 +80,15 @@ export async function listDomains(
const { orgId } = parsedParams.data; const { orgId } = parsedParams.data;
const domains = await queryDomains(orgId.toString(), limit, offset); const domainsList = await queryDomains(orgId.toString(), limit, offset);
const [{ count }] = await db const [{ count }] = await db
.select({ count: sql<number>`count(*)` }) .select({ count: sql<number>`count(*)` })
.from(users); .from(domains);
return response<ListDomainsResponse>(res, { return response<ListDomainsResponse>(res, {
data: { data: {
domains, domains: domainsList,
pagination: { pagination: {
total: count, total: count,
limit, limit,

View file

@ -383,7 +383,10 @@ authenticated.get(
authenticated.get(`/org/:orgId/overview`, verifyOrgAccess, org.getOrgOverview); authenticated.get(`/org/:orgId/overview`, verifyOrgAccess, org.getOrgOverview);
authenticated.post(`/supporter-key/validate`, supporterKey.validateSupporterKey); authenticated.post(
`/supporter-key/validate`,
supporterKey.validateSupporterKey
);
authenticated.post(`/supporter-key/hide`, supporterKey.hideSupporterKey); authenticated.post(`/supporter-key/hide`, supporterKey.hideSupporterKey);
unauthenticated.get("/resource/:resourceId/auth", resource.getResourceAuthInfo); unauthenticated.get("/resource/:resourceId/auth", resource.getResourceAuthInfo);
@ -470,7 +473,11 @@ authenticated.delete(
// role.removeRoleAction // role.removeRoleAction
// ); // );
authenticated.put("/newt", createNewt); // authenticated.put(
// "/newt",
// verifyUserHasAction(ActionsEnum.createNewt),
// createNewt
// );
// Auth routes // Auth routes
export const authRouter = Router(); export const authRouter = Router();
@ -559,3 +566,8 @@ authRouter.post(
"/resource/:resourceId/access-token", "/resource/:resourceId/access-token",
resource.authWithAccessToken resource.authWithAccessToken
); );
authRouter.post(
"/access-token",
resource.authWithAccessToken
);

View file

@ -1,6 +1,6 @@
import { Request, Response, NextFunction } from 'express'; import { Request, Response, NextFunction } from 'express';
import { z } from 'zod'; import { z } from 'zod';
import { sites, resources, targets, exitNodes } from '@server/db/schema'; import { sites, resources, targets, exitNodes } from '@server/db/schemas';
import { db } from '@server/db'; import { db } from '@server/db';
import { eq } from 'drizzle-orm'; import { eq } from 'drizzle-orm';
import response from "@server/lib/response"; import response from "@server/lib/response";

View file

@ -1,7 +1,7 @@
import axios from 'axios'; import axios from 'axios';
import logger from '@server/logger'; import logger from '@server/logger';
import db from '@server/db'; import db from '@server/db';
import { exitNodes } from '@server/db/schema'; import { exitNodes } from '@server/db/schemas';
import { eq } from 'drizzle-orm'; import { eq } from 'drizzle-orm';
export async function addPeer(exitNodeId: number, peer: { export async function addPeer(exitNodeId: number, peer: {

View file

@ -1,6 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { DrizzleError, eq } from "drizzle-orm"; import { DrizzleError, eq } from "drizzle-orm";
import { sites, resources, targets, exitNodes } from "@server/db/schema"; import { sites, resources, targets, exitNodes } from "@server/db/schemas";
import db from "@server/db"; import db from "@server/db";
import logger from "@server/logger"; import logger from "@server/logger";
import createHttpError from "http-errors"; import createHttpError from "http-errors";

View file

@ -3,7 +3,7 @@ import db from "@server/db";
import { hash } from "@node-rs/argon2"; import { hash } from "@node-rs/argon2";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import { z } from "zod"; import { z } from "zod";
import { newts } from "@server/db/schema"; import { newts } from "@server/db/schemas";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import response from "@server/lib/response"; import response from "@server/lib/response";
import { SqliteError } from "better-sqlite3"; import { SqliteError } from "better-sqlite3";

View file

@ -1,6 +1,6 @@
import { generateSessionToken } from "@server/auth/sessions/app"; import { generateSessionToken } from "@server/auth/sessions/app";
import db from "@server/db"; import db from "@server/db";
import { newts } from "@server/db/schema"; import { newts } from "@server/db/schemas";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import response from "@server/lib/response"; import response from "@server/lib/response";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";

View file

@ -6,7 +6,7 @@ import {
sites, sites,
Target, Target,
targets targets
} from "@server/db/schema"; } from "@server/db/schemas";
import { eq, and, sql, inArray } from "drizzle-orm"; import { eq, and, sql, inArray } from "drizzle-orm";
import { addPeer, deletePeer } from "../gerbil/peers"; import { addPeer, deletePeer } from "../gerbil/peers";
import logger from "@server/logger"; import logger from "@server/logger";

View file

@ -1,4 +1,4 @@
import { Target } from "@server/db/schema"; import { Target } from "@server/db/schemas";
import { sendToClient } from "../ws"; import { sendToClient } from "../ws";
export function addTargets( export function addTargets(

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { orgs } from "@server/db/schema"; import { orgs } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -10,7 +10,7 @@ import {
roleActions, roleActions,
roles, roles,
userOrgs userOrgs
} from "@server/db/schema"; } from "@server/db/schemas";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
@ -27,7 +27,7 @@ const createOrgSchema = z
}) })
.strict(); .strict();
const MAX_ORGS = 5; // const MAX_ORGS = 5;
export async function createOrg( export async function createOrg(
req: Request, req: Request,
@ -57,15 +57,15 @@ export async function createOrg(
); );
} }
const userOrgIds = req.userOrgIds; // const userOrgIds = req.userOrgIds;
if (userOrgIds && userOrgIds.length > MAX_ORGS) { // if (userOrgIds && userOrgIds.length > MAX_ORGS) {
return next( // return next(
createHttpError( // createHttpError(
HttpCode.FORBIDDEN, // HttpCode.FORBIDDEN,
`Maximum number of organizations reached.` // `Maximum number of organizations reached.`
) // )
); // );
} // }
const { orgId, name } = parsedBody.data; const { orgId, name } = parsedBody.data;

View file

@ -7,7 +7,7 @@ import {
orgs, orgs,
sites, sites,
userActions userActions
} from "@server/db/schema"; } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,12 +1,13 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { Org, orgs } from "@server/db/schema"; import { Org, orgs } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import logger from "@server/logger"; import logger from "@server/logger";
import { fromZodError } from "zod-validation-error";
const getOrgSchema = z const getOrgSchema = z
.object({ .object({
@ -29,7 +30,7 @@ export async function getOrg(
return next( return next(
createHttpError( createHttpError(
HttpCode.BAD_REQUEST, HttpCode.BAD_REQUEST,
parsedParams.error.errors.map((e) => e.message).join(", ") fromZodError(parsedParams.error)
) )
); );
} }

View file

@ -10,12 +10,13 @@ import {
userResources, userResources,
users, users,
userSites userSites
} from "@server/db/schema"; } from "@server/db/schemas";
import { and, count, eq, inArray } from "drizzle-orm"; import { and, count, eq, inArray } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import logger from "@server/logger"; import logger from "@server/logger";
import { fromZodError } from "zod-validation-error";
const getOrgParamsSchema = z const getOrgParamsSchema = z
.object({ .object({
@ -45,7 +46,7 @@ export async function getOrgOverview(
return next( return next(
createHttpError( createHttpError(
HttpCode.BAD_REQUEST, HttpCode.BAD_REQUEST,
parsedParams.error.errors.map((e) => e.message).join(", ") fromZodError(parsedParams.error)
) )
); );
} }

View file

@ -1,12 +1,13 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { Org, orgs } from "@server/db/schema"; import { Org, orgs } from "@server/db/schemas";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import { sql, inArray } from "drizzle-orm"; import { sql, inArray } from "drizzle-orm";
import logger from "@server/logger"; import logger from "@server/logger";
import { fromZodError } from "zod-validation-error";
const listOrgsSchema = z.object({ const listOrgsSchema = z.object({
limit: z limit: z
@ -39,7 +40,7 @@ export async function listOrgs(
return next( return next(
createHttpError( createHttpError(
HttpCode.BAD_REQUEST, HttpCode.BAD_REQUEST,
parsedQuery.error.errors.map((e) => e.message).join(", ") fromZodError(parsedQuery.error)
) )
); );
} }

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { orgs } from "@server/db/schema"; import { orgs } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,6 +1,6 @@
import { generateSessionToken } from "@server/auth/sessions/app"; import { generateSessionToken } from "@server/auth/sessions/app";
import db from "@server/db"; import db from "@server/db";
import { resources } from "@server/db/schema"; import { Resource, resources } from "@server/db/schemas";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import response from "@server/lib/response"; import response from "@server/lib/response";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
@ -10,13 +10,16 @@ import { z } from "zod";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { createResourceSession } from "@server/auth/sessions/resource"; import { createResourceSession } from "@server/auth/sessions/resource";
import logger from "@server/logger"; import logger from "@server/logger";
import { verifyResourceAccessToken } from "@server/auth/verifyResourceAccessToken"; import {
verifyResourceAccessToken
} from "@server/auth/verifyResourceAccessToken";
import config from "@server/lib/config"; import config from "@server/lib/config";
import stoi from "@server/lib/stoi";
const authWithAccessTokenBodySchema = z const authWithAccessTokenBodySchema = z
.object({ .object({
accessToken: z.string(), accessToken: z.string(),
accessTokenId: z.string() accessTokenId: z.string().optional()
}) })
.strict(); .strict();
@ -24,13 +27,15 @@ const authWithAccessTokenParamsSchema = z
.object({ .object({
resourceId: z resourceId: z
.string() .string()
.transform(Number) .optional()
.pipe(z.number().int().positive()) .transform(stoi)
.pipe(z.number().int().positive().optional())
}) })
.strict(); .strict();
export type AuthWithAccessTokenResponse = { export type AuthWithAccessTokenResponse = {
session?: string; session?: string;
redirectUrl?: string | null;
}; };
export async function authWithAccessToken( export async function authWithAccessToken(
@ -64,24 +69,62 @@ export async function authWithAccessToken(
const { accessToken, accessTokenId } = parsedBody.data; const { accessToken, accessTokenId } = parsedBody.data;
try { try {
const [resource] = await db let valid;
let tokenItem;
let error;
let resource: Resource | undefined;
if (accessTokenId) {
if (!resourceId) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Resource ID is required"
)
);
}
const [foundResource] = await db
.select() .select()
.from(resources) .from(resources)
.where(eq(resources.resourceId, resourceId)) .where(eq(resources.resourceId, resourceId))
.limit(1); .limit(1);
if (!resource) { if (!foundResource) {
return next( return next(
createHttpError(HttpCode.NOT_FOUND, "Resource not found") createHttpError(HttpCode.NOT_FOUND, "Resource not found")
); );
} }
const { valid, error, tokenItem } = await verifyResourceAccessToken({ const res = await verifyResourceAccessToken({
resource,
accessTokenId, accessTokenId,
accessToken accessToken
}); });
valid = res.valid;
tokenItem = res.tokenItem;
error = res.error;
resource = foundResource;
} else {
const res = await verifyResourceAccessToken({
accessToken
});
valid = res.valid;
tokenItem = res.tokenItem;
error = res.error;
resource = res.resource;
}
if (!tokenItem || !resource) {
return next(
createHttpError(
HttpCode.UNAUTHORIZED,
"Access token does not exist for resource"
)
);
}
if (!valid) { if (!valid) {
if (config.getRawConfig().app.log_failed_attempts) { if (config.getRawConfig().app.log_failed_attempts) {
logger.info( logger.info(
@ -96,18 +139,9 @@ export async function authWithAccessToken(
); );
} }
if (!tokenItem || !resource) {
return next(
createHttpError(
HttpCode.UNAUTHORIZED,
"Access token does not exist for resource"
)
);
}
const token = generateSessionToken(); const token = generateSessionToken();
await createResourceSession({ await createResourceSession({
resourceId, resourceId: resource.resourceId,
token, token,
accessTokenId: tokenItem.accessTokenId, accessTokenId: tokenItem.accessTokenId,
isRequestToken: true, isRequestToken: true,
@ -118,7 +152,8 @@ export async function authWithAccessToken(
return response<AuthWithAccessTokenResponse>(res, { return response<AuthWithAccessTokenResponse>(res, {
data: { data: {
session: token session: token,
redirectUrl: `${resource.ssl ? "https" : "http"}://${resource.fullDomain}`
}, },
success: true, success: true,
error: false, error: false,

View file

@ -1,7 +1,7 @@
import { verify } from "@node-rs/argon2"; import { verify } from "@node-rs/argon2";
import { generateSessionToken } from "@server/auth/sessions/app"; import { generateSessionToken } from "@server/auth/sessions/app";
import db from "@server/db"; import db from "@server/db";
import { orgs, resourcePassword, resources } from "@server/db/schema"; import { orgs, resourcePassword, resources } from "@server/db/schemas";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import response from "@server/lib/response"; import response from "@server/lib/response";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";

View file

@ -1,6 +1,6 @@
import { generateSessionToken } from "@server/auth/sessions/app"; import { generateSessionToken } from "@server/auth/sessions/app";
import db from "@server/db"; import db from "@server/db";
import { orgs, resourcePincode, resources } from "@server/db/schema"; import { orgs, resourcePincode, resources } from "@server/db/schemas";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import response from "@server/lib/response"; import response from "@server/lib/response";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";

View file

@ -5,7 +5,7 @@ import {
resourceOtp, resourceOtp,
resources, resources,
resourceWhitelist resourceWhitelist
} from "@server/db/schema"; } from "@server/db/schemas";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import response from "@server/lib/response"; import response from "@server/lib/response";
import { eq, and } from "drizzle-orm"; import { eq, and } from "drizzle-orm";

View file

@ -10,7 +10,7 @@ import {
roleResources, roleResources,
roles, roles,
userResources userResources
} from "@server/db/schema"; } from "@server/db/schemas";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { resourceRules, resources } from "@server/db/schema"; import { resourceRules, resources } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { newts, resources, sites, targets } from "@server/db/schema"; import { newts, resources, sites, targets } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { resourceRules, resources } from "@server/db/schema"; import { resourceRules, resources } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { resources } from "@server/db/schema"; import { resources } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { createResourceSession } from "@server/auth/sessions/resource"; import { createResourceSession } from "@server/auth/sessions/resource";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { Resource, resources, sites } from "@server/db/schema"; import { Resource, resources, sites } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -5,7 +5,7 @@ import {
resourcePassword, resourcePassword,
resourcePincode, resourcePincode,
resources resources
} from "@server/db/schema"; } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { resourceWhitelist, users } from "@server/db/schema"; // Assuming these are the correct tables import { resourceWhitelist, users } from "@server/db/schemas"; // Assuming these are the correct tables
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { roleResources, roles } from "@server/db/schema"; import { roleResources, roles } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,5 +1,5 @@
import { db } from "@server/db"; import { db } from "@server/db";
import { resourceRules, resources } from "@server/db/schema"; import { resourceRules, resources } from "@server/db/schemas";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import response from "@server/lib/response"; import response from "@server/lib/response";
import { eq, sql } from "drizzle-orm"; import { eq, sql } from "drizzle-orm";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { userResources, users } from "@server/db/schema"; // Assuming these are the correct tables import { userResources, users } from "@server/db/schemas"; // Assuming these are the correct tables
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -8,13 +8,14 @@ import {
roleResources, roleResources,
resourcePassword, resourcePassword,
resourcePincode resourcePincode
} from "@server/db/schema"; } from "@server/db/schemas";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import { sql, eq, or, inArray, and, count } from "drizzle-orm"; import { sql, eq, or, inArray, and, count } from "drizzle-orm";
import logger from "@server/logger"; import logger from "@server/logger";
import stoi from "@server/lib/stoi"; import stoi from "@server/lib/stoi";
import { fromZodError } from "zod-validation-error";
const listResourcesParamsSchema = z const listResourcesParamsSchema = z
.object({ .object({
@ -66,7 +67,8 @@ function queryResources(
whitelist: resources.emailWhitelistEnabled, whitelist: resources.emailWhitelistEnabled,
http: resources.http, http: resources.http,
protocol: resources.protocol, protocol: resources.protocol,
proxyPort: resources.proxyPort proxyPort: resources.proxyPort,
enabled: resources.enabled
}) })
.from(resources) .from(resources)
.leftJoin(sites, eq(resources.siteId, sites.siteId)) .leftJoin(sites, eq(resources.siteId, sites.siteId))
@ -99,7 +101,8 @@ function queryResources(
whitelist: resources.emailWhitelistEnabled, whitelist: resources.emailWhitelistEnabled,
http: resources.http, http: resources.http,
protocol: resources.protocol, protocol: resources.protocol,
proxyPort: resources.proxyPort proxyPort: resources.proxyPort,
enabled: resources.enabled
}) })
.from(resources) .from(resources)
.leftJoin(sites, eq(resources.siteId, sites.siteId)) .leftJoin(sites, eq(resources.siteId, sites.siteId))
@ -136,7 +139,7 @@ export async function listResources(
return next( return next(
createHttpError( createHttpError(
HttpCode.BAD_REQUEST, HttpCode.BAD_REQUEST,
parsedQuery.error.errors.map((e) => e.message).join(", ") fromZodError(parsedQuery.error)
) )
); );
} }
@ -147,7 +150,7 @@ export async function listResources(
return next( return next(
createHttpError( createHttpError(
HttpCode.BAD_REQUEST, HttpCode.BAD_REQUEST,
parsedParams.error.errors.map((e) => e.message).join(", ") fromZodError(parsedParams.error)
) )
); );
} }

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { resourcePassword } from "@server/db/schema"; import { resourcePassword } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { resourcePincode } from "@server/db/schema"; import { resourcePincode } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { roleResources, roles } from "@server/db/schema"; import { roleResources, roles } from "@server/db/schemas";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { userResources } from "@server/db/schema"; import { userResources } from "@server/db/schemas";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { resources, resourceWhitelist } from "@server/db/schema"; import { resources, resourceWhitelist } from "@server/db/schemas";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { newts, resources, sites, targets } from "@server/db/schema"; import { newts, resources, sites, targets } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -8,7 +8,7 @@ import {
orgs, orgs,
Resource, Resource,
resources resources
} from "@server/db/schema"; } from "@server/db/schemas";
import { eq, and } from "drizzle-orm"; import { eq, and } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
@ -39,7 +39,8 @@ const updateHttpResourceBodySchema = z
emailWhitelistEnabled: z.boolean().optional(), emailWhitelistEnabled: z.boolean().optional(),
isBaseDomain: z.boolean().optional(), isBaseDomain: z.boolean().optional(),
applyRules: z.boolean().optional(), applyRules: z.boolean().optional(),
domainId: z.string().optional() domainId: z.string().optional(),
enabled: z.boolean().optional()
}) })
.strict() .strict()
.refine((data) => Object.keys(data).length > 0, { .refine((data) => Object.keys(data).length > 0, {
@ -73,7 +74,8 @@ export type UpdateResourceResponse = Resource;
const updateRawResourceBodySchema = z const updateRawResourceBodySchema = z
.object({ .object({
name: z.string().min(1).max(255).optional(), name: z.string().min(1).max(255).optional(),
proxyPort: z.number().int().min(1).max(65535).optional() proxyPort: z.number().int().min(1).max(65535).optional(),
enabled: z.boolean().optional()
}) })
.strict() .strict()
.refine((data) => Object.keys(data).length > 0, { .refine((data) => Object.keys(data).length > 0, {

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { resourceRules, resources } from "@server/db/schema"; import { resourceRules, resources } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { roleActions, roles } from "@server/db/schema"; import { roleActions, roles } from "@server/db/schemas";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { resources, roleResources, roleSites } from "@server/db/schema"; import { resources, roleResources, roleSites } from "@server/db/schemas";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { orgs, Role, roleActions, roles } from "@server/db/schema"; import { orgs, Role, roleActions, roles } from "@server/db/schemas";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { roles, userOrgs } from "@server/db/schema"; import { roles, userOrgs } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { roles } from "@server/db/schema"; import { roles } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { roleActions, actions } from "@server/db/schema"; import { roleActions, actions } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db } from "@server/db"; import { db } from "@server/db";
import { roleResources, resources } from "@server/db/schema"; import { roleResources, resources } from "@server/db/schemas";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";

Some files were not shown because too many files have changed in this diff Show more