initial
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
<?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)
|
||||
* );
|
||||
*
|
||||
* Config via env: FCM_LIMIT_PER_HOUR, FCM_LIMIT_PER_DAY, MAPS_LIMIT_PER_DAY, etc.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user