Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
# Dependencies
/vendor/
/composer.lock

# Configuration files (contain secrets)
/config/db.php
/config/api.php
/config/api.local.php
/.env

# Logs and storage
/storage/
/logs/
*.log

# Testing artifacts
jwt_token.txt
*.token
test_*.txt
secrets_*.txt

# IDE and OS
.DS_Store
.idea/
/tests/output/
/composer.lock
/tests/output/
1 change: 1 addition & 0 deletions .phpunit.cache/test-results
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"version":2,"defects":{"RateLimiterTest::testCleanup":7,"RequestLoggerTest::testLogStatistics":7},"times":{"RateLimiterTest::testBasicRateLimiting":0.02,"RateLimiterTest::testRequestCount":0.007,"RateLimiterTest::testRemainingRequests":0.006,"RateLimiterTest::testRateLimitReset":0.014,"RateLimiterTest::testWindowExpiration":3.017,"RateLimiterTest::testHeaders":0.007,"RateLimiterTest::testDisabledRateLimiting":0.001,"RateLimiterTest::testCustomLimits":0.009,"RateLimiterTest::testMultipleIdentifiers":0.015,"RateLimiterTest::testResetTime":0.005,"RateLimiterTest::testCleanup":1.01,"RequestLoggerTest::testBasicRequestLogging":0.013,"RequestLoggerTest::testSensitiveDataRedaction":0.006,"RequestLoggerTest::testAuthenticationLogging":0.009,"RequestLoggerTest::testRateLimitLogging":0.004,"RequestLoggerTest::testErrorLogging":0.004,"RequestLoggerTest::testQuickRequestLogging":0.006,"RequestLoggerTest::testLogStatistics":0.014,"RequestLoggerTest::testDisabledLogging":0.001,"RequestLoggerTest::testLogRotation":0.082,"RequestLoggerTest::testCleanup":0.015,"RequestLoggerTest::testLogLevels":0.021}}
114 changes: 114 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,119 @@
# Changelog

## 1.3.0 - Request Logging and Monitoring

### New Features
- **📝 Request Logging**: Comprehensive request/response logging system
- Automatic logging of all API requests and responses
- Multiple log levels (debug, info, warning, error)
- Sensitive data redaction (passwords, tokens, API keys)
- Authentication attempt logging
- Rate limit hit logging
- Error logging with stack traces
- Log rotation and cleanup
- Configurable log retention
- Statistics and analytics
- Zero configuration required (works out of the box)

### Improvements
- Enhanced security with comprehensive audit logging
- Better debugging capabilities with detailed request/response logging
- Performance monitoring with execution time tracking
- Security monitoring with authentication and rate limit logging
- Automatic sensitive data redaction in logs
- Added log statistics for monitoring
- Improved Router integration with automatic logging

### Logging Features
- **Request Details**: Method, action, table, IP, user, query params, headers, body
- **Response Details**: Status code, execution time, response size, body (optional)
- **Authentication Logging**: Success/failure with reasons
- **Rate Limit Logging**: Tracks rate limit violations
- **Error Logging**: Comprehensive error details with context
- **Sensitive Data Redaction**: Automatic redaction of passwords, tokens, API keys
- **Log Rotation**: Automatic rotation when file exceeds size limit
- **Cleanup**: Automatic removal of old log files
- **Statistics**: Daily statistics (requests, errors, warnings, etc.)

### Configuration
- Added logging section to api.example.php:
- `enabled` - Enable/disable logging
- `log_dir` - Log directory path
- `log_level` - Minimum log level (debug, info, warning, error)
- `log_headers` - Log request headers
- `log_body` - Log request body
- `log_query_params` - Log query parameters
- `log_response_body` - Log response body (optional)
- `max_body_length` - Maximum body length to log
- `sensitive_keys` - Keys to redact in logs
- `rotation_size` - Size threshold for log rotation
- `max_files` - Maximum log files to retain

### Documentation
- Added `docs/REQUEST_LOGGING.md` (coming soon)
- Updated README with logging information
- Added logging demo script
- Added comprehensive test coverage

### Testing
- Added comprehensive RequestLoggerTest with 11 test cases
- Tests cover: request logging, sensitive data redaction, auth logging, rate limit logging, error logging, statistics, rotation, cleanup

### Migration Notes
- ✅ **100% Backward Compatible** - No breaking changes
- Logging is enabled by default but can be disabled in config
- Logs are stored in `/logs` directory (auto-created)
- Recommended: Review log settings for production use

---

## 1.2.0 - Rate Limiting and Production Security

