Files
DynamoDNS/server/storage.ts
T
alphaeusmote a3d13bf968 Checkpoint
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/0b0a9e81-bb40-4ac4-b480-8a47fd1275dc.jpg
2025-04-10 01:22:05 +00:00

442 lines
14 KiB
TypeScript

import {
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
} from "@shared/schema";
import session from "express-session";
import { DatabaseStorage } from "./database-storage";
export interface IStorage {
// User management
getUser(id: string): Promise<User | undefined>;
getUserByUsername(username: string): Promise<User | undefined>;
getUserByEmail(email: string): Promise<User | undefined>;
createUser(user: InsertUser): Promise<User>;
updateUser(id: string, user: Partial<InsertUser>): Promise<User | undefined>;
deleteUser(id: string): Promise<boolean>;
// Organization management
getOrganization(id: string): Promise<Organization | undefined>;
getOrganizations(): Promise<Organization[]>;
createOrganization(org: InsertOrganization): Promise<Organization>;
updateOrganization(id: string, org: Partial<InsertOrganization>): Promise<Organization | undefined>;
deleteOrganization(id: string): Promise<boolean>;
// Domain management
getDomain(id: string): Promise<Domain | undefined>;
getDomainsByOrganization(organizationId: string): Promise<Domain[]>;
getAllDomains(): Promise<Domain[]>;
createDomain(domain: InsertDomain): Promise<Domain>;
updateDomain(id: string, domain: Partial<InsertDomain>): Promise<Domain | undefined>;
deleteDomain(id: string): Promise<boolean>;
// DNS Record management
getDnsRecord(id: string): Promise<DnsRecord | undefined>;
getDnsRecordsByDomain(domainId: string): Promise<DnsRecord[]>;
createDnsRecord(record: InsertDnsRecord): Promise<DnsRecord>;
updateDnsRecord(id: string, record: Partial<InsertDnsRecord>): Promise<DnsRecord | undefined>;
deleteDnsRecord(id: string): Promise<boolean>;
// Provider management
getProvider(id: string): Promise<Provider | undefined>;
getProviders(): Promise<Provider[]>;
createProvider(provider: InsertProvider): Promise<Provider>;
updateProvider(id: string, provider: Partial<InsertProvider>): Promise<Provider | undefined>;
deleteProvider(id: string): Promise<boolean>;
// API Token management
getApiToken(id: string): Promise<ApiToken | undefined>;
getApiTokenByToken(token: string): Promise<ApiToken | undefined>;
getApiTokensByOrganization(organizationId: string): Promise<ApiToken[]>;
createApiToken(token: InsertApiToken): Promise<ApiToken>;
updateApiToken(id: string, token: Partial<InsertApiToken>): Promise<ApiToken | undefined>;
deleteApiToken(id: string): Promise<boolean>;
// DNS History
addDnsHistory(recordId: string, action: string, previousValue?: string, newValue?: string, userId?: string): Promise<DnsHistory>;
getDnsHistoryByRecord(recordId: string): Promise<DnsHistory[]>;
getDnsHistoryByDomain(domainId: string): Promise<DnsHistory[]>;
// Session store
sessionStore: any;
}
export class MemStorage implements IStorage {
private usersMap: Map<number, User>;
private orgsMap: Map<number, Organization>;
private domainsMap: Map<number, Domain>;
private recordsMap: Map<number, DnsRecord>;
private providersMap: Map<number, Provider>;
private apiTokensMap: Map<number, ApiToken>;
private historyMap: Map<number, DnsHistory>;
// Counters for IDs
private userIdCounter: number;
private orgIdCounter: number;
private domainIdCounter: number;
private recordIdCounter: number;
private providerIdCounter: number;
private apiTokenIdCounter: number;
private historyIdCounter: number;
public sessionStore: any;
constructor() {
this.usersMap = new Map();
this.orgsMap = new Map();
this.domainsMap = new Map();
this.recordsMap = new Map();
this.providersMap = new Map();
this.apiTokensMap = new Map();
this.historyMap = new Map();
this.userIdCounter = 1;
this.orgIdCounter = 1;
this.domainIdCounter = 1;
this.recordIdCounter = 1;
this.providerIdCounter = 1;
this.apiTokenIdCounter = 1;
this.historyIdCounter = 1;
// Session store is created in the DatabaseStorage class
this.sessionStore = null;
// Initialize sample data
this.initSampleData();
}
private initSampleData() {
// Create a default provider for Cloudflare
const cloudflareProvider: InsertProvider = {
name: "Cloudflare",
type: "cloudflare",
credentials: { apiKey: process.env.CLOUDFLARE_API_KEY || "" },
isActive: true
};
this.createProvider(cloudflareProvider);
// Create sample organization
const defaultOrg: InsertOrganization = {
name: "Default Organization",
isActive: true
};
this.createOrganization(defaultOrg);
}
// Users
async getUser(id: string): Promise<User | undefined> {
return this.usersMap.get(parseInt(id));
}
async getUserByUsername(username: string): Promise<User | undefined> {
return Array.from(this.usersMap.values()).find(
(user) => user.username === username,
);
}
async getUserByEmail(email: string): Promise<User | undefined> {
return Array.from(this.usersMap.values()).find(
(user) => user.email === email,
);
}
async createUser(user: InsertUser): Promise<User> {
const id = this.userIdCounter++;
const createdAt = new Date();
const newUser: User = {
id,
username: user.username,
password: user.password,
email: user.email,
fullName: user.fullName || null,
role: user.role || 'user',
organizationId: user.organizationId || null,
createdAt
};
this.usersMap.set(id, newUser);
return newUser;
}
async updateUser(id: string, userData: Partial<InsertUser>): Promise<User | undefined> {
const numId = parseInt(id);
const user = await this.getUser(id);
if (!user) return undefined;
const updatedUser = { ...user, ...userData };
this.usersMap.set(numId, updatedUser);
return updatedUser;
}
async deleteUser(id: string): Promise<boolean> {
return this.usersMap.delete(parseInt(id));
}
// Organizations
async getOrganization(id: string): Promise<Organization | undefined> {
return this.orgsMap.get(parseInt(id));
}
async getOrganizations(): Promise<Organization[]> {
return Array.from(this.orgsMap.values());
}
async createOrganization(org: InsertOrganization): Promise<Organization> {
const id = this.orgIdCounter++;
const createdAt = new Date();
const newOrg: Organization = {
id: id.toString(),
name: org.name,
isActive: org.isActive ?? true,
createdAt
};
this.orgsMap.set(id, newOrg);
return newOrg;
}
async updateOrganization(id: string, orgData: Partial<InsertOrganization>): Promise<Organization | undefined> {
const numId = parseInt(id);
const org = await this.getOrganization(id);
if (!org) return undefined;
const updatedOrg = { ...org, ...orgData };
this.orgsMap.set(numId, updatedOrg);
return updatedOrg;
}
async deleteOrganization(id: string): Promise<boolean> {
return this.orgsMap.delete(parseInt(id));
}
// Domains
async getDomain(id: string): Promise<Domain | undefined> {
return this.domainsMap.get(parseInt(id));
}
async getDomainsByOrganization(organizationId: string): Promise<Domain[]> {
return Array.from(this.domainsMap.values())
.filter(domain => domain.organizationId === organizationId);
}
async getAllDomains(): Promise<Domain[]> {
return Array.from(this.domainsMap.values());
}
async createDomain(domain: InsertDomain): Promise<Domain> {
const id = this.domainIdCounter++;
const createdAt = new Date();
const lastUpdated = new Date();
const newDomain: Domain = {
id: id.toString(),
name: domain.name,
organizationId: domain.organizationId,
providerId: domain.providerId,
isActive: domain.isActive ?? true,
lastUpdated,
createdAt
};
this.domainsMap.set(id, newDomain);
return newDomain;
}
async updateDomain(id: string, domainData: Partial<InsertDomain>): Promise<Domain | undefined> {
const numId = parseInt(id);
const domain = await this.getDomain(id);
if (!domain) return undefined;
const updatedDomain = {
...domain,
...domainData,
lastUpdated: new Date()
};
this.domainsMap.set(numId, updatedDomain);
return updatedDomain;
}
async deleteDomain(id: string): Promise<boolean> {
return this.domainsMap.delete(parseInt(id));
}
// DNS Records
async getDnsRecord(id: string): Promise<DnsRecord | undefined> {
return this.recordsMap.get(parseInt(id));
}
async getDnsRecordsByDomain(domainId: string): Promise<DnsRecord[]> {
return Array.from(this.recordsMap.values())
.filter(record => record.domainId === domainId);
}
async createDnsRecord(record: InsertDnsRecord): Promise<DnsRecord> {
const id = this.recordIdCounter++;
const createdAt = new Date();
const lastUpdated = new Date();
const newRecord: DnsRecord = {
id: id.toString(),
domainId: record.domainId,
name: record.name,
type: record.type,
content: record.content,
ttl: record.ttl ?? 3600,
proxied: record.proxied ?? false,
isActive: record.isActive ?? true,
isAutoIP: record.isAutoIP ?? false,
notes: record.notes ?? null,
lastUpdated,
createdAt
};
this.recordsMap.set(id, newRecord);
return newRecord;
}
async updateDnsRecord(id: string, recordData: Partial<InsertDnsRecord>): Promise<DnsRecord | undefined> {
const numId = parseInt(id);
const record = await this.getDnsRecord(id);
if (!record) return undefined;
const updatedRecord = {
...record,
...recordData,
lastUpdated: new Date()
};
this.recordsMap.set(numId, updatedRecord);
return updatedRecord;
}
async deleteDnsRecord(id: string): Promise<boolean> {
return this.recordsMap.delete(parseInt(id));
}
// Providers
async getProvider(id: string): Promise<Provider | undefined> {
return this.providersMap.get(parseInt(id));
}
async getProviders(): Promise<Provider[]> {
return Array.from(this.providersMap.values());
}
async createProvider(provider: InsertProvider): Promise<Provider> {
const id = this.providerIdCounter++;
const createdAt = new Date();
const newProvider: Provider = {
id: id.toString(),
name: provider.name,
type: provider.type,
credentials: provider.credentials ?? null,
isActive: provider.isActive ?? true,
createdAt
};
this.providersMap.set(id, newProvider);
return newProvider;
}
async updateProvider(id: string, providerData: Partial<InsertProvider>): Promise<Provider | undefined> {
const numId = parseInt(id);
const provider = await this.getProvider(id);
if (!provider) return undefined;
const updatedProvider = { ...provider, ...providerData };
this.providersMap.set(numId, updatedProvider);
return updatedProvider;
}
async deleteProvider(id: string): Promise<boolean> {
return this.providersMap.delete(parseInt(id));
}
// API Tokens
async getApiToken(id: string): Promise<ApiToken | undefined> {
return this.apiTokensMap.get(parseInt(id));
}
async getApiTokenByToken(token: string): Promise<ApiToken | undefined> {
return Array.from(this.apiTokensMap.values())
.find(apiToken => apiToken.token === token);
}
async getApiTokensByOrganization(organizationId: string): Promise<ApiToken[]> {
return Array.from(this.apiTokensMap.values())
.filter(token => token.organizationId === organizationId);
}
async createApiToken(token: InsertApiToken): Promise<ApiToken> {
const id = this.apiTokenIdCounter++;
const createdAt = new Date();
const newToken: ApiToken = {
id: id.toString(),
name: token.name,
token: token.token,
organizationId: token.organizationId,
permissions: token.permissions ?? null,
createdBy: token.createdBy,
isActive: token.isActive ?? true,
expiresAt: token.expiresAt ?? null,
createdAt
};
this.apiTokensMap.set(id, newToken);
return newToken;
}
async updateApiToken(id: string, tokenData: Partial<InsertApiToken>): Promise<ApiToken | undefined> {
const numId = parseInt(id);
const token = await this.getApiToken(id);
if (!token) return undefined;
const updatedToken = { ...token, ...tokenData };
this.apiTokensMap.set(numId, updatedToken);
return updatedToken;
}
async deleteApiToken(id: string): Promise<boolean> {
return this.apiTokensMap.delete(parseInt(id));
}
// DNS History
async addDnsHistory(
recordId: number,
action: string,
previousValue?: string,
newValue?: string,
userId?: number
): Promise<DnsHistory> {
const id = this.historyIdCounter++;
const timestamp = new Date();
const historyEntry: DnsHistory = {
id,
recordId,
action,
previousValue: previousValue ?? null,
newValue: newValue ?? null,
userId: userId ?? null,
timestamp
};
this.historyMap.set(id, historyEntry);
return historyEntry;
}
async getDnsHistoryByRecord(recordId: number): Promise<DnsHistory[]> {
return Array.from(this.historyMap.values())
.filter(history => history.recordId === recordId)
.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
}
async getDnsHistoryByDomain(domainId: number): Promise<DnsHistory[]> {
// Get all records for domain
const records = await this.getDnsRecordsByDomain(domainId);
const recordIds = records.map(r => r.id);
// Get history entries for all records
return Array.from(this.historyMap.values())
.filter(history => recordIds.includes(history.recordId))
.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
}
}
export const storage = new DatabaseStorage();