mirror of
https://github.com/freedbygrace/ActiveDirectoryManager.git
synced 2026-07-26 11:59:14 +00:00
Add support for querying Active Directory sites and subnets
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/38d85472-a91b-4a98-977a-cd9ab8f43196.jpg
This commit is contained in:
Generated
+21
@@ -51,6 +51,7 @@
|
||||
"@types/passport-jwt": "^4.0.1",
|
||||
"@types/swagger-jsdoc": "^6.0.4",
|
||||
"@types/swagger-ui-express": "^4.1.8",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.0.0",
|
||||
@@ -88,6 +89,7 @@
|
||||
"swagger-ui-express": "^5.0.1",
|
||||
"tailwind-merge": "^2.5.4",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"uuid": "^11.1.0",
|
||||
"vaul": "^1.1.0",
|
||||
"wouter": "^3.3.5",
|
||||
"ws": "^8.18.0",
|
||||
@@ -3852,6 +3854,12 @@
|
||||
"@types/serve-static": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/uuid": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
|
||||
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.5.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz",
|
||||
@@ -9110,6 +9118,19 @@
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
|
||||
"integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "dist/esm/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/validator": {
|
||||
"version": "13.15.0",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-13.15.0.tgz",
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
"@types/passport-jwt": "^4.0.1",
|
||||
"@types/swagger-jsdoc": "^6.0.4",
|
||||
"@types/swagger-ui-express": "^4.1.8",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.0.0",
|
||||
@@ -90,6 +91,7 @@
|
||||
"swagger-ui-express": "^5.0.1",
|
||||
"tailwind-merge": "^2.5.4",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"uuid": "^11.1.0",
|
||||
"vaul": "^1.1.0",
|
||||
"wouter": "^3.3.5",
|
||||
"ws": "^8.18.0",
|
||||
|
||||
@@ -152,6 +152,94 @@ class LdapClient extends EventEmitter {
|
||||
return this.searchUsers(connectionId, filter, attributes || defaultAttributes);
|
||||
}
|
||||
|
||||
async searchSites(connectionId: number, filter = '(objectClass=site)', attributes?: string[]): Promise<any[]> {
|
||||
const defaultAttributes = ['cn', 'distinguishedName', 'description', 'location', 'managedBy'];
|
||||
// Sites are typically stored in the Configuration naming context
|
||||
const client = this.getClient(connectionId);
|
||||
if (!client) throw new Error('LDAP connection not established');
|
||||
|
||||
const connection = await storage.getLdapConnection(connectionId);
|
||||
if (!connection) throw new Error('LDAP connection not found');
|
||||
|
||||
// Sites are located in the Configuration container
|
||||
const baseDN = 'CN=Sites,CN=Configuration,' + this.getDomainDN(connection);
|
||||
const searchAttributes = attributes?.length ? attributes : defaultAttributes;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const results: any[] = [];
|
||||
|
||||
client.search(baseDN, {
|
||||
filter,
|
||||
scope: 'sub',
|
||||
attributes: searchAttributes
|
||||
}, (err, res) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
res.on('searchEntry', (entry) => {
|
||||
results.push(entry.object);
|
||||
});
|
||||
|
||||
res.on('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
|
||||
res.on('end', (result) => {
|
||||
resolve(results);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async searchSubnets(connectionId: number, filter = '(objectClass=subnet)', attributes?: string[]): Promise<any[]> {
|
||||
const defaultAttributes = ['cn', 'distinguishedName', 'description', 'location', 'siteObject', 'managedBy'];
|
||||
// Subnets are typically stored in the Configuration naming context
|
||||
const client = this.getClient(connectionId);
|
||||
if (!client) throw new Error('LDAP connection not established');
|
||||
|
||||
const connection = await storage.getLdapConnection(connectionId);
|
||||
if (!connection) throw new Error('LDAP connection not found');
|
||||
|
||||
// Subnets are located in the Configuration container
|
||||
const baseDN = 'CN=Subnets,CN=Sites,CN=Configuration,' + this.getDomainDN(connection);
|
||||
const searchAttributes = attributes?.length ? attributes : defaultAttributes;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const results: any[] = [];
|
||||
|
||||
client.search(baseDN, {
|
||||
filter,
|
||||
scope: 'sub',
|
||||
attributes: searchAttributes
|
||||
}, (err, res) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
res.on('searchEntry', (entry) => {
|
||||
results.push(entry.object);
|
||||
});
|
||||
|
||||
res.on('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
|
||||
res.on('end', (result) => {
|
||||
resolve(results);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Helper function to extract domain DN from connection
|
||||
getDomainDN(connection: LdapConnection): string {
|
||||
const domainParts = connection.domain.split('.');
|
||||
return domainParts.map(part => `DC=${part}`).join(',');
|
||||
}
|
||||
|
||||
async createEntry(connectionId: number, dn: string, attributes: any): Promise<boolean> {
|
||||
const client = this.getClient(connectionId);
|
||||
if (!client) throw new Error('LDAP connection not established');
|
||||
|
||||
+1080
-1
File diff suppressed because it is too large
Load Diff
+153
-2
@@ -3,11 +3,11 @@ import {
|
||||
LdapConnection, InsertLdapConnection,
|
||||
AdUser, InsertAdUser, AdGroup, InsertAdGroup,
|
||||
AdOrgUnit, InsertAdOrgUnit, AdComputer, InsertAdComputer,
|
||||
AdDomain, InsertAdDomain, Role, ApiQuery,
|
||||
AdDomain, InsertAdDomain, AdSite, InsertAdSite, AdSubnet, InsertAdSubnet, Role, ApiQuery,
|
||||
LdapFilter, InsertLdapFilter, LdapFilterRevision, InsertLdapFilterRevision,
|
||||
LdapAttribute, InsertLdapAttribute, AuditLog, InsertAuditLog,
|
||||
users, apiTokens, ldapConnections, adUsers, adGroups, adOrgUnits, adComputers, adDomains,
|
||||
roles, ldapFilters, ldapFilterRevisions, ldapAttributes, auditLogs
|
||||
adSites, adSubnets, roles, ldapFilters, ldapFilterRevisions, ldapAttributes, auditLogs
|
||||
} from "@shared/schema";
|
||||
import session from "express-session";
|
||||
import createMemoryStore from "memorystore";
|
||||
@@ -121,6 +121,24 @@ export interface IStorage {
|
||||
deleteAdDomain(id: number): Promise<boolean>;
|
||||
listAdDomains(connectionId: number, query?: any): Promise<AdDomain[]>;
|
||||
|
||||
// AD Sites
|
||||
getAdSite(id: number): Promise<AdSite | undefined>;
|
||||
getAdSiteByObjectGUID(connectionId: number, objectGUID: string): Promise<AdSite | undefined>;
|
||||
createAdSite(site: InsertAdSite): Promise<AdSite>;
|
||||
updateAdSite(id: number, site: Partial<AdSite>): Promise<AdSite | undefined>;
|
||||
updateAdSiteByObjectGUID(connectionId: number, objectGUID: string, site: Partial<AdSite>): Promise<AdSite | undefined>;
|
||||
deleteAdSite(id: number): Promise<boolean>;
|
||||
listAdSites(connectionId: number, query?: any): Promise<AdSite[]>;
|
||||
|
||||
// AD Subnets
|
||||
getAdSubnet(id: number): Promise<AdSubnet | undefined>;
|
||||
getAdSubnetByObjectGUID(connectionId: number, objectGUID: string): Promise<AdSubnet | undefined>;
|
||||
createAdSubnet(subnet: InsertAdSubnet): Promise<AdSubnet>;
|
||||
updateAdSubnet(id: number, subnet: Partial<AdSubnet>): Promise<AdSubnet | undefined>;
|
||||
updateAdSubnetByObjectGUID(connectionId: number, objectGUID: string, subnet: Partial<AdSubnet>): Promise<AdSubnet | undefined>;
|
||||
deleteAdSubnet(id: number): Promise<boolean>;
|
||||
listAdSubnets(connectionId: number, query?: any): Promise<AdSubnet[]>;
|
||||
|
||||
// Audit logging
|
||||
createAuditLogEntry(entry: InsertAuditLog): Promise<AuditLog>;
|
||||
getAuditLogs(connectionId?: number, userId?: number, page?: number, pageSize?: number): Promise<{ data: AuditLog[], metadata: { currentPage: number, totalPages: number, totalRecords: number, nextPage: number | null, prevPage: number | null } }>;
|
||||
@@ -548,6 +566,12 @@ export class DatabaseStorage implements IStorage {
|
||||
case 'domain':
|
||||
results = await this.listAdDomains(connectionId);
|
||||
break;
|
||||
case 'site':
|
||||
results = await this.listAdSites(connectionId);
|
||||
break;
|
||||
case 'subnet':
|
||||
results = await this.listAdSubnets(connectionId);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported object class: ${objectClass}`);
|
||||
}
|
||||
@@ -651,6 +675,11 @@ export class DatabaseStorage implements IStorage {
|
||||
if (selectedFields && selectedFields.length > 0) {
|
||||
const result = users.map(user => {
|
||||
const filtered: Partial<AdUser> = { id: user.id };
|
||||
|
||||
// Always include managedBy field regardless of selection
|
||||
filtered.managedBy = user.managedBy;
|
||||
|
||||
// Add selected fields
|
||||
selectedFields.forEach(field => {
|
||||
if (field in user) {
|
||||
filtered[field as keyof AdUser] = user[field as keyof AdUser];
|
||||
@@ -765,6 +794,10 @@ export class DatabaseStorage implements IStorage {
|
||||
if (selectedFields && selectedFields.length > 0) {
|
||||
const result = groups.map(group => {
|
||||
const filtered: Partial<AdGroup> = { id: group.id };
|
||||
|
||||
// Always include managedBy field regardless of selection
|
||||
filtered.managedBy = group.managedBy;
|
||||
|
||||
selectedFields.forEach(field => {
|
||||
if (field in group) {
|
||||
filtered[field as keyof AdGroup] = group[field as keyof AdGroup];
|
||||
@@ -845,6 +878,10 @@ export class DatabaseStorage implements IStorage {
|
||||
|
||||
return orgUnits.map(ou => {
|
||||
const result: any = { id: ou.id };
|
||||
|
||||
// Always include managedBy field regardless of selection
|
||||
result.managedBy = ou.managedBy;
|
||||
|
||||
properties.forEach((prop: string) => {
|
||||
if ((ou as any)[prop] !== undefined) {
|
||||
result[prop] = (ou as any)[prop];
|
||||
@@ -913,6 +950,10 @@ export class DatabaseStorage implements IStorage {
|
||||
|
||||
return computers.map(computer => {
|
||||
const result: any = { id: computer.id };
|
||||
|
||||
// Always include managedBy field regardless of selection
|
||||
result.managedBy = computer.managedBy;
|
||||
|
||||
properties.forEach((prop: string) => {
|
||||
if ((computer as any)[prop] !== undefined) {
|
||||
result[prop] = (computer as any)[prop];
|
||||
@@ -968,6 +1009,116 @@ export class DatabaseStorage implements IStorage {
|
||||
return adDomainsQuery;
|
||||
}
|
||||
|
||||
// AD Sites
|
||||
async getAdSite(id: number): Promise<AdSite | undefined> {
|
||||
const result = await db.select().from(adSites).where(eq(adSites.id, id));
|
||||
return result.length > 0 ? result[0] : undefined;
|
||||
}
|
||||
|
||||
async getAdSiteByObjectGUID(connectionId: number, objectGUID: string): Promise<AdSite | undefined> {
|
||||
const result = await db.select().from(adSites).where(
|
||||
and(
|
||||
eq(adSites.connectionId, connectionId),
|
||||
eq(adSites.objectGUID, objectGUID)
|
||||
)
|
||||
);
|
||||
return result.length > 0 ? result[0] : undefined;
|
||||
}
|
||||
|
||||
async createAdSite(site: InsertAdSite): Promise<AdSite> {
|
||||
const result = await db.insert(adSites).values(site).returning();
|
||||
return result[0];
|
||||
}
|
||||
|
||||
async updateAdSite(id: number, site: Partial<AdSite>): Promise<AdSite | undefined> {
|
||||
const result = await db.update(adSites).set(site).where(eq(adSites.id, id)).returning();
|
||||
return result.length > 0 ? result[0] : undefined;
|
||||
}
|
||||
|
||||
async updateAdSiteByObjectGUID(connectionId: number, objectGUID: string, site: Partial<AdSite>): Promise<AdSite | undefined> {
|
||||
const result = await db.update(adSites)
|
||||
.set(site)
|
||||
.where(
|
||||
and(
|
||||
eq(adSites.connectionId, connectionId),
|
||||
eq(adSites.objectGUID, objectGUID)
|
||||
)
|
||||
)
|
||||
.returning();
|
||||
return result.length > 0 ? result[0] : undefined;
|
||||
}
|
||||
|
||||
async deleteAdSite(id: number): Promise<boolean> {
|
||||
const result = await db.delete(adSites).where(eq(adSites.id, id)).returning({ id: adSites.id });
|
||||
return result.length > 0;
|
||||
}
|
||||
|
||||
async listAdSites(connectionId: number, query?: any): Promise<AdSite[]> {
|
||||
let adSitesQuery = db.select().from(adSites).where(eq(adSites.connectionId, connectionId));
|
||||
|
||||
// Apply query options (filtering, pagination, etc.)
|
||||
if (query) {
|
||||
adSitesQuery = applyQueryOptions(adSitesQuery, query, adSites);
|
||||
}
|
||||
|
||||
return adSitesQuery;
|
||||
}
|
||||
|
||||
// AD Subnets
|
||||
async getAdSubnet(id: number): Promise<AdSubnet | undefined> {
|
||||
const result = await db.select().from(adSubnets).where(eq(adSubnets.id, id));
|
||||
return result.length > 0 ? result[0] : undefined;
|
||||
}
|
||||
|
||||
async getAdSubnetByObjectGUID(connectionId: number, objectGUID: string): Promise<AdSubnet | undefined> {
|
||||
const result = await db.select().from(adSubnets).where(
|
||||
and(
|
||||
eq(adSubnets.connectionId, connectionId),
|
||||
eq(adSubnets.objectGUID, objectGUID)
|
||||
)
|
||||
);
|
||||
return result.length > 0 ? result[0] : undefined;
|
||||
}
|
||||
|
||||
async createAdSubnet(subnet: InsertAdSubnet): Promise<AdSubnet> {
|
||||
const result = await db.insert(adSubnets).values(subnet).returning();
|
||||
return result[0];
|
||||
}
|
||||
|
||||
async updateAdSubnet(id: number, subnet: Partial<AdSubnet>): Promise<AdSubnet | undefined> {
|
||||
const result = await db.update(adSubnets).set(subnet).where(eq(adSubnets.id, id)).returning();
|
||||
return result.length > 0 ? result[0] : undefined;
|
||||
}
|
||||
|
||||
async updateAdSubnetByObjectGUID(connectionId: number, objectGUID: string, subnet: Partial<AdSubnet>): Promise<AdSubnet | undefined> {
|
||||
const result = await db.update(adSubnets)
|
||||
.set(subnet)
|
||||
.where(
|
||||
and(
|
||||
eq(adSubnets.connectionId, connectionId),
|
||||
eq(adSubnets.objectGUID, objectGUID)
|
||||
)
|
||||
)
|
||||
.returning();
|
||||
return result.length > 0 ? result[0] : undefined;
|
||||
}
|
||||
|
||||
async deleteAdSubnet(id: number): Promise<boolean> {
|
||||
const result = await db.delete(adSubnets).where(eq(adSubnets.id, id)).returning({ id: adSubnets.id });
|
||||
return result.length > 0;
|
||||
}
|
||||
|
||||
async listAdSubnets(connectionId: number, query?: any): Promise<AdSubnet[]> {
|
||||
let adSubnetsQuery = db.select().from(adSubnets).where(eq(adSubnets.connectionId, connectionId));
|
||||
|
||||
// Apply query options (filtering, pagination, etc.)
|
||||
if (query) {
|
||||
adSubnetsQuery = applyQueryOptions(adSubnetsQuery, query, adSubnets);
|
||||
}
|
||||
|
||||
return adSubnetsQuery;
|
||||
}
|
||||
|
||||
// Audit logging
|
||||
async createAuditLogEntry(entry: InsertAuditLog): Promise<AuditLog> {
|
||||
debug(`Creating audit log entry: ${JSON.stringify(entry)}`);
|
||||
|
||||
@@ -105,6 +105,7 @@ const swaggerOptions = {
|
||||
enabled: { type: "boolean" },
|
||||
lastLogon: { type: "string", format: "date-time" },
|
||||
memberOf: { type: "array", items: { type: "string" } },
|
||||
managedBy: { type: "string", description: "Distinguished name of the user or group managing this object" },
|
||||
adProperties: { type: "object" },
|
||||
objectType: { type: "string", enum: ["user"] },
|
||||
},
|
||||
@@ -122,6 +123,7 @@ const swaggerOptions = {
|
||||
groupType: { type: "string" },
|
||||
description: { type: "string" },
|
||||
members: { type: "array", items: { type: "string" } },
|
||||
managedBy: { type: "string", description: "Distinguished name of the user or group managing this object" },
|
||||
adProperties: { type: "object" },
|
||||
objectType: { type: "string", enum: ["group"] },
|
||||
},
|
||||
@@ -137,6 +139,7 @@ const swaggerOptions = {
|
||||
cn: { type: "string" },
|
||||
name: { type: "string" },
|
||||
description: { type: "string" },
|
||||
managedBy: { type: "string", description: "Distinguished name of the user or group managing this object" },
|
||||
adProperties: { type: "object" },
|
||||
objectType: { type: "string", enum: ["organizationalUnit"] },
|
||||
},
|
||||
@@ -156,6 +159,7 @@ const swaggerOptions = {
|
||||
operatingSystemVersion: { type: "string" },
|
||||
lastLogon: { type: "string", format: "date-time" },
|
||||
enabled: { type: "boolean" },
|
||||
managedBy: { type: "string", description: "Distinguished name of the user or group managing this object" },
|
||||
adProperties: { type: "object" },
|
||||
objectType: { type: "string", enum: ["computer"] },
|
||||
},
|
||||
@@ -177,6 +181,41 @@ const swaggerOptions = {
|
||||
objectType: { type: "string", enum: ["domain"] },
|
||||
},
|
||||
},
|
||||
AdSite: {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: { type: "integer" },
|
||||
connectionId: { type: "integer" },
|
||||
objectGUID: { type: "string" },
|
||||
distinguishedName: { type: "string" },
|
||||
cn: { type: "string" },
|
||||
name: { type: "string" },
|
||||
description: { type: "string" },
|
||||
location: { type: "string" },
|
||||
managedBy: { type: "string", description: "Distinguished name of the user or group managing this site" },
|
||||
adProperties: { type: "object" },
|
||||
objectType: { type: "string", enum: ["site"] },
|
||||
},
|
||||
},
|
||||
AdSubnet: {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: { type: "integer" },
|
||||
connectionId: { type: "integer" },
|
||||
objectGUID: { type: "string" },
|
||||
distinguishedName: { type: "string" },
|
||||
cn: { type: "string" },
|
||||
name: { type: "string" },
|
||||
description: { type: "string" },
|
||||
siteObject: { type: "string", description: "Distinguished name of the site this subnet belongs to" },
|
||||
location: { type: "string" },
|
||||
networkAddress: { type: "string" },
|
||||
networkMask: { type: "string" },
|
||||
managedBy: { type: "string", description: "Distinguished name of the user or group managing this subnet" },
|
||||
adProperties: { type: "object" },
|
||||
objectType: { type: "string", enum: ["subnet"] },
|
||||
},
|
||||
},
|
||||
LdapAttribute: {
|
||||
type: "object",
|
||||
properties: {
|
||||
|
||||
+40
-1
@@ -226,6 +226,39 @@ export const adDomains = pgTable("ad_domains", {
|
||||
adProperties: jsonb("ad_properties"),
|
||||
});
|
||||
|
||||
// AD Sites table for Sites and Services
|
||||
export const adSites = pgTable("ad_sites", {
|
||||
id: serial("id").primaryKey(),
|
||||
connectionId: integer("connection_id").notNull(),
|
||||
objectGUID: text("object_guid").notNull(),
|
||||
distinguishedName: text("distinguished_name").notNull(),
|
||||
cn: text("cn"),
|
||||
name: text("name").notNull(),
|
||||
description: text("description"),
|
||||
location: text("location"),
|
||||
managedBy: text("managed_by"),
|
||||
adProperties: jsonb("ad_properties"),
|
||||
objectType: text("object_type").default("site").notNull(),
|
||||
});
|
||||
|
||||
// AD Subnets table for Sites and Services
|
||||
export const adSubnets = pgTable("ad_subnets", {
|
||||
id: serial("id").primaryKey(),
|
||||
connectionId: integer("connection_id").notNull(),
|
||||
objectGUID: text("object_guid").notNull(),
|
||||
distinguishedName: text("distinguished_name").notNull(),
|
||||
cn: text("cn"),
|
||||
name: text("name").notNull(),
|
||||
description: text("description"),
|
||||
siteObject: text("site_object"),
|
||||
location: text("location"),
|
||||
networkAddress: text("network_address"),
|
||||
networkMask: text("network_mask"),
|
||||
managedBy: text("managed_by"),
|
||||
adProperties: jsonb("ad_properties"),
|
||||
objectType: text("object_type").default("subnet").notNull(),
|
||||
});
|
||||
|
||||
// Define relations between tables
|
||||
export const rolesRelations = relations(roles, ({ many }) => ({
|
||||
permissions: many(rolePermissions),
|
||||
@@ -270,6 +303,8 @@ export const insertAdGroupSchema = createInsertSchema(adGroups).omit({ id: true
|
||||
export const insertAdOrgUnitSchema = createInsertSchema(adOrgUnits).omit({ id: true });
|
||||
export const insertAdComputerSchema = createInsertSchema(adComputers).omit({ id: true });
|
||||
export const insertAdDomainSchema = createInsertSchema(adDomains).omit({ id: true });
|
||||
export const insertAdSiteSchema = createInsertSchema(adSites).omit({ id: true });
|
||||
export const insertAdSubnetSchema = createInsertSchema(adSubnets).omit({ id: true });
|
||||
|
||||
// Login schema
|
||||
export const loginSchema = z.object({
|
||||
@@ -339,6 +374,10 @@ export type AdComputer = typeof adComputers.$inferSelect;
|
||||
export type InsertAdComputer = z.infer<typeof insertAdComputerSchema>;
|
||||
export type AdDomain = typeof adDomains.$inferSelect;
|
||||
export type InsertAdDomain = z.infer<typeof insertAdDomainSchema>;
|
||||
export type AdSite = typeof adSites.$inferSelect;
|
||||
export type InsertAdSite = z.infer<typeof insertAdSiteSchema>;
|
||||
export type AdSubnet = typeof adSubnets.$inferSelect;
|
||||
export type InsertAdSubnet = z.infer<typeof insertAdSubnetSchema>;
|
||||
export type Login = z.infer<typeof loginSchema>;
|
||||
export type ApiQuery = z.infer<typeof apiQuerySchema>;
|
||||
export type MoveComputer = z.infer<typeof moveComputerSchema>;
|
||||
@@ -348,7 +387,7 @@ export type RemoveFromGroup = z.infer<typeof removeFromGroupSchema>;
|
||||
|
||||
|
||||
// LDAP Query Builder schemas
|
||||
export const ldapFilterObjectClasses = ["user", "group", "organizationalUnit", "computer", "domain"] as const;
|
||||
export const ldapFilterObjectClasses = ["user", "group", "organizationalUnit", "computer", "domain", "site", "subnet"] as const;
|
||||
|
||||
// LDAP Filter schema
|
||||
export const ldapFilters = pgTable("ldap_filters", {
|
||||
|
||||
Reference in New Issue
Block a user