Fix authentication errors by improving authorization middleware and Docker deployment.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 705f2157-ef97-4fbd-89e4-8c7f2ecaea90
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7ed01c5f-a82d-405a-b728-b2e3d127c60c/29c4139d-db30-4851-8296-3b0c9c5c6466.jpg
This commit is contained in:
alphaeusmote
2025-04-08 20:56:46 +00:00
parent 69c5c814a7
commit bcb0a6279f
7 changed files with 5 additions and 1488 deletions
+4 -18
View File
@@ -10,25 +10,11 @@ import { connectToLdap, searchLdap, getLdapAvailableAttributes } from "./ldap";
import { IStorage } from "./storage";
import { InsertLdapQuery, LdapQuery, InsertLdapQueryVersion } from "@shared/schema";
// Use middleware to check permissions
import { requirePermission } from "./authorization";
// Use the proper auth middleware from authorization.ts with option to allow API tokens
function hasPermission(permission: string) {
return (req: any, res: any, next: any) => {
// Check if the user is authenticated via passport session or has a valid API token
if (
// Check for authenticated session (safely check if isAuthenticated is a function first)
(typeof req.isAuthenticated === 'function' && req.isAuthenticated()) ||
// Or check for existing user object (set by token auth)
req.user ||
// Or check for authorization header (token auth)
req.headers.authorization
) {
// In a real implementation, this would check the user's permissions against the required permission
return next();
}
// If not authenticated, return 401 Unauthorized
return res.status(401).json({ error: "Unauthorized" });
};
return requirePermission(permission, { allowApiToken: true });
}
export function registerLdapQueryBuilderRoutes(router: Router, storage: IStorage) {
-556
View File
@@ -1,556 +0,0 @@
import { Router } from "express";
import {
validateQueryBuilder,
generateLdapFilter,
getHumanReadableFilter,
buildLdapFilter,
LdapQueryBuilder
} from "./ldap-filter-builder";
import { connectToLdap, searchLdap } from "./ldap";
import { IStorage } from "./storage";
import { InsertLdapQuery, LdapQuery, InsertLdapQueryVersion } from "@shared/schema";
// Use middleware to check permissions
function hasPermission(permission: string) {
return (req: any, res: any, next: any) => {
// For now, we'll just allow all requests through
// In a real implementation, this would check the user's permissions
return next();
};
}
export function registerLdapQueryBuilderRoutes(router: Router, storage: IStorage) {
/**
* @swagger
* /ldap-queries:
* get:
* summary: Get all saved LDAP queries
* description: Retrieve a list of all saved LDAP query filters
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: A list of LDAP queries
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: '#/components/schemas/LdapQuery'
*/
router.get("/ldap-queries", hasPermission("read:ldap_queries"), async (req, res) => {
try {
const queries = await storage.getLdapQueries();
res.json(queries);
} catch (error) {
console.error("Error getting LDAP queries:", error);
res.status(500).json({ error: "Failed to retrieve LDAP queries" });
}
});
/**
* @swagger
* /ldap-queries/{id}:
* get:
* summary: Get a saved LDAP query by ID
* description: Retrieve a specific LDAP query filter by its ID
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: Query ID
* responses:
* 200:
* description: LDAP query found
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/LdapQuery'
* 404:
* description: Query not found
*/
router.get("/ldap-queries/:id", hasPermission("read:ldap_queries"), async (req, res) => {
try {
const id = parseInt(req.params.id);
if (isNaN(id)) {
return res.status(400).json({ error: "Invalid query ID" });
}
const query = await storage.getLdapQueryById(id);
if (!query) {
return res.status(404).json({ error: "LDAP query not found" });
}
res.json(query);
} catch (error) {
console.error("Error getting LDAP query:", error);
res.status(500).json({ error: "Failed to retrieve LDAP query" });
}
});
/**
* @swagger
* /ldap-queries/{id}/versions:
* get:
* summary: Get version history for an LDAP query
* description: Retrieve the revision history for a specific LDAP query
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: Query ID
* responses:
* 200:
* description: List of query versions
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: '#/components/schemas/LdapQueryVersion'
* 404:
* description: Query not found
*/
router.get("/ldap-queries/:id/versions", hasPermission("read:ldap_queries"), async (req, res) => {
try {
const id = parseInt(req.params.id);
if (isNaN(id)) {
return res.status(400).json({ error: "Invalid query ID" });
}
const query = await storage.getLdapQueryById(id);
if (!query) {
return res.status(404).json({ error: "LDAP query not found" });
}
const versions = await storage.getLdapQueryVersions(id);
res.json(versions);
} catch (error) {
console.error("Error getting LDAP query versions:", error);
res.status(500).json({ error: "Failed to retrieve LDAP query versions" });
}
});
/**
* @swagger
* /ldap-queries:
* post:
* summary: Create a new LDAP query
* description: Save a new LDAP query filter
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* name:
* type: string
* description:
* type: string
* targetObject:
* type: string
* enum: [users, groups, computers, ous]
* filter:
* type: object
* responses:
* 201:
* description: Query created successfully
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/LdapQuery'
* 400:
* description: Invalid query format
*/
router.post("/ldap-queries", hasPermission("write:ldap_queries"), async (req, res) => {
try {
const { name, description, targetObject, filter } = req.body;
if (!name || !targetObject || !filter) {
return res.status(400).json({ error: "Missing required fields: name, targetObject, filter" });
}
try {
// Validate the filter format
const queryBuilder = validateQueryBuilder({ targetObject, filter });
// Generate the LDAP filter and readable representation
const ldapFilter = generateLdapFilter(queryBuilder);
const readableFilter = getHumanReadableFilter(queryBuilder.filter);
const insertQuery: InsertLdapQuery = {
name,
description: description || "",
targetObject,
filterJson: filter,
ldapFilter,
readableFilter,
createdBy: req.user?.id || null,
};
const query = await storage.createLdapQuery(insertQuery);
res.status(201).json(query);
} catch (error) {
console.error("Error validating query:", error);
return res.status(400).json({ error: "Invalid query format", details: error.message });
}
} catch (error) {
console.error("Error creating LDAP query:", error);
res.status(500).json({ error: "Failed to create LDAP query" });
}
});
/**
* @swagger
* /ldap-queries/{id}:
* put:
* summary: Update an LDAP query
* description: Update an existing LDAP query and create a new version
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: Query ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* name:
* type: string
* description:
* type: string
* targetObject:
* type: string
* enum: [users, groups, computers, ous]
* filter:
* type: object
* responses:
* 200:
* description: Query updated successfully
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/LdapQuery'
* 400:
* description: Invalid query format
* 404:
* description: Query not found
*/
router.put("/ldap-queries/:id", hasPermission("write:ldap_queries"), async (req, res) => {
try {
const id = parseInt(req.params.id);
if (isNaN(id)) {
return res.status(400).json({ error: "Invalid query ID" });
}
const { name, description, targetObject, filter } = req.body;
if (!name || !targetObject || !filter) {
return res.status(400).json({ error: "Missing required fields: name, targetObject, filter" });
}
// Check if query exists
const existingQuery = await storage.getLdapQueryById(id);
if (!existingQuery) {
return res.status(404).json({ error: "LDAP query not found" });
}
try {
// Validate the filter format
const queryBuilder = validateQueryBuilder({ targetObject, filter });
// Generate the LDAP filter and readable representation
const ldapFilter = generateLdapFilter(queryBuilder);
const readableFilter = getHumanReadableFilter(queryBuilder.filter);
// Create a version entry for the previous state
const versionEntry: InsertLdapQueryVersion = {
queryId: id,
version: existingQuery.version,
filterJson: existingQuery.filterJson as any, // Type safety is handled by schema validation
ldapFilter: existingQuery.ldapFilter,
readableFilter: existingQuery.readableFilter,
targetObject: existingQuery.targetObject,
createdBy: existingQuery.createdBy,
createdAt: existingQuery.createdAt
};
await storage.createLdapQueryVersion(versionEntry);
// Update the query with new values
const updatedQuery = await storage.updateLdapQuery(id, {
name,
description: description || "",
targetObject,
filterJson: filter,
ldapFilter,
readableFilter,
updatedBy: req.user?.id || null,
version: existingQuery.version + 1
});
res.status(200).json(updatedQuery);
} catch (error) {
console.error("Error validating query:", error);
return res.status(400).json({ error: "Invalid query format", details: error.message });
}
} catch (error) {
console.error("Error updating LDAP query:", error);
res.status(500).json({ error: "Failed to update LDAP query" });
}
});
/**
* @swagger
* /ldap-queries/{id}:
* delete:
* summary: Delete an LDAP query
* description: Delete an LDAP query and all its versions
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: Query ID
* responses:
* 204:
* description: Query deleted successfully
* 404:
* description: Query not found
*/
router.delete("/ldap-queries/:id", hasPermission("delete:ldap_queries"), async (req, res) => {
try {
const id = parseInt(req.params.id);
if (isNaN(id)) {
return res.status(400).json({ error: "Invalid query ID" });
}
// Check if query exists
const existingQuery = await storage.getLdapQueryById(id);
if (!existingQuery) {
return res.status(404).json({ error: "LDAP query not found" });
}
// Delete all versions and the query itself
await storage.deleteLdapQueryVersions(id);
await storage.deleteLdapQuery(id);
res.status(204).send();
} catch (error) {
console.error("Error deleting LDAP query:", error);
res.status(500).json({ error: "Failed to delete LDAP query" });
}
});
/**
* @swagger
* /ldap-queries/{id}/revert/{version}:
* post:
* summary: Revert to a previous version
* description: Revert an LDAP query to a specific previous version
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: Query ID
* - in: path
* name: version
* required: true
* schema:
* type: integer
* description: Version to revert to
* responses:
* 200:
* description: Query reverted successfully
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/LdapQuery'
* 404:
* description: Query or version not found
*/
router.post("/ldap-queries/:id/revert/:version", hasPermission("write:ldap_queries"), async (req, res) => {
try {
const id = parseInt(req.params.id);
const version = parseInt(req.params.version);
if (isNaN(id) || isNaN(version)) {
return res.status(400).json({ error: "Invalid query ID or version" });
}
// Check if query exists
const existingQuery = await storage.getLdapQueryById(id);
if (!existingQuery) {
return res.status(404).json({ error: "LDAP query not found" });
}
// Find the version to revert to
const versionToRevert = await storage.getLdapQueryVersion(id, version);
if (!versionToRevert) {
return res.status(404).json({ error: "Version not found" });
}
// Create a version entry for the current state
const versionEntry: InsertLdapQueryVersion = {
queryId: id,
version: existingQuery.version,
filterJson: existingQuery.filterJson as any, // Type safety is handled by schema validation
ldapFilter: existingQuery.ldapFilter,
readableFilter: existingQuery.readableFilter,
targetObject: existingQuery.targetObject,
createdBy: existingQuery.createdBy,
createdAt: existingQuery.createdAt
};
await storage.createLdapQueryVersion(versionEntry);
// Update the query with the version's values
const updatedQuery = await storage.updateLdapQuery(id, {
targetObject: versionToRevert.targetObject,
filterJson: versionToRevert.filterJson,
ldapFilter: versionToRevert.ldapFilter,
readableFilter: versionToRevert.readableFilter,
updatedBy: req.user?.id || null,
version: existingQuery.version + 1
});
res.status(200).json(updatedQuery);
} catch (error) {
console.error("Error reverting LDAP query:", error);
res.status(500).json({ error: "Failed to revert LDAP query" });
}
});
/**
* @swagger
* /ldap-queries/test:
* post:
* summary: Test an LDAP query filter
* description: Test a filter against an LDAP connection to see what objects would be returned
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* connectionId:
* type: integer
* targetObject:
* type: string
* enum: [users, groups, computers, ous]
* filter:
* type: object
* limit:
* type: integer
* default: 100
* properties:
* type: array
* items:
* type: string
* responses:
* 200:
* description: Query results
* content:
* application/json:
* schema:
* type: object
* properties:
* count:
* type: integer
* results:
* type: array
* items:
* type: object
* filter:
* type: string
* 400:
* description: Invalid query or connection
* 404:
* description: Connection not found
*/
router.post("/ldap-queries/test", hasPermission("read:ldap_objects"), async (req, res) => {
try {
const { connectionId, targetObject, filter, limit = 100, properties = [] } = req.body;
if (!connectionId || !targetObject || !filter) {
return res.status(400).json({ error: "Missing required fields: connectionId, targetObject, filter" });
}
// Get the connection
const connection = await storage.getLdapConnectionById(connectionId);
if (!connection) {
return res.status(404).json({ error: "LDAP connection not found" });
}
// Validate and generate the filter
let ldapFilter: string;
try {
const queryBuilder = validateQueryBuilder({ targetObject, filter });
ldapFilter = generateLdapFilter(queryBuilder);
} catch (error) {
return res.status(400).json({ error: "Invalid filter format", details: error.message });
}
// Connect to LDAP
const client = await connectToLdap(connection);
try {
// Execute the search
const results = await searchLdap(client, {
filter: ldapFilter,
attributes: properties.length > 0 ? properties : undefined,
limit
});
// Return the results
res.json({
count: results.length,
results,
filter: ldapFilter
});
} finally {
// Always destroy the client
client.destroy();
}
} catch (error) {
console.error("Error testing LDAP query:", error);
res.status(500).json({ error: "Failed to test LDAP query", details: error.message });
}
});
}
-558
View File
@@ -1,558 +0,0 @@
import { Router } from "express";
import {
validateQueryBuilder,
generateLdapFilter,
getHumanReadableFilter,
buildLdapFilter,
LdapQueryBuilder
} from "./ldap-filter-builder";
import { connectToLdap, searchLdap } from "./ldap";
import { IStorage } from "./storage";
import { InsertLdapQuery, LdapQuery, InsertLdapQueryVersion } from "@shared/schema";
// Use middleware to check permissions
function hasPermission(permission: string) {
return (req: any, res: any, next: any) => {
// For now, we'll just allow all requests through
// In a real implementation, this would check the user's permissions
return next();
};
}
export function registerLdapQueryBuilderRoutes(router: Router, storage: IStorage) {
/**
* @swagger
* /ldap-queries:
* get:
* summary: Get all saved LDAP queries
* description: Retrieve a list of all saved LDAP query filters
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: A list of LDAP queries
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: '#/components/schemas/LdapQuery'
*/
router.get("/ldap-queries", hasPermission("read:ldap_queries"), async (req, res) => {
try {
const queries = await storage.getLdapQueries();
res.json(queries);
} catch (error) {
console.error("Error getting LDAP queries:", error);
res.status(500).json({ error: "Failed to retrieve LDAP queries" });
}
});
/**
* @swagger
* /ldap-queries/{id}:
* get:
* summary: Get a saved LDAP query by ID
* description: Retrieve a specific LDAP query filter by its ID
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: Query ID
* responses:
* 200:
* description: LDAP query found
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/LdapQuery'
* 404:
* description: Query not found
*/
router.get("/ldap-queries/:id", hasPermission("read:ldap_queries"), async (req, res) => {
try {
const id = parseInt(req.params.id);
if (isNaN(id)) {
return res.status(400).json({ error: "Invalid query ID" });
}
const query = await storage.getLdapQuery(id);
if (!query) {
return res.status(404).json({ error: "LDAP query not found" });
}
res.json(query);
} catch (error) {
console.error("Error getting LDAP query:", error);
res.status(500).json({ error: "Failed to retrieve LDAP query" });
}
});
/**
* @swagger
* /ldap-queries/{id}/versions:
* get:
* summary: Get version history for an LDAP query
* description: Retrieve the revision history for a specific LDAP query
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: Query ID
* responses:
* 200:
* description: List of query versions
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: '#/components/schemas/LdapQueryVersion'
* 404:
* description: Query not found
*/
router.get("/ldap-queries/:id/versions", hasPermission("read:ldap_queries"), async (req, res) => {
try {
const id = parseInt(req.params.id);
if (isNaN(id)) {
return res.status(400).json({ error: "Invalid query ID" });
}
const query = await storage.getLdapQuery(id);
if (!query) {
return res.status(404).json({ error: "LDAP query not found" });
}
const versions = await storage.getLdapQueryVersions(id);
res.json(versions);
} catch (error) {
console.error("Error getting LDAP query versions:", error);
res.status(500).json({ error: "Failed to retrieve LDAP query versions" });
}
});
/**
* @swagger
* /ldap-queries:
* post:
* summary: Create a new LDAP query
* description: Save a new LDAP query filter
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* name:
* type: string
* description:
* type: string
* targetObject:
* type: string
* enum: [users, groups, computers, ous]
* filter:
* type: object
* responses:
* 201:
* description: Query created successfully
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/LdapQuery'
* 400:
* description: Invalid query format
*/
router.post("/ldap-queries", hasPermission("write:ldap_queries"), async (req, res) => {
try {
const { name, description, targetObject, filter } = req.body;
if (!name || !targetObject || !filter) {
return res.status(400).json({ error: "Missing required fields: name, targetObject, filter" });
}
try {
// Validate the filter format
const queryBuilder = validateQueryBuilder({ targetObject, filter });
// Generate the LDAP filter and readable representation
const ldapFilter = generateLdapFilter(queryBuilder);
const readableFilter = getHumanReadableFilter(queryBuilder.filter);
const insertQuery: InsertLdapQuery = {
name,
description: description || "",
targetObject,
filterJson: filter as any, // Type safety is handled by schema validation
ldapFilter,
readableFilter,
createdBy: req.user?.id || 1, // Default to 1 if no user
};
const query = await storage.createLdapQuery(insertQuery);
res.status(201).json(query);
} catch (error: any) {
console.error("Error validating query:", error);
return res.status(400).json({ error: "Invalid query format", details: error.message });
}
} catch (error) {
console.error("Error creating LDAP query:", error);
res.status(500).json({ error: "Failed to create LDAP query" });
}
});
/**
* @swagger
* /ldap-queries/{id}:
* put:
* summary: Update an LDAP query
* description: Update an existing LDAP query and create a new version
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: Query ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* name:
* type: string
* description:
* type: string
* targetObject:
* type: string
* enum: [users, groups, computers, ous]
* filter:
* type: object
* responses:
* 200:
* description: Query updated successfully
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/LdapQuery'
* 400:
* description: Invalid query format
* 404:
* description: Query not found
*/
router.put("/ldap-queries/:id", hasPermission("write:ldap_queries"), async (req, res) => {
try {
const id = parseInt(req.params.id);
if (isNaN(id)) {
return res.status(400).json({ error: "Invalid query ID" });
}
const { name, description, targetObject, filter } = req.body;
if (!name || !targetObject || !filter) {
return res.status(400).json({ error: "Missing required fields: name, targetObject, filter" });
}
// Check if query exists
const existingQuery = await storage.getLdapQuery(id);
if (!existingQuery) {
return res.status(404).json({ error: "LDAP query not found" });
}
try {
// Validate the filter format
const queryBuilder = validateQueryBuilder({ targetObject, filter });
// Generate the LDAP filter and readable representation
const ldapFilter = generateLdapFilter(queryBuilder);
const readableFilter = getHumanReadableFilter(queryBuilder.filter);
// Create a version entry for the previous state
const versionEntry: InsertLdapQueryVersion = {
queryId: id,
version: existingQuery.version,
filterJson: existingQuery.filterJson as any, // Type safety is handled by schema validation
ldapFilter: existingQuery.ldapFilter,
readableFilter: existingQuery.readableFilter,
targetObject: existingQuery.targetObject,
createdBy: existingQuery.createdBy,
createdAt: existingQuery.createdAt
};
await storage.createLdapQueryVersion(versionEntry);
// Update the query with new values
const updatedQuery = await storage.updateLdapQuery(id, {
name,
description: description || "",
targetObject,
filterJson: filter as any,
ldapFilter,
readableFilter,
updatedBy: req.user?.id || 1, // Default to 1 if no user
version: existingQuery.version + 1
});
res.status(200).json(updatedQuery);
} catch (error: any) {
console.error("Error validating query:", error);
return res.status(400).json({ error: "Invalid query format", details: error.message });
}
} catch (error) {
console.error("Error updating LDAP query:", error);
res.status(500).json({ error: "Failed to update LDAP query" });
}
});
/**
* @swagger
* /ldap-queries/{id}:
* delete:
* summary: Delete an LDAP query
* description: Delete an LDAP query and all its versions
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: Query ID
* responses:
* 204:
* description: Query deleted successfully
* 404:
* description: Query not found
*/
router.delete("/ldap-queries/:id", hasPermission("delete:ldap_queries"), async (req, res) => {
try {
const id = parseInt(req.params.id);
if (isNaN(id)) {
return res.status(400).json({ error: "Invalid query ID" });
}
// Check if query exists
const existingQuery = await storage.getLdapQuery(id);
if (!existingQuery) {
return res.status(404).json({ error: "LDAP query not found" });
}
// Delete the query - versions will be deleted via cascading foreign key constraints
await storage.deleteLdapQuery(id);
res.status(204).send();
} catch (error) {
console.error("Error deleting LDAP query:", error);
res.status(500).json({ error: "Failed to delete LDAP query" });
}
});
/**
* @swagger
* /ldap-queries/{id}/revert/{version}:
* post:
* summary: Revert to a previous version
* description: Revert an LDAP query to a specific previous version
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: Query ID
* - in: path
* name: version
* required: true
* schema:
* type: integer
* description: Version to revert to
* responses:
* 200:
* description: Query reverted successfully
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/LdapQuery'
* 404:
* description: Query or version not found
*/
router.post("/ldap-queries/:id/revert/:version", hasPermission("write:ldap_queries"), async (req, res) => {
try {
const id = parseInt(req.params.id);
const versionNumber = parseInt(req.params.version);
if (isNaN(id) || isNaN(versionNumber)) {
return res.status(400).json({ error: "Invalid query ID or version" });
}
// Check if query exists
const existingQuery = await storage.getLdapQuery(id);
if (!existingQuery) {
return res.status(404).json({ error: "LDAP query not found" });
}
// Find the version to revert to - we need to get all versions and find the matching one
const allVersions = await storage.getLdapQueryVersions(id);
const versionToRevert = allVersions.find(v => v.version === versionNumber);
if (!versionToRevert) {
return res.status(404).json({ error: "Version not found" });
}
// Create a version entry for the current state
const versionEntry: InsertLdapQueryVersion = {
queryId: id,
version: existingQuery.version,
filterJson: existingQuery.filterJson as any, // Type safety is handled by schema validation
ldapFilter: existingQuery.ldapFilter,
readableFilter: existingQuery.readableFilter,
targetObject: existingQuery.targetObject,
createdBy: existingQuery.createdBy,
createdAt: existingQuery.createdAt
};
await storage.createLdapQueryVersion(versionEntry);
// Update the query with the version's values
const updatedQuery = await storage.updateLdapQuery(id, {
targetObject: versionToRevert.targetObject,
filterJson: versionToRevert.filterJson as any,
ldapFilter: versionToRevert.ldapFilter,
readableFilter: versionToRevert.readableFilter,
updatedBy: req.user?.id || 1, // Default to 1 if no user
version: existingQuery.version + 1
});
res.status(200).json(updatedQuery);
} catch (error) {
console.error("Error reverting LDAP query:", error);
res.status(500).json({ error: "Failed to revert LDAP query" });
}
});
/**
* @swagger
* /ldap-queries/test:
* post:
* summary: Test an LDAP query filter
* description: Test a filter against an LDAP connection to see what objects would be returned
* tags: [LDAP Query Builder]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* connectionId:
* type: integer
* targetObject:
* type: string
* enum: [users, groups, computers, ous]
* filter:
* type: object
* limit:
* type: integer
* default: 100
* properties:
* type: array
* items:
* type: string
* responses:
* 200:
* description: Query results
* content:
* application/json:
* schema:
* type: object
* properties:
* count:
* type: integer
* results:
* type: array
* items:
* type: object
* filter:
* type: string
* 400:
* description: Invalid query or connection
* 404:
* description: Connection not found
*/
router.post("/ldap-queries/test", hasPermission("read:ldap_objects"), async (req, res) => {
try {
const { connectionId, targetObject, filter, limit = 100, properties = [] } = req.body;
if (!connectionId || !targetObject || !filter) {
return res.status(400).json({ error: "Missing required fields: connectionId, targetObject, filter" });
}
// Get the connection
const connection = await storage.getLdapConnection(connectionId);
if (!connection) {
return res.status(404).json({ error: "LDAP connection not found" });
}
// Validate and generate the filter
let ldapFilter: string;
try {
const queryBuilder = validateQueryBuilder({ targetObject, filter });
ldapFilter = generateLdapFilter(queryBuilder);
} catch (error: any) {
return res.status(400).json({ error: "Invalid filter format", details: error.message });
}
// Connect to LDAP
const client = await connectToLdap(connection);
try {
// Execute the search
const results = await searchLdap(client, {
filter: ldapFilter,
attributes: properties.length > 0 ? properties : undefined,
limit
});
// Return the results
res.json({
count: results.length,
results,
filter: ldapFilter
});
} finally {
// Always destroy the client
client.destroy();
}
} catch (error: any) {
console.error("Error testing LDAP query:", error);
res.status(500).json({ error: "Failed to test LDAP query", details: error.message });
}
});
}
+1 -4
View File
@@ -104,14 +104,11 @@ export interface IStorage {
updateAdDomain(id: number, domain: Partial<AdDomain>): Promise<AdDomain | undefined>;
deleteAdDomain(id: number): Promise<boolean>;
listAdDomains(connectionId: number, query?: any): Promise<AdDomain[]>;
// Session store
sessionStore: any;
}
// Database Storage implementation
export class DatabaseStorage implements IStorage {
sessionStore: any;
sessionStore: session.Store;
constructor() {
this.sessionStore = new PostgresStore({