Fix API token creation issues by improving data handling and default values.

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/61cfb37c-5c5b-400f-b068-24cfbbdc7a23.jpg
This commit is contained in:
alphaeusmote
2025-04-11 17:33:23 +00:00
parent 7084050128
commit fbc0464b00
2 changed files with 83 additions and 46 deletions
+41 -39
View File
@@ -974,100 +974,102 @@ export async function registerRoutes(app: Express): Promise<Server> {
// Generate a random token
const tokenValue = randomBytes(32).toString('hex');
// Extract fields from request body, with defaults where needed
const name = req.body.name || "Unnamed Token";
const role = req.body.role || "readonly";
const organizationId = req.body.organizationId || "1";
const isActive = req.body.isActive !== undefined ? req.body.isActive : true;
// Set default permissions based on the role
let permissions = [];
if (role === 'admin') {
permissions = ['admin', 'manager', 'user', 'readonly'];
} else if (role === 'manager') {
permissions = ['manager', 'user', 'readonly'];
} else if (role === 'user') {
permissions = ['user', 'readonly'];
} else {
permissions = ['readonly'];
}
// Create token data as a plain object (bypass schema validation)
const tokenData = {
name: name,
// Get data directly from the form
let tokenData: any = {
// Required fields
name: req.body.name || "Unnamed Token",
token: tokenValue,
organizationId: organizationId,
permissions: permissions,
role: role,
createdBy: req.user?.id || '1',
isActive: isActive
organizationId: req.body.organizationId || "1",
role: req.body.role || "readonly",
createdBy: req.user?.id || "1",
// Optional fields
isActive: req.body.isActive !== undefined ? req.body.isActive : true,
permissions: [] // Will be populated in storage.ts
};
// Handle expiration date directly from form data
// Handle expiration date
if (req.body.expiresIn && req.body.expiresIn !== 'never') {
const now = new Date();
if (req.body.expiresIn === 'custom' && req.body.customDate) {
// For custom date/time
try {
console.log("Custom date received:", req.body.customDate);
console.log("Custom time received:", req.body.customTime || "none");
// Create date from input
const customDate = new Date(req.body.customDate);
console.log("Parsed customDate:", customDate);
// If time was selected, add it to the date
if (req.body.customTime) {
const [hours, minutes] = req.body.customTime.split(':').map(Number);
if (!isNaN(hours) && !isNaN(minutes)) {
customDate.setHours(hours, minutes, 0, 0);
console.log(`Setting time to ${hours}:${minutes}`);
} else {
customDate.setHours(23, 59, 59, 999);
console.log("Invalid time format, setting to end of day");
}
} else {
customDate.setHours(23, 59, 59, 999);
console.log("No time specified, setting to end of day");
}
tokenData.expiresAt = customDate;
console.log("Custom expiration date set to:", customDate);
console.log("Final custom expiration date:", customDate);
} catch (e) {
console.error("Error parsing custom date:", e);
}
} else {
// For preset expiration options
let daysToAdd = 0;
let expirationDate: Date | null = null;
switch (req.body.expiresIn) {
case '1hour':
tokenData.expiresAt = new Date(now.getTime() + 60 * 60 * 1000);
expirationDate = new Date(now.getTime() + 60 * 60 * 1000);
break;
case '1day':
tokenData.expiresAt = new Date(now.getTime() + 24 * 60 * 60 * 1000);
expirationDate = new Date(now.getTime() + 24 * 60 * 60 * 1000);
break;
case '7days':
tokenData.expiresAt = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
expirationDate = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
break;
case '30days':
tokenData.expiresAt = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000);
expirationDate = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000);
break;
case '90days':
tokenData.expiresAt = new Date(now.getTime() + 90 * 24 * 60 * 60 * 1000);
expirationDate = new Date(now.getTime() + 90 * 24 * 60 * 60 * 1000);
break;
case '1year':
tokenData.expiresAt = new Date(now.getTime() + 365 * 24 * 60 * 60 * 1000);
expirationDate = new Date(now.getTime() + 365 * 24 * 60 * 60 * 1000);
break;
}
if (expirationDate) {
tokenData.expiresAt = expirationDate;
console.log(`Setting expiration to ${req.body.expiresIn}:`, expirationDate);
}
}
} else {
console.log("No expiration set (never expires)");
}
console.log("Final token data for storage:", tokenData);
console.log("Final token data for storage:", JSON.stringify(tokenData, null, 2));
// Skip schema validation, call storage directly
// Pass data directly to storage
const token = await storage.createApiToken(tokenData);
console.log("Token created successfully:", JSON.stringify(token, null, 2));
// Return the full token only on creation
res.status(201).json(token);
} catch (error) {
console.error("Error creating API token:", error);
// Return detailed error to help debugging
res.status(500).json({
message: "Error creating token",
details: error instanceof Error ? error.message : String(error)
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined
});
}
});
+42 -7
View File
@@ -480,21 +480,56 @@ export class MemStorage implements IStorage {
.filter(token => token.organizationId === organizationId);
}
async createApiToken(token: InsertApiToken): Promise<ApiToken> {
async createApiToken(token: any): Promise<ApiToken> {
console.log("Storage createApiToken received:", JSON.stringify(token, null, 2));
const numId = this.apiTokenIdCounter++;
const createdAt = new Date();
// Generate default permissions if none provided
let permissions: string[] = [];
if (token.permissions && Array.isArray(token.permissions)) {
permissions = token.permissions;
} else if (token.role) {
// Default permissions based on role if not explicitly provided
if (token.role === 'admin') {
permissions = ['admin', 'manager', 'user', 'readonly'];
} else if (token.role === 'manager') {
permissions = ['manager', 'user', 'readonly'];
} else if (token.role === 'user') {
permissions = ['user', 'readonly'];
} else {
permissions = ['readonly'];
}
}
// Handle expiresAt
let expiresAt = null;
if (token.expiresAt) {
if (token.expiresAt instanceof Date) {
expiresAt = token.expiresAt;
} else if (typeof token.expiresAt === 'string') {
try {
expiresAt = new Date(token.expiresAt);
} catch (e) {
console.error("Failed to parse expiresAt date string:", token.expiresAt);
}
}
}
const newToken: ApiToken = {
id: numId.toString(),
name: token.name,
token: token.token,
organizationId: token.organizationId,
permissions: token.permissions ?? null,
name: token.name || "Unnamed Token",
token: token.token || "test_token_" + numId,
organizationId: token.organizationId || "1",
permissions: permissions,
role: token.role || 'readonly',
createdBy: token.createdBy,
createdBy: token.createdBy || "1",
isActive: token.isActive ?? true,
expiresAt: token.expiresAt ?? null,
expiresAt: expiresAt,
createdAt
};
console.log("Storing new token:", JSON.stringify(newToken, null, 2));
this.apiTokensMap.set(numId, newToken);
return newToken;
}