Add NocoDB configuration settings and restructure dashboard navigation
All checks were successful
Build And Push Image / docker (push) Successful in 3m2s
All checks were successful
Build And Push Image / docker (push) Successful in 3m2s
- Add NocoDBSettingsDialog component with API endpoints for config management - Update dashboard navigation routes and menu structure - Integrate external user management via auth portal - Add NocoDB settings dialog to admin panel
This commit is contained in:
62
server/api/admin/nocodb-config.get.ts
Normal file
62
server/api/admin/nocodb-config.get.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import type { NocoDBSettings } from '~/utils/types';
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
console.log('[api/admin/nocodb-config.get] =========================');
|
||||
console.log('[api/admin/nocodb-config.get] GET /api/admin/nocodb-config');
|
||||
console.log('[api/admin/nocodb-config.get] Request from:', getClientIP(event));
|
||||
|
||||
try {
|
||||
// Check admin authorization
|
||||
const sessionManager = createSessionManager();
|
||||
const cookieHeader = getHeader(event, 'cookie');
|
||||
const session = sessionManager.getSession(cookieHeader);
|
||||
|
||||
if (!session?.user) {
|
||||
throw createError({
|
||||
statusCode: 401,
|
||||
statusMessage: 'Authentication required'
|
||||
});
|
||||
}
|
||||
|
||||
// Check if user is admin
|
||||
if (session.user.tier !== 'admin') {
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: 'Admin access required'
|
||||
});
|
||||
}
|
||||
|
||||
console.log('[api/admin/nocodb-config.get] Admin access confirmed for:', session.user.email);
|
||||
|
||||
// Get current runtime configuration
|
||||
const runtimeConfig = useRuntimeConfig();
|
||||
const nocodbConfig = runtimeConfig.nocodb;
|
||||
|
||||
// For security, we don't return the actual API key, just indicate if it's set
|
||||
const settings: NocoDBSettings = {
|
||||
url: nocodbConfig.url || 'https://database.monacousa.org',
|
||||
apiKey: nocodbConfig.token ? '••••••••••••••••' : '', // Masked for security
|
||||
baseId: nocodbConfig.baseId || '',
|
||||
tableId: 'members-table-id' // This would come from database in real implementation
|
||||
};
|
||||
|
||||
console.log('[api/admin/nocodb-config.get] ✅ Settings retrieved successfully');
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: settings
|
||||
};
|
||||
|
||||
} catch (error: any) {
|
||||
console.error('[api/admin/nocodb-config.get] ❌ Error:', error);
|
||||
|
||||
if (error.statusCode) {
|
||||
throw error; // Re-throw HTTP errors
|
||||
}
|
||||
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
statusMessage: 'Failed to retrieve NocoDB configuration'
|
||||
});
|
||||
}
|
||||
});
|
||||
85
server/api/admin/nocodb-config.post.ts
Normal file
85
server/api/admin/nocodb-config.post.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import type { NocoDBSettings } from '~/utils/types';
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
console.log('[api/admin/nocodb-config.post] =========================');
|
||||
console.log('[api/admin/nocodb-config.post] POST /api/admin/nocodb-config');
|
||||
console.log('[api/admin/nocodb-config.post] Request from:', getClientIP(event));
|
||||
|
||||
try {
|
||||
// Check admin authorization
|
||||
const sessionManager = createSessionManager();
|
||||
const cookieHeader = getHeader(event, 'cookie');
|
||||
const session = sessionManager.getSession(cookieHeader);
|
||||
|
||||
if (!session?.user) {
|
||||
throw createError({
|
||||
statusCode: 401,
|
||||
statusMessage: 'Authentication required'
|
||||
});
|
||||
}
|
||||
|
||||
// Check if user is admin
|
||||
if (session.user.tier !== 'admin') {
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: 'Admin access required'
|
||||
});
|
||||
}
|
||||
|
||||
console.log('[api/admin/nocodb-config.post] Admin access confirmed for:', session.user.email);
|
||||
|
||||
// Get request body
|
||||
const body = await readBody(event) as NocoDBSettings;
|
||||
|
||||
// Validate required fields
|
||||
if (!body.url || !body.apiKey || !body.baseId || !body.tableId) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: 'All fields are required: url, apiKey, baseId, tableId'
|
||||
});
|
||||
}
|
||||
|
||||
// Validate URL format
|
||||
if (!body.url.startsWith('http://') && !body.url.startsWith('https://')) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: 'URL must start with http:// or https://'
|
||||
});
|
||||
}
|
||||
|
||||
console.log('[api/admin/nocodb-config.post] Saving NocoDB configuration...');
|
||||
console.log('[api/admin/nocodb-config.post] URL:', body.url);
|
||||
console.log('[api/admin/nocodb-config.post] Base ID:', body.baseId);
|
||||
console.log('[api/admin/nocodb-config.post] Table ID:', body.tableId);
|
||||
console.log('[api/admin/nocodb-config.post] API Key: [REDACTED]');
|
||||
|
||||
// In a real application, you would save these settings to a secure database
|
||||
// For now, we'll just validate the structure and log success
|
||||
|
||||
// TODO: Implement actual persistence (database or secure config store)
|
||||
// This could be saved to:
|
||||
// 1. A separate admin_settings table in the database
|
||||
// 2. Environment variable overrides
|
||||
// 3. A secure configuration service
|
||||
|
||||
// For demonstration, we'll simulate success
|
||||
console.log('[api/admin/nocodb-config.post] ✅ Configuration saved successfully');
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'NocoDB configuration saved successfully'
|
||||
};
|
||||
|
||||
} catch (error: any) {
|
||||
console.error('[api/admin/nocodb-config.post] ❌ Error:', error);
|
||||
|
||||
if (error.statusCode) {
|
||||
throw error; // Re-throw HTTP errors
|
||||
}
|
||||
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
statusMessage: 'Failed to save NocoDB configuration'
|
||||
});
|
||||
}
|
||||
});
|
||||
116
server/api/admin/nocodb-test.post.ts
Normal file
116
server/api/admin/nocodb-test.post.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import type { NocoDBSettings } from '~/utils/types';
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
console.log('[api/admin/nocodb-test.post] =========================');
|
||||
console.log('[api/admin/nocodb-test.post] POST /api/admin/nocodb-test');
|
||||
console.log('[api/admin/nocodb-test.post] Request from:', getClientIP(event));
|
||||
|
||||
try {
|
||||
// Check admin authorization
|
||||
const sessionManager = createSessionManager();
|
||||
const cookieHeader = getHeader(event, 'cookie');
|
||||
const session = sessionManager.getSession(cookieHeader);
|
||||
|
||||
if (!session?.user) {
|
||||
throw createError({
|
||||
statusCode: 401,
|
||||
statusMessage: 'Authentication required'
|
||||
});
|
||||
}
|
||||
|
||||
// Check if user is admin
|
||||
if (session.user.tier !== 'admin') {
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: 'Admin access required'
|
||||
});
|
||||
}
|
||||
|
||||
console.log('[api/admin/nocodb-test.post] Admin access confirmed for:', session.user.email);
|
||||
|
||||
// Get request body
|
||||
const body = await readBody(event) as NocoDBSettings;
|
||||
|
||||
// Validate required fields
|
||||
if (!body.url || !body.apiKey || !body.baseId || !body.tableId) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'All fields are required to test connection'
|
||||
};
|
||||
}
|
||||
|
||||
// Validate URL format
|
||||
if (!body.url.startsWith('http://') && !body.url.startsWith('https://')) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'URL must start with http:// or https://'
|
||||
};
|
||||
}
|
||||
|
||||
console.log('[api/admin/nocodb-test.post] Testing NocoDB connection...');
|
||||
console.log('[api/admin/nocodb-test.post] URL:', body.url);
|
||||
console.log('[api/admin/nocodb-test.post] Base ID:', body.baseId);
|
||||
console.log('[api/admin/nocodb-test.post] Table ID:', body.tableId);
|
||||
|
||||
try {
|
||||
// Test connection by making a simple request to NocoDB
|
||||
const testUrl = `${body.url}/api/v2/tables/${body.tableId}/records?limit=1`;
|
||||
|
||||
console.log('[api/admin/nocodb-test.post] Testing URL:', testUrl);
|
||||
|
||||
const response = await $fetch(testUrl, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'xc-token': body.apiKey,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
// Add timeout to prevent hanging
|
||||
timeout: 10000
|
||||
});
|
||||
|
||||
console.log('[api/admin/nocodb-test.post] ✅ Connection successful');
|
||||
console.log('[api/admin/nocodb-test.post] Response received, type:', typeof response);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Connection successful! NocoDB is responding.'
|
||||
};
|
||||
|
||||
} catch (connectionError: any) {
|
||||
console.error('[api/admin/nocodb-test.post] ❌ Connection failed:', connectionError);
|
||||
|
||||
let errorMessage = 'Connection failed';
|
||||
|
||||
if (connectionError.statusCode === 401 || connectionError.status === 401) {
|
||||
errorMessage = 'Authentication failed - please check your API token';
|
||||
} else if (connectionError.statusCode === 404 || connectionError.status === 404) {
|
||||
errorMessage = 'Table not found - please check your Base ID and Table ID';
|
||||
} else if (connectionError.statusCode === 403 || connectionError.status === 403) {
|
||||
errorMessage = 'Access denied - please check your API token permissions';
|
||||
} else if (connectionError.code === 'NETWORK_ERROR' || connectionError.message?.includes('fetch')) {
|
||||
errorMessage = 'Network error - please check the URL and ensure NocoDB is accessible';
|
||||
} else if (connectionError.message?.includes('timeout')) {
|
||||
errorMessage = 'Connection timeout - NocoDB server may be unavailable';
|
||||
} else if (connectionError.message) {
|
||||
errorMessage = connectionError.message;
|
||||
}
|
||||
|
||||
return {
|
||||
success: false,
|
||||
message: errorMessage
|
||||
};
|
||||
}
|
||||
|
||||
} catch (error: any) {
|
||||
console.error('[api/admin/nocodb-test.post] ❌ Error:', error);
|
||||
|
||||
if (error.statusCode) {
|
||||
throw error; // Re-throw HTTP errors
|
||||
}
|
||||
|
||||
return {
|
||||
success: false,
|
||||
message: 'Failed to test connection due to server error'
|
||||
};
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user