Refactor NocoDB settings to support dynamic table configuration and update related validation
Build And Push Image / docker (push) Successful in 3m13s
Details
Build And Push Image / docker (push) Successful in 3m13s
Details
This commit is contained in:
parent
d0d7a34ae7
commit
22a74c6b33
|
|
@ -68,7 +68,7 @@
|
|||
/>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" md="6">
|
||||
<v-col cols="12">
|
||||
<v-text-field
|
||||
v-model="form.baseId"
|
||||
label="Base ID"
|
||||
|
|
@ -80,18 +80,25 @@
|
|||
:error-messages="getFieldError('baseId')"
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12">
|
||||
<h3 class="text-h6 mb-4 text-primary">Table Configuration</h3>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" md="6">
|
||||
<v-col cols="12">
|
||||
<v-text-field
|
||||
v-model="form.tableId"
|
||||
v-model="form.tables.members"
|
||||
label="Members Table ID"
|
||||
variant="outlined"
|
||||
:rules="[rules.required]"
|
||||
required
|
||||
placeholder="members-table-id"
|
||||
:error="hasFieldError('tableId')"
|
||||
:error-messages="getFieldError('tableId')"
|
||||
:error="hasFieldError('tables.members')"
|
||||
:error-messages="getFieldError('tables.members')"
|
||||
/>
|
||||
<div class="text-caption text-medium-emphasis mt-1">
|
||||
Configure the table ID for the Members functionality
|
||||
</div>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12">
|
||||
|
|
@ -210,7 +217,7 @@ const form = ref<NocoDBSettings>({
|
|||
url: 'https://database.monacousa.org',
|
||||
apiKey: '',
|
||||
baseId: '',
|
||||
tableId: ''
|
||||
tables: { members: '' }
|
||||
});
|
||||
|
||||
// Error handling
|
||||
|
|
@ -261,6 +268,10 @@ const loadSettings = async () => {
|
|||
|
||||
if (response.success && response.data) {
|
||||
form.value = { ...response.data };
|
||||
// Ensure tables object exists
|
||||
if (!form.value.tables) {
|
||||
form.value.tables = { members: '' };
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('Failed to load NocoDB settings:', error);
|
||||
|
|
@ -352,7 +363,7 @@ const resetForm = () => {
|
|||
url: 'https://database.monacousa.org',
|
||||
apiKey: '',
|
||||
baseId: '',
|
||||
tableId: ''
|
||||
tables: { members: '' }
|
||||
};
|
||||
clearFieldErrors();
|
||||
connectionStatus.value = null;
|
||||
|
|
|
|||
|
|
@ -32,10 +32,10 @@ export default defineEventHandler(async (event) => {
|
|||
const body = await readBody(event) as NocoDBSettings;
|
||||
|
||||
// Validate required fields
|
||||
if (!body.url || !body.apiKey || !body.baseId || !body.tableId) {
|
||||
if (!body.url || !body.apiKey || !body.baseId || !body.tables) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: 'All fields are required: url, apiKey, baseId, tableId'
|
||||
statusMessage: 'All fields are required: url, apiKey, baseId, tables'
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ export default defineEventHandler(async (event) => {
|
|||
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] Tables:', Object.keys(body.tables));
|
||||
console.log('[api/admin/nocodb-config.post] API Key: [REDACTED]');
|
||||
|
||||
// Save configuration using the new admin config system
|
||||
|
|
|
|||
|
|
@ -32,10 +32,10 @@ export default defineEventHandler(async (event) => {
|
|||
const body = await readBody(event) as NocoDBSettings;
|
||||
|
||||
// Validate required fields
|
||||
if (!body.url || !body.apiKey || !body.baseId || !body.tableId) {
|
||||
if (!body.url || !body.apiKey || !body.baseId || !body.tables || Object.keys(body.tables).length === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'All fields are required to test connection'
|
||||
message: 'All fields are required to test connection (url, apiKey, baseId, and at least one table)'
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -50,11 +50,13 @@ export default defineEventHandler(async (event) => {
|
|||
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);
|
||||
console.log('[api/admin/nocodb-test.post] Tables:', Object.keys(body.tables));
|
||||
|
||||
try {
|
||||
// Test connection by making a simple request to NocoDB
|
||||
const testUrl = `${body.url}/api/v2/tables/${body.tableId}/records?limit=1`;
|
||||
// Test connection by making a simple request to NocoDB using the first table
|
||||
const firstTableName = Object.keys(body.tables)[0];
|
||||
const firstTableId = body.tables[firstTableName];
|
||||
const testUrl = `${body.url}/api/v2/tables/${firstTableId}/records?limit=1`;
|
||||
|
||||
console.log('[api/admin/nocodb-test.post] Testing URL:', testUrl);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { readFile, writeFile, mkdir, access, constants } from 'fs/promises';
|
||||
import { existsSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { createCipheriv, createDecipheriv, randomBytes, pbkdf2Sync } from 'crypto';
|
||||
import type { NocoDBSettings } from '~/utils/types';
|
||||
|
|
@ -13,10 +14,20 @@ interface EffectiveNocoDB {
|
|||
url: string;
|
||||
token: string;
|
||||
baseId: string;
|
||||
tableId: string;
|
||||
tables: { [tableName: string]: string };
|
||||
}
|
||||
|
||||
const CONFIG_DIR = '/app/data';
|
||||
// Support both Docker (/app/data) and local development (./data) paths
|
||||
const getConfigDir = () => {
|
||||
// Check if running in Docker container
|
||||
if (process.env.NODE_ENV === 'production' || existsSync('/app/data')) {
|
||||
return '/app/data';
|
||||
}
|
||||
// Local development
|
||||
return './data';
|
||||
};
|
||||
|
||||
const CONFIG_DIR = getConfigDir();
|
||||
const CONFIG_FILE = join(CONFIG_DIR, 'admin-config.json');
|
||||
const BACKUP_FILE = join(CONFIG_DIR, 'admin-config.backup.json');
|
||||
const LOG_FILE = join(CONFIG_DIR, 'admin-config.log');
|
||||
|
|
@ -169,6 +180,15 @@ export async function loadAdminConfig(): Promise<AdminConfiguration | null> {
|
|||
|
||||
console.log('[admin-config] Configuration loaded from file');
|
||||
configCache = config;
|
||||
|
||||
// Update global nocodb configuration
|
||||
try {
|
||||
const { setGlobalNocoDBConfig } = await import('./nocodb');
|
||||
setGlobalNocoDBConfig(getEffectiveNocoDBConfig());
|
||||
} catch (error) {
|
||||
console.error('[admin-config] Failed to update global configuration:', error);
|
||||
}
|
||||
|
||||
return config;
|
||||
} catch (error) {
|
||||
console.log('[admin-config] No configuration file found, using defaults');
|
||||
|
|
@ -207,6 +227,15 @@ export async function saveAdminConfig(config: NocoDBSettings, updatedBy: string)
|
|||
console.log('[admin-config] Configuration saved to file');
|
||||
await logConfigChange('CONFIG_SAVED', updatedBy, { url: config.url, baseId: config.baseId });
|
||||
|
||||
// Update global nocodb configuration immediately
|
||||
try {
|
||||
const { setGlobalNocoDBConfig } = await import('./nocodb');
|
||||
setGlobalNocoDBConfig(getEffectiveNocoDBConfig());
|
||||
console.log('[admin-config] Global configuration updated immediately');
|
||||
} catch (error) {
|
||||
console.error('[admin-config] Failed to update global configuration after save:', error);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('[admin-config] Failed to save configuration:', error);
|
||||
await logConfigChange('CONFIG_SAVE_FAILED', updatedBy, { error: error instanceof Error ? error.message : String(error) });
|
||||
|
|
@ -225,7 +254,7 @@ export function getEffectiveNocoDBConfig(): EffectiveNocoDB {
|
|||
url: runtimeConfig.nocodb?.url || 'https://database.monacousa.org',
|
||||
token: runtimeConfig.nocodb?.token || '',
|
||||
baseId: runtimeConfig.nocodb?.baseId || '',
|
||||
tableId: 'members-table-id' // This would be configured
|
||||
tables: { members: 'members-table-id' } // Default table mapping
|
||||
};
|
||||
|
||||
// Override with file configuration if available
|
||||
|
|
@ -234,7 +263,7 @@ export function getEffectiveNocoDBConfig(): EffectiveNocoDB {
|
|||
url: configCache.nocodb.url || envConfig.url,
|
||||
token: configCache.nocodb.apiKey || envConfig.token,
|
||||
baseId: configCache.nocodb.baseId || envConfig.baseId,
|
||||
tableId: configCache.nocodb.tableId || envConfig.tableId
|
||||
tables: configCache.nocodb.tables || envConfig.tables
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -253,7 +282,7 @@ export async function getCurrentConfig(): Promise<NocoDBSettings> {
|
|||
url: config.nocodb.url || runtimeConfig.nocodb?.url || 'https://database.monacousa.org',
|
||||
apiKey: config.nocodb.apiKey ? '••••••••••••••••' : '',
|
||||
baseId: config.nocodb.baseId || runtimeConfig.nocodb?.baseId || '',
|
||||
tableId: config.nocodb.tableId || 'members-table-id'
|
||||
tables: config.nocodb.tables || { members: 'members-table-id' }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -262,7 +291,7 @@ export async function getCurrentConfig(): Promise<NocoDBSettings> {
|
|||
url: runtimeConfig.nocodb?.url || 'https://database.monacousa.org',
|
||||
apiKey: runtimeConfig.nocodb?.token ? '••••••••••••••••' : '',
|
||||
baseId: runtimeConfig.nocodb?.baseId || '',
|
||||
tableId: 'members-table-id'
|
||||
tables: { members: 'members-table-id' }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,17 +28,13 @@ export interface EntityResponse<T> {
|
|||
|
||||
// Dynamic table ID getter - will use configured table ID from admin panel
|
||||
export const getTableId = (tableName: 'Members'): string => {
|
||||
try {
|
||||
// Try to get table ID from persistent configuration
|
||||
const { getEffectiveNocoDBConfig } = require('./admin-config');
|
||||
const effectiveConfig = getEffectiveNocoDBConfig();
|
||||
|
||||
if (tableName === 'Members' && effectiveConfig.tableId) {
|
||||
console.log(`[nocodb] Using configured table ID for ${tableName}:`, effectiveConfig.tableId);
|
||||
return effectiveConfig.tableId;
|
||||
// Try to get table ID from global configuration first
|
||||
if (globalNocoDBConfig?.tables && tableName === 'Members') {
|
||||
const tableId = globalNocoDBConfig.tables['members'] || globalNocoDBConfig.tables['Members'];
|
||||
if (tableId) {
|
||||
console.log(`[nocodb] Using global table ID for ${tableName}:`, tableId);
|
||||
return tableId;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`[nocodb] Admin config not available for table ID, using fallback`);
|
||||
}
|
||||
|
||||
// Fallback to default
|
||||
|
|
@ -102,31 +98,35 @@ export const formatNationalitiesAsString = (nationalities: string[]): string =>
|
|||
return nationalities.filter(n => n && n.trim()).join(',');
|
||||
};
|
||||
|
||||
// Global variable to store effective configuration
|
||||
let globalNocoDBConfig: any = null;
|
||||
|
||||
// Function to set the global configuration (called by the admin-config system)
|
||||
export const setGlobalNocoDBConfig = (config: any) => {
|
||||
globalNocoDBConfig = config;
|
||||
console.log('[nocodb] Global configuration updated:', config.url);
|
||||
};
|
||||
|
||||
export const getNocoDbConfiguration = () => {
|
||||
try {
|
||||
// Try to use the persistent configuration system
|
||||
const { getEffectiveNocoDBConfig } = require('./admin-config');
|
||||
const effectiveConfig = getEffectiveNocoDBConfig();
|
||||
|
||||
const config = {
|
||||
url: effectiveConfig.url,
|
||||
token: effectiveConfig.token,
|
||||
baseId: effectiveConfig.baseId
|
||||
// Try to use the global configuration first
|
||||
if (globalNocoDBConfig) {
|
||||
console.log('[nocodb] Using global configuration - URL:', globalNocoDBConfig.url);
|
||||
return {
|
||||
url: globalNocoDBConfig.url,
|
||||
token: globalNocoDBConfig.token,
|
||||
baseId: globalNocoDBConfig.baseId
|
||||
};
|
||||
|
||||
console.log('[nocodb] Using effective configuration - URL:', config.url);
|
||||
return config;
|
||||
} catch (error) {
|
||||
// Fallback to runtime config if admin config is not available
|
||||
console.log('[nocodb] Admin config not available, using runtime config');
|
||||
const config = useRuntimeConfig().nocodb;
|
||||
const fallbackConfig = {
|
||||
...config,
|
||||
url: config.url || 'https://database.monacousa.org'
|
||||
};
|
||||
console.log('[nocodb] Fallback configuration URL:', fallbackConfig.url);
|
||||
return fallbackConfig;
|
||||
}
|
||||
|
||||
// Fallback to runtime config
|
||||
console.log('[nocodb] Global config not available, using runtime config');
|
||||
const config = useRuntimeConfig().nocodb;
|
||||
const fallbackConfig = {
|
||||
...config,
|
||||
url: config.url || 'https://database.monacousa.org'
|
||||
};
|
||||
console.log('[nocodb] Fallback configuration URL:', fallbackConfig.url);
|
||||
return fallbackConfig;
|
||||
};
|
||||
|
||||
export const createTableUrl = (table: Table | string) => {
|
||||
|
|
|
|||
|
|
@ -139,10 +139,10 @@ export interface Member {
|
|||
|
||||
// Admin-only NocoDB Configuration
|
||||
export interface NocoDBSettings {
|
||||
tableId: string;
|
||||
url: string;
|
||||
apiKey: string;
|
||||
baseId: string;
|
||||
url: string;
|
||||
tables: { [tableName: string]: string }; // e.g., { "members": "m2sri3jqfqutiy5", "events": "evt123abc", ... }
|
||||
}
|
||||
|
||||
export interface MemberResponse {
|
||||
|
|
|
|||
Loading…
Reference in New Issue