68 lines
2.7 KiB
PHP
Executable File
68 lines
2.7 KiB
PHP
Executable File
<?php
|
|
defined('BASEPATH') or exit('No direct script access allowed');
|
|
|
|
/**
|
|
* Per-key quota limiter (e.g. per user, per token) for FCM, Maps, and other API usage.
|
|
* Uses database table quota_usage. Create with:
|
|
* CREATE TABLE IF NOT EXISTS quota_usage (
|
|
* id INT AUTO_INCREMENT PRIMARY KEY,
|
|
* key_name VARCHAR(255) NOT NULL,
|
|
* period_type VARCHAR(16) NOT NULL,
|
|
* period_value VARCHAR(32) NOT NULL,
|
|
* count INT UNSIGNED NOT NULL DEFAULT 0,
|
|
* updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
* UNIQUE KEY uk_key_period (key_name, period_type, period_value)
|
|
* );
|
|
*
|
|
* Callers pass limits; backend defaults often use FCM_LIMIT_PER_HOUR / FCM_LIMIT_PER_DAY from config.php.
|
|
*/
|
|
|
|
if (!function_exists('quota_limiter_allow')) {
|
|
/**
|
|
* Check and increment usage for the given key. Returns true if under limit, false if over.
|
|
* @param string $key Unique key (e.g. "fcm:recipient:".hash($token) or "maps:user:123")
|
|
* @param array $limits ['hour' => N, 'day' => N]. Use 0 to skip that period.
|
|
* @return bool True if request is allowed, false if over limit
|
|
*/
|
|
function quota_limiter_allow($key, $limits = array())
|
|
{
|
|
$CI = &get_instance();
|
|
if (!isset($CI->db) || !$CI->db->conn_id) {
|
|
return true;
|
|
}
|
|
$table = 'quota_usage';
|
|
$hour_period = date('Y-m-d-H');
|
|
$day_period = date('Y-m-d');
|
|
$hour_limit = isset($limits['hour']) ? (int) $limits['hour'] : 100;
|
|
$day_limit = isset($limits['day']) ? (int) $limits['day'] : 500;
|
|
$key_safe = substr($key, 0, 255);
|
|
|
|
foreach (array('hour' => array($hour_period, $hour_limit), 'day' => array($day_period, $day_limit)) as $period_type => $pair) {
|
|
list($period_value, $limit) = $pair;
|
|
if ($limit <= 0) {
|
|
continue;
|
|
}
|
|
$CI->db->query("
|
|
INSERT INTO {$table} (key_name, period_type, period_value, count, updated_at)
|
|
VALUES (?, ?, ?, 1, NOW())
|
|
ON DUPLICATE KEY UPDATE count = count + 1, updated_at = NOW()
|
|
", array($key_safe, $period_type, $period_value));
|
|
$row = $CI->db->query("
|
|
SELECT count FROM {$table}
|
|
WHERE key_name = ? AND period_type = ? AND period_value = ?
|
|
", array($key_safe, $period_type, $period_value))->row();
|
|
if ($row && (int) $row->count > $limit) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (!function_exists('quota_limiter_fcm_key')) {
|
|
function quota_limiter_fcm_key($recipient_identifier)
|
|
{
|
|
return 'fcm:' . substr(md5($recipient_identifier), 0, 32);
|
|
}
|
|
}
|