Anti-abuse hardening: hourly posting rate limit + captcha on facility registration
- SubmissionGuard.PostingRateExceededAsync: max 20 new listings (shifts+jobs) per account per rolling hour, enforced in PostJob + PostShift - Captcha + spam-name screen added to /Employer/RegisterFacility Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,18 @@ public class SubmissionGuard
|
||||
return candidates.Any(c => Normalize(c) == t);
|
||||
}
|
||||
|
||||
/// <summary>Max new listings (shifts + jobs) one account may post per rolling hour.</summary>
|
||||
public const int MaxListingsPerHour = 20;
|
||||
|
||||
/// <summary>True if this owner has hit the hourly posting cap (flood protection).</summary>
|
||||
public async Task<bool> PostingRateExceededAsync(int ownerUserId)
|
||||
{
|
||||
var since = DateTime.UtcNow.AddHours(-1);
|
||||
var shifts = await _db.Shifts.CountAsync(s => s.Facility.OwnerUserId == ownerUserId && s.CreatedAt >= since);
|
||||
var jobs = await _db.JobOpenings.CountAsync(j => j.Facility.OwnerUserId == ownerUserId && j.CreatedAt >= since);
|
||||
return shifts + jobs >= MaxListingsPerHour;
|
||||
}
|
||||
|
||||
/// <summary>Has this visitor already applied (Apply event) to this shift/job?</summary>
|
||||
public Task<bool> AlreadyAppliedAsync(string visitorId, int? shiftId, int? jobId) =>
|
||||
_db.InterestEvents.AnyAsync(e => e.VisitorId == visitorId
|
||||
|
||||
Reference in New Issue
Block a user