def _has_exceeded_ratelimit(self, form, room): # grab the ratelimit (as average events per second) for the room's # current level, using the highest level configured that's not bigger # than the room. e.g. if ratelimits are defined for levels 1, 2, and 4 # and the room is level 3, this will give us the ratelimit specified # for 2. desired_avg_per_sec = 1 by_level = g.live_config.get("robin_ratelimit_avg_per_sec", {}) for level, avg_per_sec in sorted(by_level.items(), key=lambda (x, y): int(x)): if int(level) > room.level: break desired_avg_per_sec = avg_per_sec # now figure out how many events per window that means window_size = g.live_config.get("robin_ratelimit_window", 10) allowed_events_per_window = int(desired_avg_per_sec * window_size) try: # now figure out how much they've actually used ratelimit_key = "robin/{}".format(c.user._id36) time_slice = ratelimit.get_timeslice(window_size) usage = ratelimit.get_usage(ratelimit_key, time_slice) # ratelimit them if too much if usage >= allowed_events_per_window: g.stats.simple_event("robin.ratelimit.exceeded") period_end = datetime.datetime.utcfromtimestamp(time_slice.end) period_end_utc = period_end.replace(tzinfo=pytz.UTC) until_reset = utils.timeuntil(period_end_utc) c.errors.add(errors.RATELIMIT, {"time": until_reset}, field="ratelimit", code=429) form.has_errors("ratelimit", errors.RATELIMIT) return True # or record the usage and move on ratelimit.record_usage(ratelimit_key, time_slice) except ratelimit.RatelimitError as exc: g.log.warning("ratelimit error: %s", exc) return False
def _has_exceeded_ratelimit(self, form, room): # grab the ratelimit (as average events per second) for the room's # current level, using the highest level configured that's not bigger # than the room. e.g. if ratelimits are defined for levels 1, 2, and 4 # and the room is level 3, this will give us the ratelimit specified # for 2. desired_avg_per_sec = 1 by_level = g.live_config.get("robin_ratelimit_avg_per_sec", {}) for level, avg_per_sec in sorted(by_level.items(), key=lambda (x,y): int(x)): if int(level) > room.level: break desired_avg_per_sec = avg_per_sec # now figure out how many events per window that means window_size = g.live_config.get("robin_ratelimit_window", 10) allowed_events_per_window = int(desired_avg_per_sec * window_size) try: # now figure out how much they've actually used ratelimit_key = "robin/{}".format(c.user._id36) time_slice = ratelimit.get_timeslice(window_size) usage = ratelimit.get_usage(ratelimit_key, time_slice) # ratelimit them if too much if usage >= allowed_events_per_window: g.stats.simple_event("robin.ratelimit.exceeded") period_end = datetime.datetime.utcfromtimestamp(time_slice.end) period_end_utc = period_end.replace(tzinfo=pytz.UTC) until_reset = utils.timeuntil(period_end_utc) c.errors.add(errors.RATELIMIT, {"time": until_reset}, field="ratelimit", code=429) form.has_errors("ratelimit", errors.RATELIMIT) return True # or record the usage and move on ratelimit.record_usage(ratelimit_key, time_slice) except ratelimit.RatelimitError as exc: g.log.warning("ratelimit error: %s", exc) return False
def test_get_usage(self): self.now = 24 * 3600 + 5 * 3600 ts = ratelimit.get_timeslice(3600) self.assertEquals(None, ratelimit.get_usage('a', ts)) ratelimit.record_usage('a', ts) self.assertEquals(1, ratelimit.get_usage('a', ts))