### New Features
- **🔒 Rate Limiting**: Built-in rate limiting to prevent API abuse
- Configurable request limits (default: 100 requests per 60 seconds)
- Smart identification (user, API key, or IP address)
- Standard HTTP headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset)
- File-based storage (easily extensible to Redis/Memcached)
- Automatic cleanup of old rate limit data
- 429 Too Many Requests response with retry information
- Per-user/IP rate limiting with sliding window algorithm
- Zero configuration required (works out of the box)

### Improvements
- Enhanced security with rate limiting layer
- Added comprehensive rate limiting documentation
- Added storage directory structure for rate limit data
- Improved Router class with rate limit integration
- Added rate limit headers to all API responses
- Better protection against DoS and brute force attacks

### Documentation
- Added `docs/RATE_LIMITING.md` with comprehensive guide
- Updated README with rate limiting information
- Added client implementation examples (JavaScript, Python, PHP)
- Added benchmarks and performance considerations
- Added troubleshooting guide

### Testing
- Added comprehensive RateLimiterTest with 11 test cases
- Tests cover: basic limiting, request counting, window expiration, headers, cleanup

### Configuration
- Added rate_limit section to api.example.php:
- `enabled` - Enable/disable rate limiting
- `max_requests` - Maximum requests per window
- `window_seconds` - Time window in seconds
- `storage_dir` - Storage directory for rate limit data

### Migration Notes
- ✅ **100% Backward Compatible** - No breaking changes
- Rate limiting is enabled by default but can be disabled in config
- Existing APIs will continue to work without modification
- Recommended: Review and adjust rate limits for your use case

---

## 1.1.0 - Enhanced Query Capabilities and Bulk Operations

### New Features
Expand Down
135 changes: 130 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
# PHP CRUD API Generator

