From b48f64b1345e64c88df9a2febcfc2e76e3cf761e Mon Sep 17 00:00:00 2001 From: alphaeusmote <41258468-alphaeusmote@users.noreply.replit.com> Date: Thu, 10 Apr 2025 12:31:11 +0000 Subject: [PATCH] Add group management functionality Replit-Commit-Author: Agent Replit-Commit-Session-Id: 9111ef36-26c8-4085-84ca-a35dc1fec1b5 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7083d608-d6d3-4a6a-9a27-6286c5109627/6b103ae4-95ab-4db4-bc85-4c7eb57c809f.jpg --- server/database-storage.ts | 49 ++++++++++++++++++++++++++- server/storage.ts | 69 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/server/database-storage.ts b/server/database-storage.ts index 1002986..fcb5460 100644 --- a/server/database-storage.ts +++ b/server/database-storage.ts @@ -1,6 +1,7 @@ import { users, organizations, domains, dnsRecords, providers, dnsHistory, apiTokens, webhooks, webhookDeliveryLogs, dnsMetrics, + groups, groupMembers, type User, type InsertUser, type Organization, type InsertOrganization, type Domain, type InsertDomain, @@ -9,7 +10,9 @@ import { type ApiToken, type InsertApiToken, type DnsHistory, type Webhook, type InsertWebhook, type WebhookDeliveryLog, type InsertWebhookDeliveryLog, - type DnsMetric, type InsertDnsMetric + type DnsMetric, type InsertDnsMetric, + type Group, type InsertGroup, + type GroupMember, type InsertGroupMember } from "@shared/schema"; import { db } from "./db"; import { eq, and, desc, or, inArray, sql } from "drizzle-orm"; @@ -92,6 +95,50 @@ export class DatabaseStorage implements IStorage { return result.length > 0; } + // Group management + async getGroup(id: string): Promise { + const [group] = await db.select().from(groups).where(eq(groups.id, id)); + return group; + } + + async getGroups(): Promise { + return await db.select().from(groups); + } + + async getGroupMembers(groupId: string): Promise { + return await db.select() + .from(groupMembers) + .where(eq(groupMembers.groupId, groupId)); + } + + async createGroup(group: InsertGroup): Promise { + const [newGroup] = await db.insert(groups).values(group).returning(); + return newGroup; + } + + async updateGroup(id: string, groupData: Partial): Promise { + const [updatedGroup] = await db.update(groups) + .set(groupData) + .where(eq(groups.id, id)) + .returning(); + return updatedGroup; + } + + async deleteGroup(id: string): Promise { + const result = await db.delete(groups).where(eq(groups.id, id)).returning(); + return result.length > 0; + } + + async addGroupMember(member: InsertGroupMember): Promise { + const [newMember] = await db.insert(groupMembers).values(member).returning(); + return newMember; + } + + async removeGroupMember(id: string): Promise { + const result = await db.delete(groupMembers).where(eq(groupMembers.id, id)).returning(); + return result.length > 0; + } + // Domain management async getDomain(id: string): Promise { try { diff --git a/server/storage.ts b/server/storage.ts index 942b44b..7c7fa5d 100644 --- a/server/storage.ts +++ b/server/storage.ts @@ -109,6 +109,8 @@ export class MemStorage implements IStorage { private webhooksMap: Map; private webhookDeliveryLogsMap: Map; private metricsMap: Map; + private groupsMap: Map; + private groupMembersMap: Map; // Counters for IDs private userIdCounter: number; @@ -121,6 +123,8 @@ export class MemStorage implements IStorage { private webhookIdCounter: number; private webhookDeliveryLogIdCounter: number; private metricIdCounter: number; + private groupIdCounter: number; + private groupMemberIdCounter: number; public sessionStore: any; @@ -135,6 +139,8 @@ export class MemStorage implements IStorage { this.webhooksMap = new Map(); this.webhookDeliveryLogsMap = new Map(); this.metricsMap = new Map(); + this.groupsMap = new Map(); + this.groupMembersMap = new Map(); this.userIdCounter = 1; this.orgIdCounter = 1; @@ -146,6 +152,8 @@ export class MemStorage implements IStorage { this.webhookIdCounter = 1; this.webhookDeliveryLogIdCounter = 1; this.metricIdCounter = 1; + this.groupIdCounter = 1; + this.groupMemberIdCounter = 1; // Session store is created in the DatabaseStorage class this.sessionStore = null; @@ -256,6 +264,67 @@ export class MemStorage implements IStorage { return this.orgsMap.delete(parseInt(id)); } + // Group management + async getGroup(id: string): Promise { + return this.groupsMap.get(parseInt(id)); + } + + async getGroups(): Promise { + return Array.from(this.groupsMap.values()); + } + + async getGroupMembers(groupId: string): Promise { + return Array.from(this.groupMembersMap.values()) + .filter(member => member.groupId === groupId); + } + + async createGroup(group: InsertGroup): Promise { + const numId = this.groupIdCounter++; + const createdAt = new Date(); + const newGroup: Group = { + id: numId.toString(), + name: group.name, + description: group.description || null, + organizationId: group.organizationId, + isActive: group.isActive ?? true, + createdAt + }; + this.groupsMap.set(numId, newGroup); + return newGroup; + } + + async updateGroup(id: string, groupData: Partial): Promise { + const numId = parseInt(id); + const group = await this.getGroup(id); + if (!group) return undefined; + + const updatedGroup = { ...group, ...groupData }; + this.groupsMap.set(numId, updatedGroup); + return updatedGroup; + } + + async deleteGroup(id: string): Promise { + return this.groupsMap.delete(parseInt(id)); + } + + async addGroupMember(member: InsertGroupMember): Promise { + const numId = this.groupMemberIdCounter++; + const createdAt = new Date(); + const newMember: GroupMember = { + id: numId.toString(), + groupId: member.groupId, + memberId: member.memberId, + memberType: member.memberType, + createdAt + }; + this.groupMembersMap.set(numId, newMember); + return newMember; + } + + async removeGroupMember(id: string): Promise { + return this.groupMembersMap.delete(parseInt(id)); + } + // Domains async getDomain(id: string): Promise { return this.domainsMap.get(parseInt(id));