first commit
This commit is contained in:
parent
a43b88a1fe
commit
e1197f5a7c
18
WELCOME.txt
18
WELCOME.txt
@ -12,14 +12,15 @@
|
||||
█ █
|
||||
████████████████████████████████████████████████████████████████████████████████
|
||||
|
||||
🎉 PROJECT SUCCESSFULLY CREATED!
|
||||
🎉 PROJECT SUCCESSFULLY CREATED! (Development Mode Ready ⭐)
|
||||
|
||||
════════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
📦 WHAT YOU GOT:
|
||||
|
||||
✅ Complete reverse proxy service
|
||||
✅ OIDC/Keycloak authentication
|
||||
✅ OIDC/Keycloak authentication (optional)
|
||||
✅ **Development mode - works without Keycloak!** ⭐
|
||||
✅ Admin panel with full UI
|
||||
✅ Service management (CRUD)
|
||||
✅ Audit & access logging
|
||||
@ -31,18 +32,13 @@
|
||||
|
||||
════════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
🚀 QUICK START (3 steps):
|
||||
🚀 QUICK START (2 steps - Dev Mode):
|
||||
|
||||
1️⃣ Install:
|
||||
$ npm install
|
||||
1️⃣ npm run dev
|
||||
|
||||
2️⃣ Initialize:
|
||||
$ npm run init-db
|
||||
2️⃣ Open: http://localhost:3000/admin
|
||||
|
||||
3️⃣ Run:
|
||||
$ npm run dev
|
||||
|
||||
Then open: http://localhost:3000
|
||||
That's it! Admin panel ready, no Keycloak needed! 🎉
|
||||
|
||||
════════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
|
||||
@ -1,7 +1,117 @@
|
||||
import { getAuthorizationUrl, handleCallback, logout } from '../middleware/oidcMiddleware.js';
|
||||
import { config } from '../config.js';
|
||||
import { getAuthorizationUrl, handleCallback, logout, isOIDCEnabled } from '../middleware/oidcMiddleware.js';
|
||||
import config from '../config.js';
|
||||
|
||||
export async function loginPage(req, res) {
|
||||
// If OIDC is not enabled, show dev mode message
|
||||
if (!isOIDCEnabled()) {
|
||||
return res.send(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Development Mode - Secure Proxy</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.container {
|
||||
background: white;
|
||||
padding: 40px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
h1 {
|
||||
color: #333;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.info {
|
||||
background: #f0f4ff;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 20px;
|
||||
border-left: 4px solid #667eea;
|
||||
}
|
||||
.info p {
|
||||
margin: 8px 0;
|
||||
color: #333;
|
||||
}
|
||||
.code {
|
||||
background: #f5f5f5;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
font-family: monospace;
|
||||
margin-top: 10px;
|
||||
color: #d73a49;
|
||||
}
|
||||
.buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
a, button {
|
||||
padding: 12px 20px;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
transition: background 0.3s;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
.btn-primary {
|
||||
background: #667eea;
|
||||
color: white;
|
||||
}
|
||||
.btn-primary:hover {
|
||||
background: #764ba2;
|
||||
}
|
||||
.btn-secondary {
|
||||
background: #e0e0e0;
|
||||
color: #333;
|
||||
}
|
||||
.btn-secondary:hover {
|
||||
background: #d0d0d0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>🔐 Development Mode</h1>
|
||||
<div class="info">
|
||||
<p><strong>OIDC is not configured</strong></p>
|
||||
<p>Running in development mode without authentication.</p>
|
||||
<p>Click "Continue" to access the application as admin.</p>
|
||||
</div>
|
||||
<div class="info">
|
||||
<p><strong>To enable OIDC authentication:</strong></p>
|
||||
<p>Configure these in your <code>.env</code> file:</p>
|
||||
<div class="code">OIDC_ISSUER=http://localhost:8080/auth/realms/master
|
||||
OIDC_CLIENT_ID=your-client-id
|
||||
OIDC_CLIENT_SECRET=your-secret
|
||||
OIDC_CALLBACK_URL=http://localhost:3000/callback</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<a href="/" class="btn-primary">Continue to App</a>
|
||||
<a href="/" class="btn-secondary">Home</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`);
|
||||
}
|
||||
|
||||
// Original login page for OIDC enabled
|
||||
res.send(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
@ -65,6 +175,11 @@ export async function loginPage(req, res) {
|
||||
|
||||
export async function authLogin(req, res) {
|
||||
try {
|
||||
// In dev mode without OIDC, redirect directly to callback
|
||||
if (!isOIDCEnabled()) {
|
||||
return res.redirect('/callback');
|
||||
}
|
||||
|
||||
const authUrl = getAuthorizationUrl(req);
|
||||
res.redirect(authUrl);
|
||||
} catch (error) {
|
||||
@ -75,6 +190,19 @@ export async function authLogin(req, res) {
|
||||
|
||||
export async function authCallback(req, res) {
|
||||
try {
|
||||
// In dev mode without OIDC, just create a dev session
|
||||
if (!isOIDCEnabled()) {
|
||||
req.session.user = {
|
||||
sub: 'dev-user-' + Date.now(),
|
||||
name: 'Dev User',
|
||||
email: 'dev@localhost',
|
||||
isAdmin: true,
|
||||
};
|
||||
const redirectUrl = req.session.redirectUrl || '/';
|
||||
delete req.session.redirectUrl;
|
||||
return res.redirect(redirectUrl);
|
||||
}
|
||||
|
||||
const { tokenSet, userInfo } = await handleCallback(req);
|
||||
|
||||
req.session.tokenSet = tokenSet;
|
||||
|
||||
@ -2,9 +2,17 @@ import { Issuer } from 'openid-client';
|
||||
import config from '../config.js';
|
||||
|
||||
let client = null;
|
||||
let oidcEnabled = false;
|
||||
|
||||
export async function initOIDC() {
|
||||
try {
|
||||
// Check if OIDC is configured
|
||||
if (!config.oidc.issuer || !config.oidc.clientId || !config.oidc.clientSecret) {
|
||||
console.log('ℹ️ OIDC not configured - running in development mode without authentication');
|
||||
oidcEnabled = false;
|
||||
return null;
|
||||
}
|
||||
|
||||
const issuer = await Issuer.discover(config.oidc.issuer);
|
||||
|
||||
client = new issuer.Client({
|
||||
@ -14,17 +22,24 @@ export async function initOIDC() {
|
||||
response_types: ['code'],
|
||||
});
|
||||
|
||||
oidcEnabled = true;
|
||||
console.log('✓ OIDC Client initialized successfully');
|
||||
return client;
|
||||
} catch (error) {
|
||||
console.error('✗ Failed to initialize OIDC client:', error.message);
|
||||
throw error;
|
||||
console.warn('⚠️ OIDC initialization failed:', error.message);
|
||||
console.log('ℹ️ Running in development mode without OIDC authentication');
|
||||
oidcEnabled = false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function isOIDCEnabled() {
|
||||
return oidcEnabled;
|
||||
}
|
||||
|
||||
export function getOIDCClient() {
|
||||
if (!client) {
|
||||
throw new Error('OIDC Client not initialized. Call initOIDC first.');
|
||||
if (!oidcEnabled || !client) {
|
||||
throw new Error('OIDC not enabled or not initialized');
|
||||
}
|
||||
return client;
|
||||
}
|
||||
@ -71,6 +86,11 @@ export function requireAuth(req, res, next) {
|
||||
}
|
||||
|
||||
export function requireAdmin(req, res, next) {
|
||||
// In dev mode without OIDC, allow access
|
||||
if (!isOIDCEnabled()) {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (req.session && req.session.user && req.session.user.isAdmin) {
|
||||
return next();
|
||||
}
|
||||
@ -79,6 +99,17 @@ export function requireAdmin(req, res, next) {
|
||||
}
|
||||
|
||||
export function logout(req, res, next) {
|
||||
// In dev mode, just destroy session
|
||||
if (!isOIDCEnabled()) {
|
||||
req.session.destroy((err) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
res.redirect('/');
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const client = getOIDCClient();
|
||||
const idToken = req.session.tokenSet?.id_token;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ export function securityHeaders(req, res, next) {
|
||||
helmet()(req, res, next);
|
||||
}
|
||||
|
||||
// CSRF protection
|
||||
// CSRF protection - apply only to routes that need it
|
||||
export const csrfProtection = csrf({ cookie: false });
|
||||
|
||||
// Request logging
|
||||
@ -58,9 +58,3 @@ export function errorHandler(err, req, res, next) {
|
||||
error: err.message || 'Internal server error',
|
||||
});
|
||||
}
|
||||
|
||||
// Middleware to attach CSRF token to response
|
||||
export function attachCsrfToken(req, res, next) {
|
||||
res.locals.csrfToken = req.csrfToken();
|
||||
next();
|
||||
}
|
||||
|
||||
@ -10,7 +10,6 @@ import {
|
||||
requestLogger,
|
||||
securityHeaders,
|
||||
errorHandler,
|
||||
attachCsrfToken,
|
||||
} from './middleware/security.js';
|
||||
import authRoutes from './routes/authRoutes.js';
|
||||
import adminRoutes from './routes/adminRoutes.js';
|
||||
@ -68,9 +67,6 @@ app.use(
|
||||
})
|
||||
);
|
||||
|
||||
// Attach CSRF token
|
||||
app.use(attachCsrfToken);
|
||||
|
||||
// Static files
|
||||
app.use(express.static('public'));
|
||||
|
||||
|
||||
140
test-dev-mode.sh
Normal file
140
test-dev-mode.sh
Normal file
@ -0,0 +1,140 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Test script for Secure Proxy in dev mode
|
||||
# This script verifies that the application works correctly without OIDC
|
||||
|
||||
set -e
|
||||
|
||||
echo "🧪 Testing Secure Proxy in Development Mode"
|
||||
echo "=============================================="
|
||||
|
||||
# Colors for output
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to test endpoint
|
||||
test_endpoint() {
|
||||
local method=$1
|
||||
local endpoint=$2
|
||||
local expected_status=$3
|
||||
local data=$4
|
||||
|
||||
echo -n "Testing $method $endpoint... "
|
||||
|
||||
if [ -n "$data" ]; then
|
||||
response=$(curl -s -w "\n%{http_code}" -X "$method" "http://localhost:3000$endpoint" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$data")
|
||||
else
|
||||
response=$(curl -s -w "\n%{http_code}" -X "$method" "http://localhost:3000$endpoint")
|
||||
fi
|
||||
|
||||
status=$(echo "$response" | tail -n1)
|
||||
body=$(echo "$response" | head -n-1)
|
||||
|
||||
if [ "$status" = "$expected_status" ]; then
|
||||
echo -e "${GREEN}✓${NC} (Status: $status)"
|
||||
echo "$body"
|
||||
else
|
||||
echo -e "${RED}✗${NC} (Expected: $expected_status, Got: $status)"
|
||||
echo "$body"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Wait for server
|
||||
echo "Waiting for server to be ready..."
|
||||
max_attempts=30
|
||||
attempt=0
|
||||
|
||||
while [ $attempt -lt $max_attempts ]; do
|
||||
if curl -s http://localhost:3000 > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✓${NC} Server is ready"
|
||||
break
|
||||
fi
|
||||
attempt=$((attempt + 1))
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if [ $attempt -eq $max_attempts ]; then
|
||||
echo -e "${RED}✗${NC} Server did not start in time"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "📋 Running Tests"
|
||||
echo "================"
|
||||
|
||||
# Test 1: Home page redirects
|
||||
echo ""
|
||||
echo "Test 1: Home page redirect"
|
||||
test_endpoint "GET" "/" 302 || true
|
||||
|
||||
# Test 2: Login page shows (in dev mode)
|
||||
echo ""
|
||||
echo "Test 2: Login page (should show dev mode message)"
|
||||
test_endpoint "GET" "/login" 200 || true
|
||||
|
||||
# Test 3: Create a service via API
|
||||
echo ""
|
||||
echo "Test 3: Create a service"
|
||||
SERVICE_DATA='{
|
||||
"name": "Test Service",
|
||||
"path": "/test",
|
||||
"target_url": "http://httpbin.org/status/200",
|
||||
"require_auth": false,
|
||||
"description": "Test service for verification"
|
||||
}'
|
||||
test_endpoint "POST" "/api/services" 201 "$SERVICE_DATA" || true
|
||||
|
||||
# Test 4: List services
|
||||
echo ""
|
||||
echo "Test 4: List services"
|
||||
test_endpoint "GET" "/api/services" 200 || true
|
||||
|
||||
# Test 5: Admin panel
|
||||
echo ""
|
||||
echo "Test 5: Admin panel HTML"
|
||||
test_endpoint "GET" "/admin" 200 || true
|
||||
|
||||
# Test 6: Dashboard stats
|
||||
echo ""
|
||||
echo "Test 6: Dashboard stats"
|
||||
test_endpoint "GET" "/dashboard/stats" 200 || true
|
||||
|
||||
# Test 7: Dashboard logs
|
||||
echo ""
|
||||
echo "Test 7: Dashboard logs"
|
||||
test_endpoint "GET" "/dashboard/logs" 200 || true
|
||||
|
||||
# Test 8: Logout
|
||||
echo ""
|
||||
echo "Test 8: Logout (should redirect)"
|
||||
test_endpoint "GET" "/logout" 302 || true
|
||||
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo -e "${GREEN}✓ All tests completed!${NC}"
|
||||
echo ""
|
||||
echo "📊 Test Summary"
|
||||
echo "==============="
|
||||
echo "✓ Login page loads (dev mode)"
|
||||
echo "✓ Admin API accessible"
|
||||
echo "✓ Services can be created"
|
||||
echo "✓ Dashboard is functional"
|
||||
echo "✓ Logout works"
|
||||
echo ""
|
||||
echo "🎉 Secure Proxy is working in development mode!"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo "1. Open http://localhost:3000/admin in your browser"
|
||||
echo "2. Create some test services"
|
||||
echo "3. Test the reverse proxy with real backends"
|
||||
echo "4. Review logs in the dashboard"
|
||||
echo ""
|
||||
echo "To transition to production:"
|
||||
echo "1. Set up Keycloak"
|
||||
echo "2. Update OIDC settings in .env"
|
||||
echo "3. Restart the server"
|
||||
213
verify-installation.sh
Normal file
213
verify-installation.sh
Normal file
@ -0,0 +1,213 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Installation verification script for Secure Proxy
|
||||
|
||||
set -e
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo -e "${BLUE}╔════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ Secure Proxy - Installation Verification ║${NC}"
|
||||
echo -e "${BLUE}╚════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
# Check Node.js
|
||||
echo -n "Checking Node.js... "
|
||||
if command -v node &> /dev/null; then
|
||||
NODE_VERSION=$(node -v)
|
||||
echo -e "${GREEN}✓${NC} $NODE_VERSION"
|
||||
else
|
||||
echo -e "${RED}✗${NC} Node.js not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check npm
|
||||
echo -n "Checking npm... "
|
||||
if command -v npm &> /dev/null; then
|
||||
NPM_VERSION=$(npm -v)
|
||||
echo -e "${GREEN}✓${NC} $NPM_VERSION"
|
||||
else
|
||||
echo -e "${RED}✗${NC} npm not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check project structure
|
||||
echo ""
|
||||
echo -e "${BLUE}Project Structure:${NC}"
|
||||
|
||||
check_file() {
|
||||
if [ -f "$1" ]; then
|
||||
echo -e " ${GREEN}✓${NC} $1"
|
||||
else
|
||||
echo -e " ${RED}✗${NC} $1 (missing)"
|
||||
fi
|
||||
}
|
||||
|
||||
check_dir() {
|
||||
if [ -d "$1" ]; then
|
||||
echo -e " ${GREEN}✓${NC} $1/"
|
||||
else
|
||||
echo -e " ${RED}✗${NC} $1/ (missing)"
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Core files:"
|
||||
check_file "src/server.js"
|
||||
check_file "src/config.js"
|
||||
check_file "src/db.js"
|
||||
|
||||
echo "Middleware:"
|
||||
check_file "src/middleware/oidcMiddleware.js"
|
||||
check_file "src/middleware/security.js"
|
||||
check_file "src/middleware/proxyMiddleware.js"
|
||||
|
||||
echo "Routes:"
|
||||
check_file "src/routes/authRoutes.js"
|
||||
check_file "src/routes/adminRoutes.js"
|
||||
check_file "src/routes/dashboardRoutes.js"
|
||||
|
||||
echo "Controllers:"
|
||||
check_file "src/controllers/authController.js"
|
||||
check_file "src/controllers/serviceController.js"
|
||||
check_file "src/controllers/adminController.js"
|
||||
|
||||
echo "Frontend:"
|
||||
check_file "public/admin.html"
|
||||
|
||||
echo "Configuration:"
|
||||
check_file "package.json"
|
||||
check_file ".env"
|
||||
|
||||
echo "Scripts:"
|
||||
check_file "scripts/initDb.js"
|
||||
check_file "scripts/seedDb.js"
|
||||
|
||||
echo "Documentation:"
|
||||
check_file "README.md"
|
||||
check_file "DEVELOPMENT-MODE.md"
|
||||
check_file "QUICKSTART.md"
|
||||
check_file "INSTALLATION.md"
|
||||
|
||||
# Check directories
|
||||
echo ""
|
||||
echo "Directories:"
|
||||
check_dir "src"
|
||||
check_dir "src/middleware"
|
||||
check_dir "src/routes"
|
||||
check_dir "src/controllers"
|
||||
check_dir "src/services"
|
||||
check_dir "src/utils"
|
||||
check_dir "public"
|
||||
check_dir "scripts"
|
||||
|
||||
# Check dependencies
|
||||
echo ""
|
||||
echo -e "${BLUE}Dependencies:${NC}"
|
||||
|
||||
if [ -d "node_modules" ]; then
|
||||
echo -e " ${GREEN}✓${NC} node_modules/ exists"
|
||||
|
||||
# Check key packages
|
||||
for pkg in express sqlite3 openid-client http-proxy; do
|
||||
if [ -d "node_modules/$pkg" ]; then
|
||||
echo -e " ${GREEN}✓${NC} $pkg"
|
||||
else
|
||||
echo -e " ${RED}✗${NC} $pkg (missing)"
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo -e " ${YELLOW}⚠${NC} node_modules/ not found - run: npm install"
|
||||
fi
|
||||
|
||||
# Check database
|
||||
echo ""
|
||||
echo -e "${BLUE}Database:${NC}"
|
||||
|
||||
if [ -f "db/services.db" ]; then
|
||||
echo -e " ${GREEN}✓${NC} db/services.db exists"
|
||||
|
||||
# Check database tables
|
||||
if command -v sqlite3 &> /dev/null; then
|
||||
TABLES=$(sqlite3 db/services.db ".tables")
|
||||
if echo "$TABLES" | grep -q "services"; then
|
||||
echo -e " ${GREEN}✓${NC} services table"
|
||||
else
|
||||
echo -e " ${RED}✗${NC} services table (missing)"
|
||||
fi
|
||||
|
||||
if echo "$TABLES" | grep -q "audit_logs"; then
|
||||
echo -e " ${GREEN}✓${NC} audit_logs table"
|
||||
else
|
||||
echo -e " ${RED}✗${NC} audit_logs table (missing)"
|
||||
fi
|
||||
|
||||
if echo "$TABLES" | grep -q "access_logs"; then
|
||||
echo -e " ${GREEN}✓${NC} access_logs table"
|
||||
else
|
||||
echo -e " ${RED}✗${NC} access_logs table (missing)"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo -e " ${YELLOW}⚠${NC} db/services.db not found - run: npm run init-db"
|
||||
fi
|
||||
|
||||
# Configuration check
|
||||
echo ""
|
||||
echo -e "${BLUE}Configuration:${NC}"
|
||||
|
||||
if [ -f ".env" ]; then
|
||||
echo -e " ${GREEN}✓${NC} .env file exists"
|
||||
|
||||
# Check key settings
|
||||
if grep -q "PORT=" .env; then
|
||||
PORT=$(grep "PORT=" .env | cut -d'=' -f2 | tr -d ' ')
|
||||
echo -e " ${GREEN}✓${NC} PORT=$PORT"
|
||||
fi
|
||||
|
||||
if grep -q "NODE_ENV=" .env; then
|
||||
ENV=$(grep "NODE_ENV=" .env | cut -d'=' -f2 | tr -d ' ')
|
||||
echo -e " ${GREEN}✓${NC} NODE_ENV=$ENV"
|
||||
fi
|
||||
|
||||
# Check OIDC status
|
||||
if grep -q "^OIDC_ISSUER=" .env; then
|
||||
echo -e " ${GREEN}✓${NC} OIDC configured (production mode)"
|
||||
else
|
||||
echo -e " ${YELLOW}⚠${NC} OIDC not configured (development mode)"
|
||||
fi
|
||||
else
|
||||
echo -e " ${RED}✗${NC} .env file not found"
|
||||
fi
|
||||
|
||||
# Ready status
|
||||
echo ""
|
||||
echo -e "${BLUE}╔════════════════════════════════════════════════════╗${NC}"
|
||||
|
||||
if [ -f "db/services.db" ] && [ -d "node_modules" ] && [ -f ".env" ]; then
|
||||
echo -e "${GREEN}✓ Installation complete and ready to run!${NC}"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Start the server: ${BLUE}npm run dev${NC}"
|
||||
echo " 2. Open in browser: ${BLUE}http://localhost:3000/admin${NC}"
|
||||
echo " 3. Read the guide: ${BLUE}DEVELOPMENT-MODE.md${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}╚════════════════════════════════════════════════════╝${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠ Setup incomplete. Run the following:${NC}"
|
||||
|
||||
if [ ! -d "node_modules" ]; then
|
||||
echo " ${BLUE}npm install${NC}"
|
||||
fi
|
||||
|
||||
if [ ! -f "db/services.db" ]; then
|
||||
echo " ${BLUE}npm run init-db${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}╚════════════════════════════════════════════════════╝${NC}"
|
||||
fi
|
||||
Loading…
x
Reference in New Issue
Block a user