Add configurable API rate limits with subtabs in settings (v0.10.0)
- Make rate limiting configurable via WordPress options - Add subtabs to API settings: General, Rate Limits, Endpoints - Add HTTP method badges for endpoint documentation - Update CHANGELOG with rate limiting configuration details Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
16
CHANGELOG.md
16
CHANGELOG.md
@@ -46,21 +46,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Pricing API:
|
- Pricing API:
|
||||||
- `POST /wp-bnb/v1/pricing/calculate` - Full price calculation with services
|
- `POST /wp-bnb/v1/pricing/calculate` - Full price calculation with services
|
||||||
- `GET /wp-bnb/v1/pricing/seasons` - Get configured seasons and pricing modifiers
|
- `GET /wp-bnb/v1/pricing/seasons` - Get configured seasons and pricing modifiers
|
||||||
- API Settings tab in plugin settings:
|
- API Settings tab in plugin settings with three subtabs:
|
||||||
- Enable/disable REST API toggle
|
- General subtab: Enable/disable REST API, rate limiting toggle, API information
|
||||||
- Enable/disable rate limiting toggle
|
- Rate Limits subtab: Configurable time window and endpoint-specific limits
|
||||||
- Endpoint documentation table
|
- Endpoints subtab: Full endpoint documentation with HTTP method badges
|
||||||
- Authentication instructions
|
- Configurable rate limiting:
|
||||||
|
- Time window setting (10-300 seconds, default 60)
|
||||||
|
- Per-endpoint-type limits (public, availability, booking, admin)
|
||||||
|
- Settings stored in WordPress options, defaults maintained in code
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Plugin.php updated to initialize REST API on `rest_api_init` hook
|
- Plugin.php updated to initialize REST API on `rest_api_init` hook
|
||||||
- Settings page now has seven tabs: General, Pricing, License, Updates, Metrics, API
|
- Settings page now has seven tabs: General, Pricing, License, Updates, Metrics, API
|
||||||
- README.md updated with comprehensive REST API documentation
|
- README.md updated with comprehensive REST API documentation
|
||||||
|
- RateLimiter class now loads limits from WordPress options with fallback defaults
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- Rate limiting: public (60/min), availability (30/min), booking (10/min), admin (120/min)
|
- Rate limiting: configurable per endpoint type (defaults: public 60/min, availability 30/min, booking 10/min, admin 120/min)
|
||||||
- Admin endpoints require `edit_posts` capability
|
- Admin endpoints require `edit_posts` capability
|
||||||
- Supports WordPress Application Passwords for external API access
|
- Supports WordPress Application Passwords for external API access
|
||||||
- Client identification by user ID (authenticated) or IP address (anonymous)
|
- Client identification by user ID (authenticated) or IP address (anonymous)
|
||||||
|
|||||||
18
README.md
18
README.md
@@ -451,8 +451,10 @@ The plugin provides a comprehensive REST API for integration with external appli
|
|||||||
### Enabling the API
|
### Enabling the API
|
||||||
|
|
||||||
1. Navigate to **WP BnB → Settings → API**
|
1. Navigate to **WP BnB → Settings → API**
|
||||||
2. Enable "Enable REST API"
|
2. In the **General** subtab, enable "Enable REST API"
|
||||||
3. Optionally enable rate limiting for protection against abuse
|
3. Optionally enable rate limiting for protection against abuse
|
||||||
|
4. Configure rate limits in the **Rate Limits** subtab
|
||||||
|
5. View all available endpoints in the **Endpoints** subtab
|
||||||
|
|
||||||
### Base URL
|
### Base URL
|
||||||
|
|
||||||
@@ -517,15 +519,23 @@ curl -u "username:app-password" https://site.com/wp-json/wp-bnb/v1/bookings
|
|||||||
|
|
||||||
### Rate Limiting
|
### Rate Limiting
|
||||||
|
|
||||||
When enabled, rate limits are applied per client (by user ID or IP address):
|
When enabled, rate limits are applied per client (by user ID or IP address). Configure limits in **Settings → API → Rate Limits**.
|
||||||
|
|
||||||
| Type | Limit | Applies To |
|
**Default Limits:**
|
||||||
| ---- | ----- | ---------- |
|
|
||||||
|
| Type | Default | Applies To |
|
||||||
|
| ---- | ------- | ---------- |
|
||||||
| Public | 60/min | Room/building listings |
|
| Public | 60/min | Room/building listings |
|
||||||
| Availability | 30/min | Availability and calendar endpoints |
|
| Availability | 30/min | Availability and calendar endpoints |
|
||||||
| Booking | 10/min | Booking creation |
|
| Booking | 10/min | Booking creation |
|
||||||
| Admin | 120/min | All admin endpoints |
|
| Admin | 120/min | All admin endpoints |
|
||||||
|
|
||||||
|
**Configuration Options:**
|
||||||
|
|
||||||
|
- **Time Window**: 10-300 seconds (default: 60 seconds)
|
||||||
|
- **Per-endpoint limits**: Customize for each endpoint type
|
||||||
|
- **Rate limiting toggle**: Enable/disable without losing settings
|
||||||
|
|
||||||
Rate limit headers are included in responses:
|
Rate limit headers are included in responses:
|
||||||
|
|
||||||
- `X-RateLimit-Limit`: Maximum requests allowed
|
- `X-RateLimit-Limit`: Maximum requests allowed
|
||||||
|
|||||||
@@ -491,6 +491,37 @@
|
|||||||
height: 16px;
|
height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* API Method Badges */
|
||||||
|
.wp-bnb-method {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-bnb-method.get {
|
||||||
|
background: #e7f5e7;
|
||||||
|
color: #1e7e1e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-bnb-method.post {
|
||||||
|
background: #e7f0f5;
|
||||||
|
color: #1e5f7e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-bnb-method.patch {
|
||||||
|
background: #f5f0e7;
|
||||||
|
color: #7e5f1e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-bnb-method.delete {
|
||||||
|
background: #f5e7e7;
|
||||||
|
color: #7e1e1e;
|
||||||
|
}
|
||||||
|
|
||||||
/* Form Tables */
|
/* Form Tables */
|
||||||
.form-table th {
|
.form-table th {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
|
|||||||
@@ -22,23 +22,61 @@ final class RateLimiter {
|
|||||||
private const TRANSIENT_PREFIX = 'wp_bnb_rate_';
|
private const TRANSIENT_PREFIX = 'wp_bnb_rate_';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rate limits per minute by endpoint type.
|
* Default rate limits per minute by endpoint type.
|
||||||
*
|
*
|
||||||
* @var array<string, int>
|
* @var array<string, int>
|
||||||
*/
|
*/
|
||||||
private array $limits = array(
|
private const DEFAULT_LIMITS = array(
|
||||||
'public' => 60, // Public read endpoints.
|
'public' => 60, // Public read endpoints.
|
||||||
'availability' => 30, // Availability checks.
|
'availability' => 30, // Availability checks.
|
||||||
'booking' => 10, // Booking creation.
|
'booking' => 10, // Booking creation.
|
||||||
'admin' => 120, // Admin endpoints.
|
'admin' => 120, // Admin endpoints.
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rate limits per minute by endpoint type.
|
||||||
|
*
|
||||||
|
* @var array<string, int>
|
||||||
|
*/
|
||||||
|
private array $limits;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Time window in seconds.
|
* Time window in seconds.
|
||||||
*
|
*
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
private int $window = 60;
|
private int $window;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
$this->load_limits_from_options();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load rate limits from WordPress options.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function load_limits_from_options(): void {
|
||||||
|
$this->limits = array(
|
||||||
|
'public' => (int) get_option( 'wp_bnb_rate_limit_public', self::DEFAULT_LIMITS['public'] ),
|
||||||
|
'availability' => (int) get_option( 'wp_bnb_rate_limit_availability', self::DEFAULT_LIMITS['availability'] ),
|
||||||
|
'booking' => (int) get_option( 'wp_bnb_rate_limit_booking', self::DEFAULT_LIMITS['booking'] ),
|
||||||
|
'admin' => (int) get_option( 'wp_bnb_rate_limit_admin', self::DEFAULT_LIMITS['admin'] ),
|
||||||
|
);
|
||||||
|
$this->window = (int) get_option( 'wp_bnb_rate_limit_window', 60 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default rate limits.
|
||||||
|
*
|
||||||
|
* @return array<string, int>
|
||||||
|
*/
|
||||||
|
public static function get_default_limits(): array {
|
||||||
|
return self::DEFAULT_LIMITS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if request is within rate limit.
|
* Check if request is within rate limit.
|
||||||
|
|||||||
317
src/Plugin.php
317
src/Plugin.php
@@ -1460,13 +1460,48 @@ final class Plugin {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function render_api_settings(): void {
|
private function render_api_settings(): void {
|
||||||
|
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Subtab switching only.
|
||||||
|
$active_subtab = isset( $_GET['subtab'] ) ? sanitize_key( $_GET['subtab'] ) : 'general';
|
||||||
|
|
||||||
$api_enabled = get_option( 'wp_bnb_api_enabled', 'yes' );
|
$api_enabled = get_option( 'wp_bnb_api_enabled', 'yes' );
|
||||||
$rate_limiting = get_option( 'wp_bnb_api_rate_limiting', 'yes' );
|
$rate_limiting = get_option( 'wp_bnb_api_rate_limiting', 'yes' );
|
||||||
$api_base_url = rest_url( RestApi::NAMESPACE );
|
$api_base_url = rest_url( RestApi::NAMESPACE );
|
||||||
|
|
||||||
|
// Rate limit values.
|
||||||
|
$defaults = \Magdev\WpBnb\Api\RateLimiter::get_default_limits();
|
||||||
|
$limit_public = get_option( 'wp_bnb_rate_limit_public', $defaults['public'] );
|
||||||
|
$limit_avail = get_option( 'wp_bnb_rate_limit_availability', $defaults['availability'] );
|
||||||
|
$limit_booking = get_option( 'wp_bnb_rate_limit_booking', $defaults['booking'] );
|
||||||
|
$limit_admin = get_option( 'wp_bnb_rate_limit_admin', $defaults['admin'] );
|
||||||
|
$limit_window = get_option( 'wp_bnb_rate_limit_window', 60 );
|
||||||
|
|
||||||
|
$base_url = admin_url( 'admin.php?page=wp-bnb-settings&tab=api' );
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
<!-- API Subtabs -->
|
||||||
|
<div class="wp-bnb-subtabs">
|
||||||
|
<a href="<?php echo esc_url( $base_url . '&subtab=general' ); ?>"
|
||||||
|
class="wp-bnb-subtab <?php echo 'general' === $active_subtab ? 'active' : ''; ?>">
|
||||||
|
<span class="dashicons dashicons-admin-generic"></span>
|
||||||
|
<?php esc_html_e( 'General', 'wp-bnb' ); ?>
|
||||||
|
</a>
|
||||||
|
<a href="<?php echo esc_url( $base_url . '&subtab=rate-limits' ); ?>"
|
||||||
|
class="wp-bnb-subtab <?php echo 'rate-limits' === $active_subtab ? 'active' : ''; ?>">
|
||||||
|
<span class="dashicons dashicons-dashboard"></span>
|
||||||
|
<?php esc_html_e( 'Rate Limits', 'wp-bnb' ); ?>
|
||||||
|
</a>
|
||||||
|
<a href="<?php echo esc_url( $base_url . '&subtab=endpoints' ); ?>"
|
||||||
|
class="wp-bnb-subtab <?php echo 'endpoints' === $active_subtab ? 'active' : ''; ?>">
|
||||||
|
<span class="dashicons dashicons-rest-api"></span>
|
||||||
|
<?php esc_html_e( 'Endpoints', 'wp-bnb' ); ?>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form method="post" action="">
|
<form method="post" action="">
|
||||||
<?php wp_nonce_field( 'wp_bnb_save_settings', 'wp_bnb_settings_nonce' ); ?>
|
<?php wp_nonce_field( 'wp_bnb_save_settings', 'wp_bnb_settings_nonce' ); ?>
|
||||||
|
|
||||||
|
<?php if ( 'general' === $active_subtab ) : ?>
|
||||||
|
<!-- General Subtab -->
|
||||||
<h2><?php esc_html_e( 'REST API Settings', 'wp-bnb' ); ?></h2>
|
<h2><?php esc_html_e( 'REST API Settings', 'wp-bnb' ); ?></h2>
|
||||||
|
|
||||||
<table class="form-table">
|
<table class="form-table">
|
||||||
@@ -1491,6 +1526,9 @@ final class Plugin {
|
|||||||
</label>
|
</label>
|
||||||
<p class="description">
|
<p class="description">
|
||||||
<?php esc_html_e( 'Limits API requests to prevent abuse. Recommended for production sites.', 'wp-bnb' ); ?>
|
<?php esc_html_e( 'Limits API requests to prevent abuse. Recommended for production sites.', 'wp-bnb' ); ?>
|
||||||
|
<?php if ( 'yes' === $rate_limiting ) : ?>
|
||||||
|
<a href="<?php echo esc_url( $base_url . '&subtab=rate-limits' ); ?>"><?php esc_html_e( 'Configure limits', 'wp-bnb' ); ?> →</a>
|
||||||
|
<?php endif; ?>
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -1525,64 +1563,102 @@ final class Plugin {
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h2 style="margin-top: 30px;"><?php esc_html_e( 'Available Endpoints', 'wp-bnb' ); ?></h2>
|
<?php submit_button( __( 'Save Settings', 'wp-bnb' ) ); ?>
|
||||||
|
|
||||||
<h3><?php esc_html_e( 'Public Endpoints', 'wp-bnb' ); ?></h3>
|
<?php elseif ( 'rate-limits' === $active_subtab ) : ?>
|
||||||
<table class="widefat" style="margin-bottom: 20px;">
|
<!-- Rate Limits Subtab -->
|
||||||
<thead>
|
<h2><?php esc_html_e( 'Rate Limit Configuration', 'wp-bnb' ); ?></h2>
|
||||||
|
|
||||||
|
<?php if ( 'yes' !== $rate_limiting ) : ?>
|
||||||
|
<div class="notice notice-warning inline" style="margin: 15px 0;">
|
||||||
|
<p>
|
||||||
|
<?php esc_html_e( 'Rate limiting is currently disabled.', 'wp-bnb' ); ?>
|
||||||
|
<a href="<?php echo esc_url( $base_url . '&subtab=general' ); ?>"><?php esc_html_e( 'Enable it in General settings', 'wp-bnb' ); ?></a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<p class="description"><?php esc_html_e( 'Configure the number of requests allowed per time window for each endpoint type.', 'wp-bnb' ); ?></p>
|
||||||
|
|
||||||
|
<table class="form-table">
|
||||||
<tr>
|
<tr>
|
||||||
<th><?php esc_html_e( 'Method', 'wp-bnb' ); ?></th>
|
<th scope="row"><?php esc_html_e( 'Time Window', 'wp-bnb' ); ?></th>
|
||||||
<th><?php esc_html_e( 'Endpoint', 'wp-bnb' ); ?></th>
|
<td>
|
||||||
<th><?php esc_html_e( 'Description', 'wp-bnb' ); ?></th>
|
<input type="number" name="wp_bnb_rate_limit_window" value="<?php echo esc_attr( $limit_window ); ?>" min="10" max="300" step="10" class="small-text">
|
||||||
|
<?php esc_html_e( 'seconds', 'wp-bnb' ); ?>
|
||||||
|
<p class="description">
|
||||||
|
<?php esc_html_e( 'The time window for rate limit counting. Default: 60 seconds.', 'wp-bnb' ); ?>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Public Endpoints', 'wp-bnb' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<input type="number" name="wp_bnb_rate_limit_public" value="<?php echo esc_attr( $limit_public ); ?>" min="1" max="1000" class="small-text">
|
||||||
|
<?php esc_html_e( 'requests per window', 'wp-bnb' ); ?>
|
||||||
|
<p class="description">
|
||||||
|
<?php
|
||||||
|
printf(
|
||||||
|
/* translators: %d: default limit */
|
||||||
|
esc_html__( 'Limit for public read endpoints (rooms, buildings, services). Default: %d', 'wp-bnb' ),
|
||||||
|
$defaults['public']
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Availability Endpoints', 'wp-bnb' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<input type="number" name="wp_bnb_rate_limit_availability" value="<?php echo esc_attr( $limit_avail ); ?>" min="1" max="1000" class="small-text">
|
||||||
|
<?php esc_html_e( 'requests per window', 'wp-bnb' ); ?>
|
||||||
|
<p class="description">
|
||||||
|
<?php
|
||||||
|
printf(
|
||||||
|
/* translators: %d: default limit */
|
||||||
|
esc_html__( 'Limit for availability checks and calendar requests. Default: %d', 'wp-bnb' ),
|
||||||
|
$defaults['availability']
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Booking Endpoints', 'wp-bnb' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<input type="number" name="wp_bnb_rate_limit_booking" value="<?php echo esc_attr( $limit_booking ); ?>" min="1" max="100" class="small-text">
|
||||||
|
<?php esc_html_e( 'requests per window', 'wp-bnb' ); ?>
|
||||||
|
<p class="description">
|
||||||
|
<?php
|
||||||
|
printf(
|
||||||
|
/* translators: %d: default limit */
|
||||||
|
esc_html__( 'Limit for booking creation. Keep low to prevent abuse. Default: %d', 'wp-bnb' ),
|
||||||
|
$defaults['booking']
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Admin Endpoints', 'wp-bnb' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<input type="number" name="wp_bnb_rate_limit_admin" value="<?php echo esc_attr( $limit_admin ); ?>" min="1" max="1000" class="small-text">
|
||||||
|
<?php esc_html_e( 'requests per window', 'wp-bnb' ); ?>
|
||||||
|
<p class="description">
|
||||||
|
<?php
|
||||||
|
printf(
|
||||||
|
/* translators: %d: default limit */
|
||||||
|
esc_html__( 'Limit for authenticated admin endpoints. Default: %d', 'wp-bnb' ),
|
||||||
|
$defaults['admin']
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr><td>GET</td><td><code>/buildings</code></td><td><?php esc_html_e( 'List all buildings', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>GET</td><td><code>/buildings/{id}</code></td><td><?php esc_html_e( 'Get building details', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>GET</td><td><code>/buildings/{id}/rooms</code></td><td><?php esc_html_e( 'List rooms in building', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>GET</td><td><code>/rooms</code></td><td><?php esc_html_e( 'List/search rooms', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>GET</td><td><code>/rooms/{id}</code></td><td><?php esc_html_e( 'Get room details', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>GET</td><td><code>/rooms/{id}/availability</code></td><td><?php esc_html_e( 'Check room availability', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>GET</td><td><code>/rooms/{id}/calendar</code></td><td><?php esc_html_e( 'Get room calendar', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>POST</td><td><code>/availability/search</code></td><td><?php esc_html_e( 'Search available rooms', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>GET</td><td><code>/services</code></td><td><?php esc_html_e( 'List services', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>POST</td><td><code>/pricing/calculate</code></td><td><?php esc_html_e( 'Calculate booking price', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>POST</td><td><code>/bookings</code></td><td><?php esc_html_e( 'Create booking (pending status)', 'wp-bnb' ); ?></td></tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h3><?php esc_html_e( 'Admin Endpoints (Requires Authentication)', 'wp-bnb' ); ?></h3>
|
<h2 style="margin-top: 30px;"><?php esc_html_e( 'Current Rate Limits Summary', 'wp-bnb' ); ?></h2>
|
||||||
<table class="widefat" style="margin-bottom: 20px;">
|
<table class="widefat striped" style="max-width: 600px;">
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th><?php esc_html_e( 'Method', 'wp-bnb' ); ?></th>
|
|
||||||
<th><?php esc_html_e( 'Endpoint', 'wp-bnb' ); ?></th>
|
|
||||||
<th><?php esc_html_e( 'Description', 'wp-bnb' ); ?></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr><td>GET</td><td><code>/bookings</code></td><td><?php esc_html_e( 'List all bookings', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>GET</td><td><code>/bookings/{id}</code></td><td><?php esc_html_e( 'Get booking details', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>PATCH</td><td><code>/bookings/{id}</code></td><td><?php esc_html_e( 'Update booking', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>DELETE</td><td><code>/bookings/{id}</code></td><td><?php esc_html_e( 'Cancel booking', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>POST</td><td><code>/bookings/{id}/confirm</code></td><td><?php esc_html_e( 'Confirm booking', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>POST</td><td><code>/bookings/{id}/check-in</code></td><td><?php esc_html_e( 'Check in guest', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>POST</td><td><code>/bookings/{id}/check-out</code></td><td><?php esc_html_e( 'Check out guest', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>GET</td><td><code>/guests</code></td><td><?php esc_html_e( 'List guests', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>GET</td><td><code>/guests/{id}</code></td><td><?php esc_html_e( 'Get guest details', 'wp-bnb' ); ?></td></tr>
|
|
||||||
<tr><td>GET</td><td><code>/guests/search</code></td><td><?php esc_html_e( 'Search guests', 'wp-bnb' ); ?></td></tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h2 style="margin-top: 30px;"><?php esc_html_e( 'Authentication', 'wp-bnb' ); ?></h2>
|
|
||||||
<p><?php esc_html_e( 'Admin endpoints require authentication. Use one of the following methods:', 'wp-bnb' ); ?></p>
|
|
||||||
<ul style="list-style: disc; margin-left: 20px;">
|
|
||||||
<li><strong><?php esc_html_e( 'Application Passwords:', 'wp-bnb' ); ?></strong> <?php esc_html_e( 'Create one in Users > Your Profile. Use Basic Auth with username and app password.', 'wp-bnb' ); ?></li>
|
|
||||||
<li><strong><?php esc_html_e( 'Cookie + Nonce:', 'wp-bnb' ); ?></strong> <?php esc_html_e( 'For same-domain requests. Pass nonce in X-WP-Nonce header.', 'wp-bnb' ); ?></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2 style="margin-top: 30px;"><?php esc_html_e( 'Rate Limits', 'wp-bnb' ); ?></h2>
|
|
||||||
<table class="widefat" style="margin-bottom: 20px;">
|
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th><?php esc_html_e( 'Type', 'wp-bnb' ); ?></th>
|
<th><?php esc_html_e( 'Type', 'wp-bnb' ); ?></th>
|
||||||
@@ -1591,16 +1667,112 @@ final class Plugin {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td><?php esc_html_e( 'Public', 'wp-bnb' ); ?></td><td>60/min</td><td><?php esc_html_e( 'GET rooms, buildings, services', 'wp-bnb' ); ?></td></tr>
|
<tr>
|
||||||
<tr><td><?php esc_html_e( 'Availability', 'wp-bnb' ); ?></td><td>30/min</td><td><?php esc_html_e( 'Availability checks, calendar', 'wp-bnb' ); ?></td></tr>
|
<td><?php esc_html_e( 'Public', 'wp-bnb' ); ?></td>
|
||||||
<tr><td><?php esc_html_e( 'Booking', 'wp-bnb' ); ?></td><td>10/min</td><td><?php esc_html_e( 'Booking creation', 'wp-bnb' ); ?></td></tr>
|
<td><strong><?php echo esc_html( $limit_public . '/' . $limit_window . 's' ); ?></strong></td>
|
||||||
<tr><td><?php esc_html_e( 'Admin', 'wp-bnb' ); ?></td><td>120/min</td><td><?php esc_html_e( 'All admin endpoints', 'wp-bnb' ); ?></td></tr>
|
<td><?php esc_html_e( 'GET rooms, buildings, services', 'wp-bnb' ); ?></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><?php esc_html_e( 'Availability', 'wp-bnb' ); ?></td>
|
||||||
|
<td><strong><?php echo esc_html( $limit_avail . '/' . $limit_window . 's' ); ?></strong></td>
|
||||||
|
<td><?php esc_html_e( 'Availability checks, calendar', 'wp-bnb' ); ?></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><?php esc_html_e( 'Booking', 'wp-bnb' ); ?></td>
|
||||||
|
<td><strong><?php echo esc_html( $limit_booking . '/' . $limit_window . 's' ); ?></strong></td>
|
||||||
|
<td><?php esc_html_e( 'Booking creation', 'wp-bnb' ); ?></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><?php esc_html_e( 'Admin', 'wp-bnb' ); ?></td>
|
||||||
|
<td><strong><?php echo esc_html( $limit_admin . '/' . $limit_window . 's' ); ?></strong></td>
|
||||||
|
<td><?php esc_html_e( 'All admin endpoints', 'wp-bnb' ); ?></td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<p class="submit">
|
<?php submit_button( __( 'Save Rate Limits', 'wp-bnb' ) ); ?>
|
||||||
<?php submit_button( __( 'Save API Settings', 'wp-bnb' ), 'primary', 'submit', false ); ?>
|
|
||||||
</p>
|
<?php else : ?>
|
||||||
|
<!-- Endpoints Subtab -->
|
||||||
|
<h2><?php esc_html_e( 'Available Endpoints', 'wp-bnb' ); ?></h2>
|
||||||
|
|
||||||
|
<h3><?php esc_html_e( 'Public Endpoints', 'wp-bnb' ); ?></h3>
|
||||||
|
<p class="description"><?php esc_html_e( 'These endpoints are accessible without authentication.', 'wp-bnb' ); ?></p>
|
||||||
|
<table class="widefat striped" style="margin-bottom: 20px;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 80px;"><?php esc_html_e( 'Method', 'wp-bnb' ); ?></th>
|
||||||
|
<th style="width: 250px;"><?php esc_html_e( 'Endpoint', 'wp-bnb' ); ?></th>
|
||||||
|
<th><?php esc_html_e( 'Description', 'wp-bnb' ); ?></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/buildings</code></td><td><?php esc_html_e( 'List all buildings', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/buildings/{id}</code></td><td><?php esc_html_e( 'Get building details', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/buildings/{id}/rooms</code></td><td><?php esc_html_e( 'List rooms in building', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/rooms</code></td><td><?php esc_html_e( 'List/search rooms', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/rooms/{id}</code></td><td><?php esc_html_e( 'Get room details', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/rooms/{id}/availability</code></td><td><?php esc_html_e( 'Check room availability', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/rooms/{id}/calendar</code></td><td><?php esc_html_e( 'Get room calendar', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method post">POST</span></td><td><code>/availability/search</code></td><td><?php esc_html_e( 'Search available rooms', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/services</code></td><td><?php esc_html_e( 'List services', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method post">POST</span></td><td><code>/pricing/calculate</code></td><td><?php esc_html_e( 'Calculate booking price', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method post">POST</span></td><td><code>/bookings</code></td><td><?php esc_html_e( 'Create booking (pending status)', 'wp-bnb' ); ?></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3><?php esc_html_e( 'Admin Endpoints', 'wp-bnb' ); ?></h3>
|
||||||
|
<p class="description"><?php esc_html_e( 'These endpoints require authentication (Application Password or Cookie + Nonce).', 'wp-bnb' ); ?></p>
|
||||||
|
<table class="widefat striped" style="margin-bottom: 20px;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 80px;"><?php esc_html_e( 'Method', 'wp-bnb' ); ?></th>
|
||||||
|
<th style="width: 250px;"><?php esc_html_e( 'Endpoint', 'wp-bnb' ); ?></th>
|
||||||
|
<th><?php esc_html_e( 'Description', 'wp-bnb' ); ?></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/bookings</code></td><td><?php esc_html_e( 'List all bookings', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/bookings/{id}</code></td><td><?php esc_html_e( 'Get booking details', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method patch">PATCH</span></td><td><code>/bookings/{id}</code></td><td><?php esc_html_e( 'Update booking', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method delete">DELETE</span></td><td><code>/bookings/{id}</code></td><td><?php esc_html_e( 'Cancel booking', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method post">POST</span></td><td><code>/bookings/{id}/confirm</code></td><td><?php esc_html_e( 'Confirm booking', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method post">POST</span></td><td><code>/bookings/{id}/check-in</code></td><td><?php esc_html_e( 'Check in guest', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method post">POST</span></td><td><code>/bookings/{id}/check-out</code></td><td><?php esc_html_e( 'Check out guest', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/guests</code></td><td><?php esc_html_e( 'List guests', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/guests/{id}</code></td><td><?php esc_html_e( 'Get guest details', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/guests/search</code></td><td><?php esc_html_e( 'Search guests', 'wp-bnb' ); ?></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2 style="margin-top: 30px;"><?php esc_html_e( 'Authentication', 'wp-bnb' ); ?></h2>
|
||||||
|
<p><?php esc_html_e( 'Admin endpoints require authentication. Use one of the following methods:', 'wp-bnb' ); ?></p>
|
||||||
|
|
||||||
|
<table class="form-table">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">
|
||||||
|
<span class="dashicons dashicons-admin-network" style="color: #2271b1;"></span>
|
||||||
|
<?php esc_html_e( 'Application Passwords', 'wp-bnb' ); ?>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<p><?php esc_html_e( 'Create an Application Password in Users > Your Profile.', 'wp-bnb' ); ?></p>
|
||||||
|
<p><code>Authorization: Basic base64(username:app-password)</code></p>
|
||||||
|
<p class="description"><?php esc_html_e( 'Recommended for external applications and integrations.', 'wp-bnb' ); ?></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">
|
||||||
|
<span class="dashicons dashicons-lock" style="color: #2271b1;"></span>
|
||||||
|
<?php esc_html_e( 'Cookie + Nonce', 'wp-bnb' ); ?>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<p><?php esc_html_e( 'For same-domain JavaScript requests when user is logged in.', 'wp-bnb' ); ?></p>
|
||||||
|
<p><code>X-WP-Nonce: <?php echo esc_html( wp_create_nonce( 'wp_rest' ) ); ?></code></p>
|
||||||
|
<p class="description"><?php esc_html_e( 'Best for frontend JavaScript that interacts with the API.', 'wp-bnb' ); ?></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<?php endif; ?>
|
||||||
</form>
|
</form>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
@@ -1836,6 +2008,31 @@ final class Plugin {
|
|||||||
update_option( 'wp_bnb_api_enabled', $api_enabled );
|
update_option( 'wp_bnb_api_enabled', $api_enabled );
|
||||||
update_option( 'wp_bnb_api_rate_limiting', $rate_limiting );
|
update_option( 'wp_bnb_api_rate_limiting', $rate_limiting );
|
||||||
|
|
||||||
|
// Save rate limit configuration.
|
||||||
|
$defaults = \Magdev\WpBnb\Api\RateLimiter::get_default_limits();
|
||||||
|
|
||||||
|
$limit_window = isset( $_POST['wp_bnb_rate_limit_window'] )
|
||||||
|
? max( 10, min( 300, absint( $_POST['wp_bnb_rate_limit_window'] ) ) )
|
||||||
|
: 60;
|
||||||
|
$limit_public = isset( $_POST['wp_bnb_rate_limit_public'] )
|
||||||
|
? max( 1, min( 1000, absint( $_POST['wp_bnb_rate_limit_public'] ) ) )
|
||||||
|
: $defaults['public'];
|
||||||
|
$limit_avail = isset( $_POST['wp_bnb_rate_limit_availability'] )
|
||||||
|
? max( 1, min( 1000, absint( $_POST['wp_bnb_rate_limit_availability'] ) ) )
|
||||||
|
: $defaults['availability'];
|
||||||
|
$limit_booking = isset( $_POST['wp_bnb_rate_limit_booking'] )
|
||||||
|
? max( 1, min( 100, absint( $_POST['wp_bnb_rate_limit_booking'] ) ) )
|
||||||
|
: $defaults['booking'];
|
||||||
|
$limit_admin = isset( $_POST['wp_bnb_rate_limit_admin'] )
|
||||||
|
? max( 1, min( 1000, absint( $_POST['wp_bnb_rate_limit_admin'] ) ) )
|
||||||
|
: $defaults['admin'];
|
||||||
|
|
||||||
|
update_option( 'wp_bnb_rate_limit_window', $limit_window );
|
||||||
|
update_option( 'wp_bnb_rate_limit_public', $limit_public );
|
||||||
|
update_option( 'wp_bnb_rate_limit_availability', $limit_avail );
|
||||||
|
update_option( 'wp_bnb_rate_limit_booking', $limit_booking );
|
||||||
|
update_option( 'wp_bnb_rate_limit_admin', $limit_admin );
|
||||||
|
|
||||||
add_settings_error( 'wp_bnb_settings', 'settings_saved', __( 'API settings saved.', 'wp-bnb' ), 'success' );
|
add_settings_error( 'wp_bnb_settings', 'settings_saved', __( 'API settings saved.', 'wp-bnb' ), 'success' );
|
||||||
settings_errors( 'wp_bnb_settings' );
|
settings_errors( 'wp_bnb_settings' );
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user