Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6760ab0abf | |||
| d9e592cc97 |
@@ -28,7 +28,7 @@ def load_config():
|
||||
load_dotenv(backend_env_path)
|
||||
log.info(f"ℹ️ Loaded local configuration from {backend_env_path}")
|
||||
else:
|
||||
log.warning("⚠️ No .env config files found. Relying on system environment variables.")
|
||||
log.info("ℹ️ [CONFIG] Using system environment variables (Docker/Server environment).")
|
||||
|
||||
# Auto-run if imported
|
||||
load_config()
|
||||
|
||||
@@ -26,6 +26,12 @@ bash /app/scripts/init_data.sh
|
||||
# Fix permissions for mounted volumes (which might be root-owned by the host)
|
||||
echo "🐳 [Docker] Fixing volume permissions..."
|
||||
chown -R appuser:appuser "${DATA_DIR}" "${LOGS_DIR}"
|
||||
chmod -R 770 "${DATA_DIR}" "${LOGS_DIR}"
|
||||
|
||||
# Verify logic: Ensure appuser can actually write before we hand off
|
||||
echo "🐳 [Docker] Verifying directory writability..."
|
||||
gosu appuser touch "${LOGS_DIR}/.startup_test" && rm "${LOGS_DIR}/.startup_test"
|
||||
gosu appuser touch "${DATA_DIR}/.startup_test" && rm "${DATA_DIR}/.startup_test"
|
||||
|
||||
# Hand off to the application server as non-root user
|
||||
echo "🐳 [Docker] Starting uvicorn as appuser..."
|
||||
|
||||
@@ -27,26 +27,25 @@ def setup_logger():
|
||||
datefmt="%Y-%m-%d %H:%M:%S"
|
||||
)
|
||||
|
||||
# Console Handler
|
||||
# File Handler (10MB max, keep 5 backups)
|
||||
try:
|
||||
file_handler = RotatingFileHandler(
|
||||
LOG_FILE_PATH, maxBytes=10*1024*1024, backupCount=5
|
||||
)
|
||||
file_handler.setFormatter(formatter)
|
||||
logger.addHandler(file_handler)
|
||||
|
||||
# Special redirect for uvicorn logs to also go to file
|
||||
logging.getLogger("uvicorn").addHandler(file_handler)
|
||||
logging.getLogger("uvicorn.access").addHandler(file_handler)
|
||||
except (PermissionError, IOError) as e:
|
||||
logger.warning(f"⚠️ [LOGGING] Cannot write to log file at {LOG_FILE_PATH}: {e}")
|
||||
logger.warning("⚠️ [LOGGING] Continuing with console-only output.")
|
||||
|
||||
# Console Handler (always registered)
|
||||
console_handler = logging.StreamHandler()
|
||||
console_handler.setFormatter(formatter)
|
||||
|
||||
# File Handler (10MB max, keep 5 backups)
|
||||
file_handler = RotatingFileHandler(
|
||||
LOG_FILE_PATH, maxBytes=10*1024*1024, backupCount=5
|
||||
)
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
# Attach handlers
|
||||
logger.addHandler(console_handler)
|
||||
logger.addHandler(file_handler)
|
||||
|
||||
# Special redirect for uvicorn logs to also go to file
|
||||
uvicorn_logger = logging.getLogger("uvicorn")
|
||||
uvicorn_logger.addHandler(file_handler)
|
||||
|
||||
uvicorn_access_logger = logging.getLogger("uvicorn.access")
|
||||
uvicorn_access_logger.addHandler(file_handler)
|
||||
|
||||
return logger
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": "1.10.0",
|
||||
"last_build": "2026-04-15-1731",
|
||||
"version": "1.10.2",
|
||||
"last_build": "2026-04-15-1754",
|
||||
"codename": "ModularAdmin",
|
||||
"commit": "074d4f1f"
|
||||
"commit": "d9e592cc"
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import { useAdmin } from '@/hooks/useAdmin';
|
||||
import { inventoryApi } from '@/lib/api';
|
||||
import { vi, describe, it, expect } from 'vitest';
|
||||
|
||||
// Mock the API
|
||||
vi.mock('@/lib/api', () => ({
|
||||
inventoryApi: {
|
||||
getUsers: vi.fn(),
|
||||
getCategories: vi.fn(),
|
||||
getLdapConfig: vi.fn(),
|
||||
getDbBackups: vi.fn(),
|
||||
getDbStats: vi.fn(),
|
||||
getDbSettings: vi.fn(),
|
||||
getAiPrompt: vi.fn(),
|
||||
getAiConfig: vi.fn(),
|
||||
}
|
||||
}));
|
||||
|
||||
// Mock toast
|
||||
vi.mock('react-hot-toast', () => ({
|
||||
toast: {
|
||||
error: vi.fn(),
|
||||
success: vi.fn(),
|
||||
}
|
||||
}));
|
||||
|
||||
describe('useAdmin hook', () => {
|
||||
it('should initialize with loading state and fetch data', async () => {
|
||||
(inventoryApi.getUsers as any).mockResolvedValue([{ id: 1, username: 'testuser' }]);
|
||||
(inventoryApi.getCategories as any).mockResolvedValue([]);
|
||||
(inventoryApi.getLdapConfig as any).mockResolvedValue({ server_uri: 'ldap://fake' });
|
||||
(inventoryApi.getDbBackups as any).mockResolvedValue([]);
|
||||
(inventoryApi.getDbStats as any).mockResolvedValue({ backup_count: 0 });
|
||||
(inventoryApi.getDbSettings as any).mockResolvedValue({ retention_count: 5 });
|
||||
(inventoryApi.getAiPrompt as any).mockResolvedValue({ value: 'test prompt' });
|
||||
(inventoryApi.getAiConfig as any).mockResolvedValue({ active_provider: 'gemini' });
|
||||
|
||||
const { result } = renderHook(() => useAdmin());
|
||||
|
||||
expect(result.current.loading).toBe(true);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false);
|
||||
});
|
||||
|
||||
expect(result.current.users).toHaveLength(1);
|
||||
expect(result.current.users[0].username).toBe('testuser');
|
||||
expect(result.current.aiPrompt).toBe('test prompt');
|
||||
});
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import path from 'path';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
globals: true,
|
||||
setupFiles: ['./vitest.setup.ts'],
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, './'),
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
import '@testing-library/jest-dom';
|
||||
Reference in New Issue
Block a user