mirror of
https://github.com/freedbygrace/DynamoDNS.git
synced 2026-07-26 11:38:13 +00:00
Add user-customer assignment management API endpoints.
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/f61cca86-ab28-414a-8579-18e14f115a0f.jpg
This commit is contained in:
+432
-1
@@ -4,7 +4,16 @@ import { storage } from "./storage";
|
||||
import { getCurrentIpAddress, getCurrentIpv6Address } from "./utils/ip-utils";
|
||||
import { setupAuth, requireRole } from "./auth";
|
||||
import { z } from "zod";
|
||||
import { insertCustomerSchema, insertDomainSchema, insertDnsRecordSchema } from "@shared/schema";
|
||||
import {
|
||||
insertCustomerSchema,
|
||||
insertDomainSchema,
|
||||
insertDnsRecordSchema,
|
||||
insertCustomerUserAssignmentSchema,
|
||||
insertProviderSchema,
|
||||
insertDomainCredentialsSchema,
|
||||
insertApiTokenSchema,
|
||||
insertCustomRoleSchema
|
||||
} from "@shared/schema";
|
||||
|
||||
export async function registerRoutes(app: Express): Promise<Server> {
|
||||
// Create HTTP server
|
||||
@@ -323,6 +332,428 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
// Customer-User Assignment routes - for managing user access to customers
|
||||
app.get("/api/customer-users", requireRole(["admin", "manager"]), async (req, res) => {
|
||||
try {
|
||||
const { customerId, userId } = req.query;
|
||||
|
||||
let assignments = [];
|
||||
if (customerId) {
|
||||
// Get all users assigned to a specific customer
|
||||
assignments = await storage.getCustomerUsers(customerId as string);
|
||||
} else if (userId) {
|
||||
// Get all customers assigned to a specific user
|
||||
assignments = await storage.getUserCustomers(userId as string);
|
||||
} else {
|
||||
return res.status(400).json({ message: "Either customerId or userId query parameter is required" });
|
||||
}
|
||||
|
||||
res.json(assignments);
|
||||
} catch (error) {
|
||||
console.error("Error getting customer-user assignments:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/api/customer-users", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const validatedData = insertCustomerUserAssignmentSchema.parse(req.body);
|
||||
const assignment = await storage.assignUserToCustomer(validatedData);
|
||||
res.status(201).json(assignment);
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({ message: "Validation error", errors: error.errors });
|
||||
} else {
|
||||
console.error("Error creating customer-user assignment:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
app.put("/api/customer-users", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const { customerId, userId, role } = req.body;
|
||||
|
||||
if (!customerId || !userId || !role) {
|
||||
return res.status(400).json({ message: "customerId, userId, and role are required" });
|
||||
}
|
||||
|
||||
const assignment = await storage.updateUserCustomerRole(customerId, userId, role);
|
||||
if (!assignment) {
|
||||
return res.status(404).json({ message: "Customer-user assignment not found" });
|
||||
}
|
||||
|
||||
res.json(assignment);
|
||||
} catch (error) {
|
||||
console.error("Error updating customer-user role:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
app.delete("/api/customer-users", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const { customerId, userId } = req.query;
|
||||
|
||||
if (!customerId || !userId) {
|
||||
return res.status(400).json({ message: "customerId and userId query parameters are required" });
|
||||
}
|
||||
|
||||
const success = await storage.removeUserFromCustomer(customerId as string, userId as string);
|
||||
if (!success) {
|
||||
return res.status(404).json({ message: "Customer-user assignment not found" });
|
||||
}
|
||||
|
||||
res.status(204).end();
|
||||
} catch (error) {
|
||||
console.error("Error deleting customer-user assignment:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
// Provider routes
|
||||
app.get("/api/providers", requireRole(["admin", "manager", "user", "readonly"]), async (req, res) => {
|
||||
try {
|
||||
const providers = await storage.getProviders();
|
||||
res.json(providers);
|
||||
} catch (error) {
|
||||
console.error("Error getting providers:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
app.get("/api/providers/:id", requireRole(["admin", "manager", "user", "readonly"]), async (req, res) => {
|
||||
try {
|
||||
const provider = await storage.getProvider(req.params.id);
|
||||
if (!provider) {
|
||||
return res.status(404).json({ message: "Provider not found" });
|
||||
}
|
||||
res.json(provider);
|
||||
} catch (error) {
|
||||
console.error("Error getting provider:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/api/providers", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const validatedData = insertProviderSchema.parse(req.body);
|
||||
const provider = await storage.createProvider(validatedData);
|
||||
res.status(201).json(provider);
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({ message: "Validation error", errors: error.errors });
|
||||
} else {
|
||||
console.error("Error creating provider:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
app.put("/api/providers/:id", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const validatedData = insertProviderSchema.partial().parse(req.body);
|
||||
const provider = await storage.updateProvider(req.params.id, validatedData);
|
||||
if (!provider) {
|
||||
return res.status(404).json({ message: "Provider not found" });
|
||||
}
|
||||
res.json(provider);
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({ message: "Validation error", errors: error.errors });
|
||||
} else {
|
||||
console.error("Error updating provider:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
app.delete("/api/providers/:id", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const success = await storage.deleteProvider(req.params.id);
|
||||
if (!success) {
|
||||
return res.status(404).json({ message: "Provider not found" });
|
||||
}
|
||||
res.status(204).end();
|
||||
} catch (error) {
|
||||
console.error("Error deleting provider:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
// Domain Credentials routes
|
||||
app.get("/api/domain-credentials/:domainId", requireRole(["admin", "manager"]), async (req, res) => {
|
||||
try {
|
||||
const credentials = await storage.getDomainCredentials(req.params.domainId);
|
||||
if (!credentials) {
|
||||
return res.status(404).json({ message: "Domain credentials not found" });
|
||||
}
|
||||
res.json(credentials);
|
||||
} catch (error) {
|
||||
console.error("Error getting domain credentials:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/api/domain-credentials", requireRole(["admin", "manager"]), async (req, res) => {
|
||||
try {
|
||||
const validatedData = insertDomainCredentialsSchema.parse(req.body);
|
||||
const credentials = await storage.createDomainCredentials(validatedData);
|
||||
res.status(201).json(credentials);
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({ message: "Validation error", errors: error.errors });
|
||||
} else {
|
||||
console.error("Error creating domain credentials:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
app.put("/api/domain-credentials/:domainId", requireRole(["admin", "manager"]), async (req, res) => {
|
||||
try {
|
||||
const validatedData = insertDomainCredentialsSchema.partial().parse(req.body);
|
||||
const credentials = await storage.updateDomainCredentials(req.params.domainId, validatedData);
|
||||
if (!credentials) {
|
||||
return res.status(404).json({ message: "Domain credentials not found" });
|
||||
}
|
||||
res.json(credentials);
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({ message: "Validation error", errors: error.errors });
|
||||
} else {
|
||||
console.error("Error updating domain credentials:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// API Token routes
|
||||
app.get("/api/api-tokens", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const { customerId } = req.query;
|
||||
|
||||
let tokens = [];
|
||||
if (customerId) {
|
||||
tokens = await storage.getApiTokensByCustomer(customerId as string);
|
||||
} else {
|
||||
tokens = await storage.getApiTokens();
|
||||
}
|
||||
|
||||
// Mask the actual token values for security
|
||||
const maskedTokens = tokens.map(token => ({
|
||||
...token,
|
||||
token: token.token ? token.token.substring(0, 6) + "************" : null
|
||||
}));
|
||||
|
||||
res.json(maskedTokens);
|
||||
} catch (error) {
|
||||
console.error("Error getting API tokens:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
app.get("/api/api-tokens/:id", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const token = await storage.getApiToken(req.params.id);
|
||||
if (!token) {
|
||||
return res.status(404).json({ message: "API token not found" });
|
||||
}
|
||||
|
||||
// Mask the actual token value for security
|
||||
const maskedToken = {
|
||||
...token,
|
||||
token: token.token ? token.token.substring(0, 6) + "************" : null
|
||||
};
|
||||
|
||||
res.json(maskedToken);
|
||||
} catch (error) {
|
||||
console.error("Error getting API token:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/api/api-tokens", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const validatedData = insertApiTokenSchema.parse(req.body);
|
||||
|
||||
// Add the current user as the creator if not specified
|
||||
if (!validatedData.createdBy && req.user) {
|
||||
validatedData.createdBy = req.user.id;
|
||||
}
|
||||
|
||||
const token = await storage.createApiToken(validatedData);
|
||||
|
||||
// Return the full token value only once during creation
|
||||
res.status(201).json(token);
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({ message: "Validation error", errors: error.errors });
|
||||
} else {
|
||||
console.error("Error creating API token:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
app.put("/api/api-tokens/:id", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const validatedData = insertApiTokenSchema.partial().parse(req.body);
|
||||
const token = await storage.updateApiToken(req.params.id, validatedData);
|
||||
if (!token) {
|
||||
return res.status(404).json({ message: "API token not found" });
|
||||
}
|
||||
|
||||
// Mask the token value for security in the response
|
||||
const maskedToken = {
|
||||
...token,
|
||||
token: token.token ? token.token.substring(0, 6) + "************" : null
|
||||
};
|
||||
|
||||
res.json(maskedToken);
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({ message: "Validation error", errors: error.errors });
|
||||
} else {
|
||||
console.error("Error updating API token:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
app.delete("/api/api-tokens/:id", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const success = await storage.deleteApiToken(req.params.id);
|
||||
if (!success) {
|
||||
return res.status(404).json({ message: "API token not found" });
|
||||
}
|
||||
res.status(204).end();
|
||||
} catch (error) {
|
||||
console.error("Error deleting API token:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
// API Token Customer Access routes
|
||||
app.get("/api/api-token-access/:tokenId", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const access = await storage.getApiTokenCustomerAccess(req.params.tokenId);
|
||||
res.json(access);
|
||||
} catch (error) {
|
||||
console.error("Error getting API token customer access:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/api/api-token-access", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const { tokenId, customerId } = req.body;
|
||||
|
||||
if (!tokenId || !customerId) {
|
||||
return res.status(400).json({ message: "tokenId and customerId are required" });
|
||||
}
|
||||
|
||||
const access = await storage.addApiTokenCustomerAccess({
|
||||
tokenId,
|
||||
customerId
|
||||
});
|
||||
|
||||
res.status(201).json(access);
|
||||
} catch (error) {
|
||||
console.error("Error adding API token customer access:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
app.delete("/api/api-token-access", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const { tokenId, customerId } = req.query;
|
||||
|
||||
if (!tokenId || !customerId) {
|
||||
return res.status(400).json({ message: "tokenId and customerId query parameters are required" });
|
||||
}
|
||||
|
||||
const success = await storage.removeApiTokenCustomerAccess(tokenId as string, customerId as string);
|
||||
if (!success) {
|
||||
return res.status(404).json({ message: "API token customer access not found" });
|
||||
}
|
||||
|
||||
res.status(204).end();
|
||||
} catch (error) {
|
||||
console.error("Error removing API token customer access:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
// Custom Roles routes
|
||||
app.get("/api/custom-roles", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const roles = await storage.getCustomRoles();
|
||||
res.json(roles);
|
||||
} catch (error) {
|
||||
console.error("Error getting custom roles:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
app.get("/api/custom-roles/:id", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const role = await storage.getCustomRole(req.params.id);
|
||||
if (!role) {
|
||||
return res.status(404).json({ message: "Custom role not found" });
|
||||
}
|
||||
res.json(role);
|
||||
} catch (error) {
|
||||
console.error("Error getting custom role:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/api/custom-roles", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const validatedData = insertCustomRoleSchema.parse(req.body);
|
||||
const role = await storage.createCustomRole(validatedData);
|
||||
res.status(201).json(role);
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({ message: "Validation error", errors: error.errors });
|
||||
} else {
|
||||
console.error("Error creating custom role:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
app.put("/api/custom-roles/:id", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const validatedData = insertCustomRoleSchema.partial().parse(req.body);
|
||||
const role = await storage.updateCustomRole(req.params.id, validatedData);
|
||||
if (!role) {
|
||||
return res.status(404).json({ message: "Custom role not found" });
|
||||
}
|
||||
res.json(role);
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({ message: "Validation error", errors: error.errors });
|
||||
} else {
|
||||
console.error("Error updating custom role:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
app.delete("/api/custom-roles/:id", requireRole(["admin"]), async (req, res) => {
|
||||
try {
|
||||
const success = await storage.deleteCustomRole(req.params.id);
|
||||
if (!success) {
|
||||
return res.status(404).json({ message: "Custom role not found" });
|
||||
}
|
||||
res.status(204).end();
|
||||
} catch (error) {
|
||||
console.error("Error deleting custom role:", error);
|
||||
res.status(500).json({ message: "Internal server error" });
|
||||
}
|
||||
});
|
||||
|
||||
return httpServer;
|
||||
}
|
||||
Reference in New Issue
Block a user