mirror of
https://github.com/freedbygrace/ActiveDirectoryManager.git
synced 2026-08-20 15:23:15 +00:00
Add Active Directory domain management endpoints
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/6da449b3-15d3-4aed-9919-3557a9495525.jpg
This commit is contained in:
@@ -2571,6 +2571,57 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
* 404:
|
* 404:
|
||||||
* $ref: '#/components/responses/NotFoundError'
|
* $ref: '#/components/responses/NotFoundError'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/connections/{connectionId}/ad-domains:
|
||||||
|
* post:
|
||||||
|
* summary: Create a new Active Directory domain
|
||||||
|
* tags: [AD Domains]
|
||||||
|
* security:
|
||||||
|
* - cookieAuth: []
|
||||||
|
* - bearerAuth: []
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: connectionId
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: integer
|
||||||
|
* description: LDAP connection ID
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* required:
|
||||||
|
* - name
|
||||||
|
* - distinguishedName
|
||||||
|
* properties:
|
||||||
|
* name:
|
||||||
|
* type: string
|
||||||
|
* description: The name of the domain
|
||||||
|
* distinguishedName:
|
||||||
|
* type: string
|
||||||
|
* description: The distinguished name of the domain
|
||||||
|
* netBIOSName:
|
||||||
|
* type: string
|
||||||
|
* description: The NetBIOS name of the domain
|
||||||
|
* forestName:
|
||||||
|
* type: string
|
||||||
|
* description: The forest name for the domain
|
||||||
|
* responses:
|
||||||
|
* 201:
|
||||||
|
* description: Domain created successfully
|
||||||
|
* 400:
|
||||||
|
* description: Invalid input
|
||||||
|
* 401:
|
||||||
|
* description: Unauthorized
|
||||||
|
* 403:
|
||||||
|
* description: Forbidden
|
||||||
|
* 500:
|
||||||
|
* description: Server error
|
||||||
|
*/
|
||||||
app.get("/api/connections/:connectionId/ad-domains", async (req, res, next) => {
|
app.get("/api/connections/:connectionId/ad-domains", async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
if (!req.isAuthenticated() && !req.headers.authorization) {
|
if (!req.isAuthenticated() && !req.headers.authorization) {
|
||||||
@@ -2628,6 +2679,188 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/connections/{connectionId}/ad-domains/{objectGUID}:
|
||||||
|
* patch:
|
||||||
|
* summary: Update an Active Directory domain
|
||||||
|
* tags: [AD Domains]
|
||||||
|
* security:
|
||||||
|
* - cookieAuth: []
|
||||||
|
* - bearerAuth: []
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: connectionId
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: integer
|
||||||
|
* description: LDAP connection ID
|
||||||
|
* - in: path
|
||||||
|
* name: objectGUID
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* description: Object GUID of the domain to update
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* description:
|
||||||
|
* type: string
|
||||||
|
* description: Description for the domain
|
||||||
|
* netBIOSName:
|
||||||
|
* type: string
|
||||||
|
* description: NetBIOS name for the domain
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Domain updated successfully
|
||||||
|
* 400:
|
||||||
|
* description: Invalid input
|
||||||
|
* 401:
|
||||||
|
* description: Unauthorized
|
||||||
|
* 403:
|
||||||
|
* description: Forbidden
|
||||||
|
* 404:
|
||||||
|
* description: Domain not found
|
||||||
|
* 500:
|
||||||
|
* description: Server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/connections/{connectionId}/ad-domains/{objectGUID}:
|
||||||
|
* delete:
|
||||||
|
* summary: Delete an Active Directory domain
|
||||||
|
* tags: [AD Domains]
|
||||||
|
* security:
|
||||||
|
* - cookieAuth: []
|
||||||
|
* - bearerAuth: []
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: connectionId
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: integer
|
||||||
|
* description: LDAP connection ID
|
||||||
|
* - in: path
|
||||||
|
* name: objectGUID
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* description: Object GUID of the domain to delete
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Domain deleted successfully
|
||||||
|
* 401:
|
||||||
|
* description: Unauthorized
|
||||||
|
* 403:
|
||||||
|
* description: Forbidden
|
||||||
|
* 404:
|
||||||
|
* description: Domain not found
|
||||||
|
* 500:
|
||||||
|
* description: Server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
app.post("/api/connections/:connectionId/ad-domains", authenticateApiToken, async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
// Check permissions
|
||||||
|
const hasPermission = await checkPermission(req, PERMISSIONS.CREATE_AD_DOMAINS);
|
||||||
|
if (!hasPermission) {
|
||||||
|
return res.status(403).json({ message: "Not authorized to create domains" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const connectionId = parseInt(req.params.connectionId);
|
||||||
|
const connection = await storage.getLdapConnection(connectionId);
|
||||||
|
|
||||||
|
if (!connection) {
|
||||||
|
return res.status(404).json({ message: "LDAP connection not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate required fields
|
||||||
|
if (!req.body.name || !req.body.distinguishedName) {
|
||||||
|
return res.status(400).json({ message: "Name and distinguishedName are required" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Connect to LDAP server
|
||||||
|
const ldapClient = await connectToLdap(connection);
|
||||||
|
|
||||||
|
// Create domain attributes
|
||||||
|
const domainAttributes = {
|
||||||
|
objectClass: ['domain'],
|
||||||
|
cn: req.body.name,
|
||||||
|
description: req.body.description || `Domain ${req.body.name}`
|
||||||
|
};
|
||||||
|
|
||||||
|
if (req.body.netBIOSName) {
|
||||||
|
domainAttributes.netBIOSName = req.body.netBIOSName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add domain to LDAP
|
||||||
|
await ldapClient.add(req.body.distinguishedName, domainAttributes);
|
||||||
|
|
||||||
|
// Get the created domain's GUID and details
|
||||||
|
const searchResults = await ldapClient.search(req.body.distinguishedName, {
|
||||||
|
scope: 'base',
|
||||||
|
attributes: ['objectGUID', 'distinguishedName', 'cn', 'description', 'name', 'netBIOSName']
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!searchResults.searchEntries || searchResults.searchEntries.length === 0) {
|
||||||
|
return res.status(500).json({ message: "Domain was created but could not be retrieved" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const domainEntry = searchResults.searchEntries[0];
|
||||||
|
|
||||||
|
// Format objectGUID
|
||||||
|
const objectGUID = Buffer.from(domainEntry.objectGUID).toString('hex');
|
||||||
|
|
||||||
|
// Create domain record in database
|
||||||
|
const domainData = {
|
||||||
|
name: req.body.name,
|
||||||
|
connectionId: connectionId,
|
||||||
|
objectGUID: objectGUID,
|
||||||
|
distinguishedName: req.body.distinguishedName,
|
||||||
|
cn: domainEntry.cn,
|
||||||
|
netBIOSName: req.body.netBIOSName,
|
||||||
|
forestName: req.body.forestName,
|
||||||
|
adProperties: domainEntry
|
||||||
|
};
|
||||||
|
|
||||||
|
const createdDomain = await storage.createAdDomain(domainData);
|
||||||
|
|
||||||
|
// Add audit log
|
||||||
|
await storage.createAuditLogEntry({
|
||||||
|
action: "create_domain",
|
||||||
|
targetId: objectGUID,
|
||||||
|
userId: req.user?.id,
|
||||||
|
connectionId: connectionId,
|
||||||
|
details: {
|
||||||
|
domain: req.body.name,
|
||||||
|
distinguishedName: req.body.distinguishedName
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(201).json({
|
||||||
|
...createdDomain,
|
||||||
|
objectType: 'domain'
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error creating domain:", err);
|
||||||
|
// Check if the error is because the domain already exists
|
||||||
|
if (err.message && err.message.includes('entryAlreadyExists')) {
|
||||||
|
return res.status(409).json({ message: "Domain already exists" });
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(500).json({ message: `Error creating domain: ${err.message}` });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/connections/{connectionId}/ldap-attributes:
|
* /api/connections/{connectionId}/ldap-attributes:
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ export const PERMISSIONS = {
|
|||||||
MOVE_AD_COMPUTERS: "move:ad_computers",
|
MOVE_AD_COMPUTERS: "move:ad_computers",
|
||||||
|
|
||||||
VIEW_AD_DOMAINS: "view:ad_domains",
|
VIEW_AD_DOMAINS: "view:ad_domains",
|
||||||
|
CREATE_AD_DOMAINS: "create:ad_domains",
|
||||||
|
UPDATE_AD_DOMAINS: "update:ad_domains",
|
||||||
|
DELETE_AD_DOMAINS: "delete:ad_domains",
|
||||||
|
|
||||||
// Sites and Services management
|
// Sites and Services management
|
||||||
VIEW_AD_SITES: "view:ad_sites",
|
VIEW_AD_SITES: "view:ad_sites",
|
||||||
@@ -101,6 +104,9 @@ export const permissionsSchema = z.enum([
|
|||||||
"delete:ad_computers",
|
"delete:ad_computers",
|
||||||
"move:ad_computers",
|
"move:ad_computers",
|
||||||
"view:ad_domains",
|
"view:ad_domains",
|
||||||
|
"create:ad_domains",
|
||||||
|
"update:ad_domains",
|
||||||
|
"delete:ad_domains",
|
||||||
"view:ad_sites",
|
"view:ad_sites",
|
||||||
"create:ad_sites",
|
"create:ad_sites",
|
||||||
"update:ad_sites",
|
"update:ad_sites",
|
||||||
|
|||||||
Reference in New Issue
Block a user