[![Latest Stable Version](https://poser.pugx.org/bitshost/php-crud-api-generator/v/stable)](https://packagist.org/packages/bitshost/php-crud-api-generator)
[![Total Downloads](https://poser.pugx.org/bitshost/php-crud-api-generator/downloads)](https://packagist.org/packages/bitshost/php-crud-api-generator)
[![License](https://poser.pugx.org/bitshost/php-crud-api-generator/license)](https://packagist.org/packages/bitshost/php-crud-api-generator)
[![PHP Version](https://img.shields.io/badge/php-%3E%3D8.0-blue.svg)](https://php.net)

Expose your MySQL/MariaDB database as a secure, flexible, and instant REST-like API.
Features optional authentication (API key, Basic Auth, JWT, OAuth-ready),
OpenAPI (Swagger) docs, and zero code generation.

---

## 🚀 ## 🚀 Features
## 🚀 Features

- Auto-discovers tables and columns
- Full CRUD endpoints for any table
- **Bulk operations** - Create or delete multiple records efficiently
- Configurable authentication (API Key, Basic Auth, JWT, or none)
- **Rate limiting** - Prevent API abuse with configurable request limits
- **Request logging** - Comprehensive logging for debugging and monitoring
- **Advanced query features:**
- **Field selection** - Choose specific columns to return
- **Advanced filtering** - Support for multiple comparison operators (eq, neq, gt, gte, lt, lte, like, in, notin, null, notnull)
Expand All @@ -25,6 +32,8 @@ OpenAPI (Swagger) docs, and zero code generation.
- PHPUnit tests and extensible architecture

📖 **[See detailed enhancement documentation →](ENHANCEMENTS.md)**
📖 **[Rate Limiting Documentation →](docs/RATE_LIMITING.md)**
📖 **[Request Logging Documentation →](docs/REQUEST_LOGGING.md)**

---

Expand Down Expand Up @@ -68,14 +77,55 @@ return [
'jwt_secret' => 'YourSuperSecretKey',
'jwt_issuer' => 'yourdomain.com',
'jwt_audience' => 'yourdomain.com',
'oauth_providers' => [
// 'google' => ['client_id' => '', 'client_secret' => '', ...]
]

// Rate limiting (recommended for production)
'rate_limit' => [
'enabled' => true,
'max_requests' => 100, // 100 requests
'window_seconds' => 60, // per 60 seconds (1 minute)
],

// Request logging (recommended for production)
'logging' => [
'enabled' => true,
'log_dir' => __DIR__ . '/../logs',
'log_level' => 'info', // debug, info, warning, error
],
];
```

---

## 🔒 Security Setup (Production)

⚠️ **IMPORTANT:** This framework ships with **example credentials for development**.
You **MUST** change these before deploying to production!

### Quick Security Setup:

```bash
# 1. Generate secure secrets (JWT secret + API keys)
php scripts/generate_secrets.php

# 2. Update config/api.php with generated secrets

# 3. Create admin user in database
php scripts/create_user.php admin admin@yoursite.com YourSecurePassword123! admin
```

### What to Change:

- [ ] `jwt_secret` - Generate with: `php scripts/generate_jwt_secret.php`
- [ ] `api_keys` - Use long random strings (64+ characters)
- [ ] Default admin password in `sql/create_api_users.sql`
- [ ] Database credentials in `config/db.php`

📖 **Full security guide:** [docs/AUTHENTICATION.md](docs/AUTHENTICATION.md)

---

---

## 🔐 Authentication Modes

- **No auth:** `'auth_enabled' => false`
Expand Down Expand Up @@ -344,11 +394,18 @@ get:
## 🛡️ Security Notes

- **Enable authentication for any public deployment!**
- **Enable rate limiting in production** to prevent abuse
- **Enable request logging** for security auditing and debugging
- Never commit real credentials—use `.gitignore` and example configs.
- Restrict DB user privileges.
- **Input validation**: All user inputs (table names, column names, IDs, filters) are validated to prevent SQL injection and invalid queries.
- **Parameterized queries**: All database queries use prepared statements with bound parameters.
- **RBAC enforcement**: Role-based access control is enforced at the routing level before any database operations.
- **Rate limiting**: Configurable request limits prevent API abuse and DoS attacks.
- **Sensitive data redaction**: Passwords, tokens, and API keys are automatically redacted from logs.

📖 **[Rate Limiting Documentation →](docs/RATE_LIMITING.md)**
📖 **[Request Logging Documentation →](docs/REQUEST_LOGGING.md)**

---

Expand All @@ -360,9 +417,77 @@ get:

---

### 🔗 Working with Related Data (Client-Side Joins)

Your API provides all the data you need - it's up to the client to decide how to combine it. This approach gives you maximum flexibility and control.

**Current approach:** Fetch related data in separate requests and combine on the client side.

#### Quick Example: Get User with Posts

```javascript
// 1. Fetch user
const user = await fetch('/api.php?action=read&table=users&id=123')
.then(r => r.json());

// 2. Fetch user's posts
const posts = await fetch('/api.php?action=list&table=posts&filter=user_id:123')
.then(r => r.json());

// 3. Combine however you want
const userData = {
...user,
posts: posts.data
};
```

#### Optimization: Use IN Operator for Batch Fetching

```javascript
// Get multiple related records in one request
const postIds = '1|2|3|4|5'; // IDs from previous query
const comments = await fetch(
`/api.php?action=list&table=comments&filter=post_id:in:${postIds}`
).then(r => r.json());

// Group by post_id on client
const commentsByPost = comments.data.reduce((acc, comment) => {
acc[comment.post_id] = acc[comment.post_id] || [];
acc[comment.post_id].push(comment);
return acc;
}, {});
```

#### Parallel Fetching for Performance

```javascript
// Fetch multiple resources simultaneously
const [user, posts, comments] = await Promise.all([
fetch('/api.php?action=read&table=users&id=123').then(r => r.json()),
fetch('/api.php?action=list&table=posts&filter=user_id:123').then(r => r.json()),
fetch('/api.php?action=list&table=comments&filter=user_id:123').then(r => r.json())
]);

// All requests happen at once - much faster!
```

📖 **[See complete client-side join examples →](docs/CLIENT_SIDE_JOINS.md)**

**Why this approach?**
- ✅ Client decides what data to fetch and when
- ✅ Easy to optimize with caching and parallel requests
- ✅ Different clients can have different data needs
- ✅ Standard REST API practice
- ✅ No server-side complexity for joins

**Future:** Auto-join/expand features may be added based on user demand.

---

## 🗺️ Roadmap

- Relations / Linked Data (auto-join, populate, or expand related records)
- **Client-side joins** ✅ (Current - simple and flexible!)
- Relations / Linked Data (auto-join, populate, or expand related records) - *Future, based on demand*
- API Versioning (when needed)
- OAuth/SSO (if targeting SaaS/public)
- More DB support (Postgres, SQLite, etc.)
Expand Down
12 changes: 9 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
"name": "bitshost/php-crud-api-generator",
"description": "Automatic, configurable CRUD API generator for MySQL/MariaDB in PHP (with optional authentication)",
"type": "project",
"description": "Instant REST API for MySQL/MariaDB with JWT auth, rate limiting, monitoring, and zero code generation",
"type": "library",
"license": "MIT",
"keywords": ["api", "rest", "crud", "mysql", "jwt", "authentication", "rate-limiting", "monitoring", "swagger", "openapi"],
"homepage": "https://github.com/BitsHost/php-crud-api-generator",
"minimum-stability": "stable",
"authors": [
"authors": [
{
"name": "Adrian D",
"email": "contact@delvirai.net",
Expand All @@ -23,5 +25,9 @@
},
"require-dev": {
"phpunit/phpunit": "^10.0"
},
"support": {
"issues": "https://github.com/BitsHost/php-crud-api-generator/issues",
"source": "https://github.com/BitsHost/php-crud-api-generator"
}
}
Loading