summaryrefslogtreecommitdiff
path: root/src/server/api/limiter.ts
diff options
context:
space:
mode:
authorAcid Chicken (硫酸鶏) <root@acid-chicken.com>2018-12-25 20:02:37 +0900
committerAcid Chicken (硫酸鶏) <root@acid-chicken.com>2018-12-25 20:02:37 +0900
commitfa03c172f211f84dd9747fcf312ec41a92d1102b (patch)
treedbd75bb96b3a30cbc1c3f30e85f44b25f54d6917 /src/server/api/limiter.ts
parentFix typo (diff)
downloadsharkey-fa03c172f211f84dd9747fcf312ec41a92d1102b.tar.gz
sharkey-fa03c172f211f84dd9747fcf312ec41a92d1102b.tar.bz2
sharkey-fa03c172f211f84dd9747fcf312ec41a92d1102b.zip
Fix typo
Diffstat (limited to 'src/server/api/limiter.ts')
-rw-r--r--src/server/api/limiter.ts89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/server/api/limiter.ts b/src/server/api/limiter.ts
new file mode 100644
index 0000000000..192aa19770
--- /dev/null
+++ b/src/server/api/limiter.ts
@@ -0,0 +1,89 @@
+import * as Limiter from 'ratelimiter';
+import * as debug from 'debug';
+import limiterDB from '../../db/redis';
+import { IEndpoint } from './endpoints';
+import getAcct from '../../misc/acct/render';
+import { IUser } from '../../models/user';
+
+const log = debug('misskey:limiter');
+
+export default (endpoint: IEndpoint, user: IUser) => new Promise((ok, reject) => {
+ // Redisがインストールされてない場合は常に許可
+ if (limiterDB == null) {
+ ok();
+ return;
+ }
+
+ const limitation = endpoint.meta.limit;
+
+ const key = limitation.hasOwnProperty('key')
+ ? limitation.key
+ : endpoint.name;
+
+ const hasShortTermLimit =
+ limitation.hasOwnProperty('minInterval');
+
+ const hasLongTermLimit =
+ limitation.hasOwnProperty('duration') &&
+ limitation.hasOwnProperty('max');
+
+ if (hasShortTermLimit) {
+ min();
+ } else if (hasLongTermLimit) {
+ max();
+ } else {
+ ok();
+ }
+
+ // Short-term limit
+ function min() {
+ const minIntervalLimiter = new Limiter({
+ id: `${user._id}:${key}:min`,
+ duration: limitation.minInterval,
+ max: 1,
+ db: limiterDB
+ });
+
+ minIntervalLimiter.get((err, info) => {
+ if (err) {
+ return reject('ERR');
+ }
+
+ log(`@${getAcct(user)} ${endpoint.name} min remaining: ${info.remaining}`);
+
+ if (info.remaining === 0) {
+ reject('BRIEF_REQUEST_INTERVAL');
+ } else {
+ if (hasLongTermLimit) {
+ max();
+ } else {
+ ok();
+ }
+ }
+ });
+ }
+
+ // Long term limit
+ function max() {
+ const limiter = new Limiter({
+ id: `${user._id}:${key}`,
+ duration: limitation.duration,
+ max: limitation.max,
+ db: limiterDB
+ });
+
+ limiter.get((err, info) => {
+ if (err) {
+ return reject('ERR');
+ }
+
+ log(`@${getAcct(user)} ${endpoint.name} max remaining: ${info.remaining}`);
+
+ if (info.remaining === 0) {
+ reject('RATE_LIMIT_EXCEEDED');
+ } else {
+ ok();
+ }
+ });
+ }
+});