Add webhook 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/8073f1fe-e0d9-429c-8016-8ed7ce338f7f.jpg
This commit is contained in:
alphaeusmote
2025-04-10 01:35:07 +00:00
2 changed files with 132 additions and 3 deletions
+53 -2
View File
@@ -1,13 +1,13 @@
import {
users, organizations, domains, dnsRecords,
providers, dnsHistory, apiTokens,
providers, dnsHistory, apiTokens, webhooks,
type User, type InsertUser,
type Organization, type InsertOrganization,
type Domain, type InsertDomain,
type DnsRecord, type InsertDnsRecord,
type Provider, type InsertProvider,
type ApiToken, type InsertApiToken,
type DnsHistory
type DnsHistory, type Webhook, type InsertWebhook
} from "@shared/schema";
import { db } from "./db";
import { eq, and, desc, or, inArray, sql } from "drizzle-orm";
@@ -260,4 +260,55 @@ export class DatabaseStorage implements IStorage {
)
.orderBy(desc(dnsHistory.timestamp));
}
// Webhook management
async getWebhook(id: string): Promise<Webhook | undefined> {
const [webhook] = await db.select().from(webhooks).where(eq(webhooks.id, id));
return webhook;
}
async getWebhooksByOrganization(organizationId: string): Promise<Webhook[]> {
return await db.select()
.from(webhooks)
.where(eq(webhooks.organizationId, organizationId));
}
async createWebhook(webhook: InsertWebhook): Promise<Webhook> {
const [newWebhook] = await db.insert(webhooks).values(webhook).returning();
return newWebhook;
}
async updateWebhook(id: string, webhookData: Partial<InsertWebhook>): Promise<Webhook | undefined> {
const [updatedWebhook] = await db.update(webhooks)
.set(webhookData)
.where(eq(webhooks.id, id))
.returning();
return updatedWebhook;
}
async deleteWebhook(id: string): Promise<boolean> {
const result = await db.delete(webhooks).where(eq(webhooks.id, id)).returning();
return result.length > 0;
}
async triggerWebhook(webhookId: string, payload: any): Promise<boolean> {
try {
// Get the webhook
const webhook = await this.getWebhook(webhookId);
if (!webhook || !webhook.isActive) return false;
// In a real implementation, this would make an HTTP request to the webhook URL
console.log(`Triggering webhook ${webhook.name} (${webhook.id}) with payload:`, payload);
// Update the lastTriggered timestamp
await db.update(webhooks)
.set({ lastTriggered: new Date() })
.where(eq(webhooks.id, webhookId));
return true;
} catch (error) {
console.error(`Error triggering webhook ${webhookId}:`, error);
return false;
}
}
}
+79 -1
View File
@@ -5,7 +5,8 @@ import {
type DnsRecord, type InsertDnsRecord,
type Provider, type InsertProvider,
type ApiToken, type InsertApiToken,
type DnsHistory
type DnsHistory,
type Webhook, type InsertWebhook
} from "@shared/schema";
import session from "express-session";
import { DatabaseStorage } from "./database-storage";
@@ -61,6 +62,14 @@ export interface IStorage {
getDnsHistoryByRecord(recordId: string): Promise<DnsHistory[]>;
getDnsHistoryByDomain(domainId: string): Promise<DnsHistory[]>;
// Webhook management
getWebhook(id: string): Promise<Webhook | undefined>;
getWebhooksByOrganization(organizationId: string): Promise<Webhook[]>;
createWebhook(webhook: InsertWebhook): Promise<Webhook>;
updateWebhook(id: string, webhook: Partial<InsertWebhook>): Promise<Webhook | undefined>;
deleteWebhook(id: string): Promise<boolean>;
triggerWebhook(webhookId: string, payload: any): Promise<boolean>;
// Session store
sessionStore: any;
}
@@ -73,6 +82,7 @@ export class MemStorage implements IStorage {
private providersMap: Map<number, Provider>;
private apiTokensMap: Map<number, ApiToken>;
private historyMap: Map<number, DnsHistory>;
private webhooksMap: Map<number, Webhook>;
// Counters for IDs
private userIdCounter: number;
@@ -82,6 +92,7 @@ export class MemStorage implements IStorage {
private providerIdCounter: number;
private apiTokenIdCounter: number;
private historyIdCounter: number;
private webhookIdCounter: number;
public sessionStore: any;
@@ -93,6 +104,7 @@ export class MemStorage implements IStorage {
this.providersMap = new Map();
this.apiTokensMap = new Map();
this.historyMap = new Map();
this.webhooksMap = new Map();
this.userIdCounter = 1;
this.orgIdCounter = 1;
@@ -101,6 +113,7 @@ export class MemStorage implements IStorage {
this.providerIdCounter = 1;
this.apiTokenIdCounter = 1;
this.historyIdCounter = 1;
this.webhookIdCounter = 1;
// Session store is created in the DatabaseStorage class
this.sessionStore = null;
@@ -436,6 +449,71 @@ export class MemStorage implements IStorage {
.filter(history => recordIds.includes(history.recordId))
.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
}
// Webhook management
async getWebhook(id: string): Promise<Webhook | undefined> {
return this.webhooksMap.get(parseInt(id));
}
async getWebhooksByOrganization(organizationId: string): Promise<Webhook[]> {
return Array.from(this.webhooksMap.values())
.filter(webhook => webhook.organizationId === organizationId);
}
async createWebhook(webhook: InsertWebhook): Promise<Webhook> {
const numId = this.webhookIdCounter++;
const createdAt = new Date();
const newWebhook: Webhook = {
id: numId.toString(),
name: webhook.name,
url: webhook.url,
organizationId: webhook.organizationId,
secret: webhook.secret ?? null,
events: webhook.events,
isActive: webhook.isActive ?? true,
lastTriggered: null,
createdBy: webhook.createdBy,
createdAt
};
this.webhooksMap.set(numId, newWebhook);
return newWebhook;
}
async updateWebhook(id: string, webhookData: Partial<InsertWebhook>): Promise<Webhook | undefined> {
const numId = parseInt(id);
const webhook = await this.getWebhook(id);
if (!webhook) return undefined;
const updatedWebhook = { ...webhook, ...webhookData };
this.webhooksMap.set(numId, updatedWebhook);
return updatedWebhook;
}
async deleteWebhook(id: string): Promise<boolean> {
return this.webhooksMap.delete(parseInt(id));
}
async triggerWebhook(webhookId: string, payload: any): Promise<boolean> {
const webhook = await this.getWebhook(webhookId);
if (!webhook || !webhook.isActive) return false;
try {
// In a real implementation, this would make an HTTP request to the webhook URL
console.log(`Triggering webhook ${webhook.name} (${webhook.id}) with payload:`, payload);
// Update the lastTriggered timestamp
const updatedWebhook = {
...webhook,
lastTriggered: new Date()
};
this.webhooksMap.set(parseInt(webhookId), updatedWebhook);
return true;
} catch (error) {
console.error(`Error triggering webhook ${webhook.id}:`, error);
return false;
}
}
}
export const storage = new DatabaseStorage();