488 lines
11 KiB
Markdown
488 lines
11 KiB
Markdown
/\*\*
|
|
|
|
- Environment Configuration
|
|
- Development | Staging | Production
|
|
\*/
|
|
|
|
// ============================================================================
|
|
// BACKEND CONFIGURATION (PHP)
|
|
// ============================================================================
|
|
|
|
// File: backend/config.php
|
|
|
|
<?php
|
|
define('ENVIRONMENT', getenv('APP_ENV') ?: 'development');
|
|
|
|
// Database Configuration
|
|
if (ENVIRONMENT === 'production') {
|
|
define('DB_HOST', getenv('DB_HOST') ?: 'prod-db.example.com');
|
|
define('DB_USER', getenv('DB_USER') ?: 'fitness_app');
|
|
define('DB_PASS', getenv('DB_PASS'));
|
|
define('DB_NAME', 'fitness_app');
|
|
define('DB_PORT', getenv('DB_PORT') ?: 3306);
|
|
define('DB_CHARSET', 'utf8mb4');
|
|
|
|
// Security Headers
|
|
define('FORCE_HTTPS', true);
|
|
define('SECURE_COOKIES', true);
|
|
define('HSTS_MAX_AGE', 31536000); // 1 year
|
|
} elseif (ENVIRONMENT === 'staging') {
|
|
define('DB_HOST', 'staging-db.example.com');
|
|
define('DB_USER', 'fitness_staging');
|
|
define('DB_PASS', getenv('DB_PASS'));
|
|
define('DB_NAME', 'fitness_staging');
|
|
define('DB_PORT', 3306);
|
|
define('FORCE_HTTPS', true);
|
|
} else {
|
|
// Development
|
|
define('DB_HOST', 'localhost');
|
|
define('DB_USER', 'root');
|
|
define('DB_PASS', 'password');
|
|
define('DB_NAME', 'fitness_app_dev');
|
|
define('DB_PORT', 3306);
|
|
define('FORCE_HTTPS', false);
|
|
}
|
|
|
|
// API Configuration
|
|
define('API_VERSION', 'v1');
|
|
define('API_BASE_PATH', '/api/' . API_VERSION);
|
|
define('REQUEST_TIMEOUT', 30); // seconds
|
|
define('MAX_PAYLOAD_SIZE', 10485760); // 10MB
|
|
|
|
// Rate Limiting
|
|
define('RATE_LIMIT_ENABLED', true);
|
|
define('RATE_LIMIT_REQUESTS', 100); // per minute
|
|
define('RATE_LIMIT_WINDOW', 60); // seconds
|
|
|
|
// Logging
|
|
define('LOG_LEVEL', ENVIRONMENT === 'production' ? 'error' : 'debug');
|
|
define('LOG_FILE', '/var/log/fitness_api.log');
|
|
define('LOG_DATABASE', true); // Log to DB as well
|
|
|
|
// CORS Configuration
|
|
define('ALLOWED_ORIGINS', [
|
|
'https://fitness-app.com',
|
|
'https://app.fitness-app.com',
|
|
ENVIRONMENT === 'development' ? 'http://localhost:3000' : null
|
|
]);
|
|
|
|
// Email Configuration (for notifications)
|
|
define('MAIL_HOST', getenv('MAIL_HOST') ?: 'smtp.gmail.com');
|
|
define('MAIL_PORT', getenv('MAIL_PORT') ?: 587);
|
|
define('MAIL_USER', getenv('MAIL_USER'));
|
|
define('MAIL_PASS', getenv('MAIL_PASS'));
|
|
define('MAIL_FROM', 'noreply@fitness-app.com');
|
|
|
|
// Cache Configuration
|
|
define('CACHE_ENABLED', ENVIRONMENT !== 'development');
|
|
define('CACHE_DRIVER', 'redis'); // 'redis' or 'file'
|
|
define('CACHE_TTL', 3600); // seconds
|
|
|
|
// Security
|
|
define('HMAC_ALGORITHM', 'sha256');
|
|
define('TIMESTAMP_TOLERANCE', 300); // 5 minutes
|
|
define('BCRYPT_COST', 12);
|
|
|
|
// API Keys (for external services)
|
|
define('MAPBOX_API_KEY', getenv('MAPBOX_API_KEY'));
|
|
define('WEATHER_API_KEY', getenv('WEATHER_API_KEY'));
|
|
|
|
// Enable debug mode (NEVER true in production)
|
|
define('DEBUG_MODE', ENVIRONMENT === 'development');
|
|
|
|
// Timezone
|
|
date_default_timezone_set('UTC');
|
|
?>
|
|
|
|
// ============================================================================
|
|
// MOBILE CONFIGURATION (Dart/Flutter)
|
|
// ============================================================================
|
|
|
|
// File: mobile/lib/config/environment.dart
|
|
|
|
const String kEnvironment = String.fromEnvironment('ENVIRONMENT', defaultValue: 'development');
|
|
|
|
class EnvironmentConfig {
|
|
static const String apiHost = String.fromEnvironment(
|
|
'API_HOST',
|
|
defaultValue: 'https://api.fitness-app.local',
|
|
);
|
|
|
|
static const String mapTileServer = 'https://map-saas.intaleqapp.com/styles/basic-preview/style.json';
|
|
|
|
static const int locationUpdateInterval = 5; // seconds
|
|
static const int mapRefreshInterval = 2; // seconds
|
|
|
|
// API Configuration
|
|
static const Duration requestTimeout = Duration(seconds: 30);
|
|
static const int maxRetries = 3;
|
|
|
|
// Location Configuration
|
|
static const double minAccuracy = 10.0; // meters
|
|
static const double minDistance = 10.0; // meters between coordinates
|
|
static const int foregroundServicePriority = 1; // HIGH
|
|
|
|
// Database Configuration
|
|
static const String databaseName = 'fitness_app.db';
|
|
static const int databaseVersion = 1;
|
|
|
|
// Feature Flags
|
|
static const bool enableBackgroundTracking = true;
|
|
static const bool enableOfflineSync = true;
|
|
static const bool enableAnalytics = !kDebugMode;
|
|
|
|
// Get API endpoint based on environment
|
|
static String get apiEndpoint {
|
|
return '$apiHost/api/v1';
|
|
}
|
|
|
|
// Get workout submission endpoint
|
|
static String get workoutSubmissionEndpoint {
|
|
return '$apiEndpoint/workouts';
|
|
}
|
|
}
|
|
|
|
class DevEnvironment {
|
|
static const String apiHost = 'http://localhost:8080';
|
|
static const bool debugLogging = true;
|
|
}
|
|
|
|
class StagingEnvironment {
|
|
static const String apiHost = 'https://staging-api.fitness-app.com';
|
|
static const bool debugLogging = true;
|
|
}
|
|
|
|
class ProductionEnvironment {
|
|
static const String apiHost = 'https://api.fitness-app.com';
|
|
static const bool debugLogging = false;
|
|
}
|
|
|
|
// ============================================================================
|
|
// DOCKER COMPOSE CONFIGURATION
|
|
// ============================================================================
|
|
|
|
# File: docker-compose.yml
|
|
|
|
version: '3.8'
|
|
|
|
services:
|
|
mysql:
|
|
image: mysql:8.0
|
|
container_name: fitness_app_mysql
|
|
environment:
|
|
MYSQL_ROOT_PASSWORD: root_password
|
|
MYSQL_DATABASE: fitness_app
|
|
MYSQL_USER: fitness_app
|
|
MYSQL_PASSWORD: ${DB_PASSWORD}
|
|
ports: - "3306:3306"
|
|
volumes: - mysql_data:/var/lib/mysql - ./backend/schema.sql:/docker-entrypoint-initdb.d/schema.sql
|
|
networks: - fitness_network
|
|
healthcheck:
|
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
|
timeout: 20s
|
|
retries: 10
|
|
|
|
php_api:
|
|
image: php:8.2-fpm
|
|
container_name: fitness_app_php
|
|
environment:
|
|
APP_ENV: ${APP_ENV:-development}
|
|
DB_HOST: mysql
|
|
DB_USER: fitness_app
|
|
DB_PASS: ${DB_PASSWORD}
|
|
DB_NAME: fitness_app
|
|
volumes: - ./backend:/app
|
|
depends_on:
|
|
mysql:
|
|
condition: service_healthy
|
|
networks: - fitness_network
|
|
|
|
nginx:
|
|
image: nginx:alpine
|
|
container_name: fitness_app_nginx
|
|
ports: - "80:80" - "443:443"
|
|
volumes: - ./backend:/app - ./nginx.conf:/etc/nginx/nginx.conf - ./ssl:/etc/nginx/ssl
|
|
depends_on: - php_api
|
|
networks: - fitness_network
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
container_name: fitness_app_redis
|
|
ports: - "6379:6379"
|
|
networks: - fitness_network
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
|
|
volumes:
|
|
mysql_data:
|
|
|
|
networks:
|
|
fitness_network:
|
|
driver: bridge
|
|
|
|
# ============================================================================
|
|
|
|
// ENVIRONMENT VARIABLES (.env file)
|
|
// ============================================================================
|
|
|
|
# File: .env.example (copy to .env for development)
|
|
|
|
# Application
|
|
|
|
APP_ENV=development
|
|
APP_DEBUG=true
|
|
TIMEZONE=UTC
|
|
|
|
# Database
|
|
|
|
DB_HOST=localhost
|
|
DB_PORT=3306
|
|
DB_USER=fitness_app
|
|
DB_PASS=your_secure_password_here
|
|
DB_NAME=fitness_app
|
|
|
|
# API Configuration
|
|
|
|
API_HOST=http://localhost:8080
|
|
API_VERSION=v1
|
|
API_RATE_LIMIT=100
|
|
|
|
# Map Tile Server
|
|
|
|
TILE_SERVER_URL=https://map-saas.intaleqapp.com/styles/basic-preview/style.json
|
|
|
|
# Email (for notifications)
|
|
|
|
MAIL_HOST=smtp.gmail.com
|
|
MAIL_PORT=587
|
|
MAIL_USER=your_email@gmail.com
|
|
MAIL_PASS=your_app_password
|
|
|
|
# External Services
|
|
|
|
MAPBOX_API_KEY=
|
|
WEATHER_API_KEY=
|
|
|
|
# Security
|
|
|
|
HMAC_ALGORITHM=sha256
|
|
BCRYPT_COST=12
|
|
|
|
# Logging
|
|
|
|
LOG_LEVEL=debug
|
|
LOG_FILE=/var/log/fitness_api.log
|
|
|
|
# Cache
|
|
|
|
CACHE_DRIVER=redis
|
|
CACHE_TTL=3600
|
|
|
|
# ============================================================================
|
|
|
|
// NGINX CONFIGURATION
|
|
// ============================================================================
|
|
|
|
# File: nginx.conf
|
|
|
|
user nginx;
|
|
worker_processes auto;
|
|
error_log /var/log/nginx/error.log warn;
|
|
pid /var/run/nginx.pid;
|
|
|
|
events {
|
|
worker_connections 1024;
|
|
}
|
|
|
|
http {
|
|
include /etc/nginx/mime.types;
|
|
default_type application/octet-stream;
|
|
|
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
|
'$status $body_bytes_sent "$http_referer" '
|
|
'"$http_user_agent" "$http_x_forwarded_for"';
|
|
|
|
access_log /var/log/nginx/access.log main;
|
|
|
|
sendfile on;
|
|
tcp_nopush on;
|
|
tcp_nodelay on;
|
|
keepalive_timeout 65;
|
|
types_hash_max_size 2048;
|
|
server_tokens off;
|
|
|
|
# Gzip compression
|
|
gzip on;
|
|
gzip_vary on;
|
|
gzip_proxied any;
|
|
gzip_comp_level 6;
|
|
gzip_types text/plain text/css text/xml text/javascript
|
|
application/json application/javascript application/xml+rss;
|
|
|
|
# Rate limiting
|
|
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
|
|
limit_req_zone $http_x_api_key zone=api:10m rate=100r/m;
|
|
|
|
upstream php_backend {
|
|
server php_api:9000;
|
|
}
|
|
|
|
# Redirect HTTP to HTTPS
|
|
server {
|
|
listen 80;
|
|
server_name _;
|
|
return 301 https://$host$request_uri;
|
|
}
|
|
|
|
# HTTPS Server
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name api.fitness-app.com;
|
|
|
|
ssl_certificate /etc/nginx/ssl/cert.crt;
|
|
ssl_certificate_key /etc/nginx/ssl/key.key;
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
ssl_prefer_server_ciphers on;
|
|
|
|
# Security headers
|
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header X-XSS-Protection "1; mode=block" always;
|
|
|
|
root /app;
|
|
|
|
# Rate limiting
|
|
limit_req zone=api burst=20 nodelay;
|
|
|
|
location / {
|
|
try_files $uri $uri/ @rewrite;
|
|
}
|
|
|
|
location @rewrite {
|
|
rewrite ^/(.*)$ /api_workouts.php?url=$1 last;
|
|
}
|
|
|
|
location ~ \.php$ {
|
|
fastcgi_pass php_backend;
|
|
fastcgi_index index.php;
|
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
include fastcgi_params;
|
|
|
|
fastcgi_connect_timeout 60s;
|
|
fastcgi_send_timeout 60s;
|
|
fastcgi_read_timeout 60s;
|
|
}
|
|
|
|
# Deny access to sensitive files
|
|
location ~ /\. {
|
|
deny all;
|
|
}
|
|
|
|
location ~ ~$ {
|
|
deny all;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// ============================================================================
|
|
// BUILD CONFIGURATION (Android)
|
|
// ============================================================================
|
|
|
|
# File: android/app/build.gradle
|
|
|
|
android {
|
|
compileSdkVersion 34
|
|
ndkVersion "25.1.8937393"
|
|
|
|
defaultConfig {
|
|
applicationId "com.fitness.tracker"
|
|
minSdkVersion 21
|
|
targetSdkVersion 34
|
|
versionCode flutterVersionCode.toInteger()
|
|
versionName flutterVersionName
|
|
}
|
|
|
|
buildTypes {
|
|
debug {
|
|
debuggable true
|
|
signingConfig signingConfigs.debug
|
|
buildConfigField "String", "API_HOST", '"http://192.168.1.100:8080"'
|
|
}
|
|
|
|
staging {
|
|
debuggable false
|
|
signingConfig signingConfigs.release
|
|
buildConfigField "String", "API_HOST", '"https://staging-api.fitness-app.com"'
|
|
}
|
|
|
|
release {
|
|
signingConfig signingConfigs.release
|
|
buildConfigField "String", "API_HOST", '"https://api.fitness-app.com"'
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// ============================================================================
|
|
// GIT IGNORE (.gitignore)
|
|
// ============================================================================
|
|
|
|
# File: .gitignore
|
|
|
|
# Environment
|
|
|
|
.env
|
|
.env.local
|
|
.env.\*.local
|
|
|
|
# API Credentials
|
|
|
|
api_key.txt
|
|
api_secret.txt
|
|
|
|
# Database
|
|
|
|
_.db
|
|
_.sqlite
|
|
\*.sqlite3
|
|
|
|
# Logs
|
|
|
|
\*.log
|
|
logs/
|
|
|
|
# IDE
|
|
|
|
.vscode/
|
|
.idea/
|
|
_.swp
|
|
_.swo
|
|
|
|
# Flutter
|
|
|
|
.dart_tool/
|
|
.flutter-plugins
|
|
.packages
|
|
build/
|
|
|
|
# Backend
|
|
|
|
vendor/
|
|
node_modules/
|
|
|
|
# OS
|
|
|
|
.DS_Store
|
|
Thumbs.db
|
|
|
|
# Secrets
|
|
|
|
secrets.json
|
|
credentials.json
|