visitor.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package server
  2. import (
  3. "errors"
  4. "golang.org/x/time/rate"
  5. "heckel.io/ntfy/util"
  6. "sync"
  7. "time"
  8. )
  9. const (
  10. // visitorExpungeAfter defines how long a visitor is active before it is removed from memory. This number
  11. // has to be very high to prevent e-mail abuse, but it doesn't really affect the other limits anyway, since
  12. // they are replenished faster (typically).
  13. visitorExpungeAfter = 24 * time.Hour
  14. )
  15. var (
  16. errVisitorLimitReached = errors.New("limit reached")
  17. )
  18. // visitor represents an API user, and its associated rate.Limiter used for rate limiting
  19. type visitor struct {
  20. config *Config
  21. ip string
  22. requests *rate.Limiter
  23. subscriptions *util.Limiter
  24. emails *rate.Limiter
  25. seen time.Time
  26. mu sync.Mutex
  27. }
  28. func newVisitor(conf *Config, ip string) *visitor {
  29. return &visitor{
  30. config: conf,
  31. ip: ip,
  32. requests: rate.NewLimiter(rate.Every(conf.VisitorRequestLimitReplenish), conf.VisitorRequestLimitBurst),
  33. subscriptions: util.NewLimiter(int64(conf.VisitorSubscriptionLimit)),
  34. emails: rate.NewLimiter(rate.Every(conf.VisitorEmailLimitReplenish), conf.VisitorEmailLimitBurst),
  35. seen: time.Now(),
  36. }
  37. }
  38. func (v *visitor) IP() string {
  39. return v.ip
  40. }
  41. func (v *visitor) RequestAllowed() error {
  42. if !v.requests.Allow() {
  43. return errVisitorLimitReached
  44. }
  45. return nil
  46. }
  47. func (v *visitor) EmailAllowed() error {
  48. if !v.emails.Allow() {
  49. return errVisitorLimitReached
  50. }
  51. return nil
  52. }
  53. func (v *visitor) SubscriptionAllowed() error {
  54. v.mu.Lock()
  55. defer v.mu.Unlock()
  56. if err := v.subscriptions.Add(1); err != nil {
  57. return errVisitorLimitReached
  58. }
  59. return nil
  60. }
  61. func (v *visitor) RemoveSubscription() {
  62. v.mu.Lock()
  63. defer v.mu.Unlock()
  64. v.subscriptions.Sub(1)
  65. }
  66. func (v *visitor) Keepalive() {
  67. v.mu.Lock()
  68. defer v.mu.Unlock()
  69. v.seen = time.Now()
  70. }
  71. func (v *visitor) Stale() bool {
  72. v.mu.Lock()
  73. defer v.mu.Unlock()
  74. return time.Since(v.seen) > visitorExpungeAfter
  75. }