Page MenuHomePhorge

D5865.1775178732.diff
No OneTemporary

Authored By
Unknown
Size
8 KB
Referenced Files
None
Subscribers
None

D5865.1775178732.diff

diff --git a/doc/Policies/RATELIMIT.md b/doc/Policies/RATELIMIT.md
--- a/doc/Policies/RATELIMIT.md
+++ b/doc/Policies/RATELIMIT.md
@@ -10,20 +10,17 @@
1. Mail from soft-deleted or suspended senders is put on HOLD.
2. Whitelisted senders are NOT rate limited (see the Whitelists section below).
-3. Accounts with 100% discount are NOT rate limited.
-4. Accounts with positive balance and any payments are NOT rate limited.
-5. If a sender or all users in an account, in last 60 minutes:
- a) sent at least `RATELIMIT_MAX_MESSAGES` (default: 10) messages or
- b) sent messages to at least `RATELIMIT_MAX_RECIPIENTS` (default: 250) recipients,
- sumbission if DEFER-ed.
+3. If a sender or all users in an account, in last 60 minutes sent messages to
+ at least `RATELIMIT_MAX_RECIPIENTS` (default: 250) recipients, sumbission is DEFER-ed.
+ The limit for new (restricted) accounts is different (`RATELIMIT_MAX_RECIPIENTS_RESTRICTED`).
## Automatic suspending
-A sender (or the whole account) created in last two months gets suspended if the submission rate
-is exceeded too much. Limits are:
+A sender (or the whole account) gets suspended if the submission rate is exceeded too much. Limit
+to number of recipients in last 60 minutes is:
-- count of messages in last 60 minutes: (`RATELIMIT_MAX_MESSAGES * RATELIMIT_SUSPEND_FACTOR`)
-- count of recipients in last 60 minutes: (`RATELIMIT_MAX_RECIPIENTS * RATELIMIT_SUSPEND_FACTOR`)
+- for all accounts: `RATELIMIT_SUSPEND_MAX_RECIPIENTS`
+- for new (restricted) accounts: `RATELIMIT_SUSPEND_MAX_RECIPIENTS_RESTRICTED`
## Whitelists
diff --git a/src/app/Policy/RateLimit.php b/src/app/Policy/RateLimit.php
--- a/src/app/Policy/RateLimit.php
+++ b/src/app/Policy/RateLimit.php
@@ -2,8 +2,8 @@
namespace App\Policy;
+use App\EventLog;
use App\Traits\BelongsToUserTrait;
-use App\Transaction;
use App\User;
use App\UserAlias;
use App\Utils;
@@ -133,94 +133,54 @@
$request->save();
}
- // exempt owners that have 100% discount.
- if ($wallet->discount && $wallet->discount->discount == 100) {
- return new Response(Response::ACTION_DUNNO);
+ // Examine the rates at which the account is sending
+ if ($error = self::checkLimits($user, $owner)) {
+ return new Response(Response::ACTION_DEFER_IF_PERMIT, $error, 403);
}
- // exempt owners that currently maintain a positive balance and made any payments.
- // Because there might be users that pay via external methods (and don't have Payment records)
- // we can't check only the Payments table. Instead we assume that a credit/award transaction
- // is enough to consider the user a "paying user" for purpose of the rate limit.
- if ($wallet->balance > 0) {
- $isPayer = $wallet->transactions()
- ->whereIn('type', [Transaction::WALLET_AWARD, Transaction::WALLET_CREDIT])
- ->where('amount', '>', 0)
- ->exists();
-
- if ($isPayer) {
- return new Response(Response::ACTION_DUNNO);
- }
- }
+ return new Response(Response::ACTION_DUNNO);
+ }
- $max_messages = config('app.ratelimit_max_messages');
+ /**
+ * Check number of recipients limit
+ */
+ private static function checkLimits($user, $owner): ?string
+ {
$max_recipients = config('app.ratelimit_max_recipients');
- $suspend_factor = config('app.ratelimit_suspend_factor');
+ $max_recipients_restricted = config('app.ratelimit_max_recipients_restricted');
+ $suspend_max_recipients = config('app.ratelimit_suspend_max_recipients');
+ $suspend_max_recipients_restricted = config('app.ratelimit_suspend_max_recipients_restricted');
- $ageThreshold = Carbon::now()->subMonthsWithoutOverflow(2);
+ // New users should get a lower limit
+ if ($owner->isRestricted() && $max_recipients_restricted) {
+ $max_recipients = $max_recipients_restricted;
+ }
- // Examine the rates at which the owner (or its users) is sending
- $ownerRates = self::where('owner_id', $owner->id)
- ->where('updated_at', '>=', Carbon::now()->subHour());
+ $recipient_count = self::where('owner_id', $owner->id)
+ ->where('updated_at', '>=', Carbon::now()->subHour())
+ ->sum('recipient_count');
- if (($count = $ownerRates->count()) >= $max_messages) {
- // automatically suspend (recursively) if X times over the original limit and younger than two months
- if ($count >= $max_messages * $suspend_factor && $owner->created_at > $ageThreshold) {
- $owner->suspendAccount();
+ if ($recipient_count >= $max_recipients) {
+ // New users should get a lower limit for suspension
+ if ($owner->isRestricted() && $suspend_max_recipients_restricted) {
+ $suspend_max_recipients = $suspend_max_recipients_restricted;
}
- return new Response(
- Response::ACTION_DEFER_IF_PERMIT,
- "The account is at {$max_messages} messages per hour, cool down.",
- 403
- );
- }
-
- if (($recipientCount = $ownerRates->sum('recipient_count')) >= $max_recipients) {
- // automatically suspend if X times over the original limit and younger than two months
- if ($recipientCount >= $max_recipients * $suspend_factor && $owner->created_at > $ageThreshold) {
+ // automatically suspend if X times over the original limit
+ if ($recipient_count >= $suspend_max_recipients) {
$owner->suspendAccount();
- }
- return new Response(
- Response::ACTION_DEFER_IF_PERMIT,
- "The account is at {$max_recipients} recipients per hour, cool down.",
- 403
- );
- }
+ // TODO: We could include in the message who sent how many messages
+ EventLog::createFor($owner, EventLog::TYPE_SUSPENDED, "Submission rate limit exceeded by {$user->email}");
- // Examine the rates at which the user is sending (if not also the owner)
- if ($user->id != $owner->id) {
- $userRates = self::where('user_id', $user->id)
- ->where('updated_at', '>=', Carbon::now()->subHour());
-
- if (($count = $userRates->count()) >= $max_messages) {
- // automatically suspend if X times over the original limit and younger than two months
- if ($count >= $max_messages * $suspend_factor && $user->created_at > $ageThreshold) {
- $user->suspend();
- }
-
- return new Response(
- Response::ACTION_DEFER_IF_PERMIT,
- "User is at {$max_messages} messages per hour, cool down.",
- 403
- );
+ // TODO: Send a notification email to the account owner?
}
- if (($recipientCount = $userRates->sum('recipient_count')) >= $max_recipients) {
- // automatically suspend if X times over the original limit
- if ($recipientCount >= $max_recipients * $suspend_factor && $user->created_at > $ageThreshold) {
- $user->suspend();
- }
-
- return new Response(
- Response::ACTION_DEFER_IF_PERMIT,
- "The account is at {$max_recipients} recipients per hour, cool down.",
- 403
- );
- }
+ return "The account is at {$max_recipients} recipients per hour, cool down.";
}
- return new Response(Response::ACTION_DUNNO);
+ // TODO: Add another cumulative limit (for 24 hours)?
+
+ return null;
}
}
diff --git a/src/config/app.php b/src/config/app.php
--- a/src/config/app.php
+++ b/src/config/app.php
@@ -275,9 +275,11 @@
'woat_ns2' => env('WOAT_NS2', 'ns02.' . env('APP_DOMAIN')),
'ratelimit_whitelist' => explode(',', env('RATELIMIT_WHITELIST', '')),
- 'ratelimit_max_messages' => (int) env('RATELIMIT_MAX_MESSAGES', 10),
'ratelimit_max_recipients' => (int) env('RATELIMIT_MAX_RECIPIENTS', 100),
- 'ratelimit_suspend_factor' => (float) env('RATELIMIT_SUSPEND_FACTOR', 2.5),
+ 'ratelimit_max_recipients_restricted' => (int) env('RATELIMIT_MAX_RECIPIENTS_RESTRICTED'),
+ 'ratelimit_suspend_max_recipients' => (int) env('RATELIMIT_SUSPEND_MAX_RECIPIENTS', 250),
+ 'ratelimit_suspend_max_recipients_restricted' => (int) env('RATELIMIT_SUSPEND_MAX_RECIPIENTS_RESTRICTED'),
+
'companion_download_link' => env(
'COMPANION_DOWNLOAD_LINK',
"https://mirror.apheleia-it.ch/pub/companion-app-beta.apk"

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 3, 1:12 AM (21 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18821853
Default Alt Text
D5865.1775178732.diff (8 KB)

Event Timeline