Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop
This commit is contained in:
@ -6,6 +6,9 @@ const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/;
|
||||
const urlRegexFull = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+$/;
|
||||
|
||||
export function fromHtml(html: string, hashtagNames?: string[]): string {
|
||||
// some AP servers like Pixelfed use br tags as well as newlines
|
||||
html = html.replace(/<br\s?\/?>\r?\n/gi, '\n');
|
||||
|
||||
const dom = parse5.parseFragment(html);
|
||||
|
||||
let text = '';
|
||||
|
9
packages/backend/src/misc/get-ip-hash.ts
Normal file
9
packages/backend/src/misc/get-ip-hash.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import IPCIDR from 'ip-cidr';
|
||||
|
||||
export function getIpHash(ip: string) {
|
||||
// because a single person may control many IPv6 addresses,
|
||||
// only a /64 subnet prefix of any IP will be taken into account.
|
||||
// (this means for IPv4 the entire address is used)
|
||||
const prefix = IPCIDR.createAddress(ip).mask(64);
|
||||
return 'ip-' + BigInt('0b' + prefix).toString(36);
|
||||
}
|
@ -305,11 +305,13 @@ export default function() {
|
||||
systemQueue.add('resyncCharts', {
|
||||
}, {
|
||||
repeat: { cron: '0 0 * * *' },
|
||||
removeOnComplete: true,
|
||||
});
|
||||
|
||||
systemQueue.add('cleanCharts', {
|
||||
}, {
|
||||
repeat: { cron: '0 0 * * *' },
|
||||
removeOnComplete: true,
|
||||
});
|
||||
|
||||
systemQueue.add('checkExpiredMutings', {
|
||||
|
@ -6,7 +6,7 @@ import endpoints, { IEndpointMeta } from './endpoints.js';
|
||||
import { ApiError } from './error.js';
|
||||
import { apiLogger } from './logger.js';
|
||||
import { AccessToken } from '@/models/entities/access-token.js';
|
||||
import IPCIDR from 'ip-cidr';
|
||||
import { getIpHash } from '@/misc/get-ip-hash.js';
|
||||
|
||||
const accessDenied = {
|
||||
message: 'Access denied.',
|
||||
@ -33,18 +33,13 @@ export default async (endpoint: string, user: CacheableLocalUser | null | undefi
|
||||
throw new ApiError(accessDenied);
|
||||
}
|
||||
|
||||
if (ep.meta.requireCredential && ep.meta.limit && !isModerator) {
|
||||
if (ep.meta.limit && !isModerator) {
|
||||
// koa will automatically load the `X-Forwarded-For` header if `proxy: true` is configured in the app.
|
||||
let limitActor: string;
|
||||
if (user) {
|
||||
limitActor = user.id;
|
||||
} else {
|
||||
// because a single person may control many IPv6 addresses,
|
||||
// only a /64 subnet prefix of any IP will be taken into account.
|
||||
// (this means for IPv4 the entire address is used)
|
||||
const ip = IPCIDR.createAddress(ctx.ip).mask(64);
|
||||
|
||||
limitActor = 'ip-' + parseInt(ip, 2).toString(36);
|
||||
limitActor = getIpHash(ctx!.ip);
|
||||
}
|
||||
|
||||
const limit = Object.assign({}, ep.meta.limit);
|
||||
|
@ -10,6 +10,7 @@ import { verifyLogin, hash } from '../2fa.js';
|
||||
import { randomBytes } from 'node:crypto';
|
||||
import { IsNull } from 'typeorm';
|
||||
import { limiter } from '../limiter.js';
|
||||
import { getIpHash } from '@/misc/get-ip-hash.js';
|
||||
|
||||
export default async (ctx: Koa.Context) => {
|
||||
ctx.set('Access-Control-Allow-Origin', config.url);
|
||||
@ -27,7 +28,7 @@ export default async (ctx: Koa.Context) => {
|
||||
|
||||
try {
|
||||
// not more than 1 attempt per second and not more than 10 attempts per hour
|
||||
await limiter({ key: 'signin', duration: 60 * 60 * 1000, max: 10, minInterval: 1000 }, ctx.ip);
|
||||
await limiter({ key: 'signin', duration: 60 * 60 * 1000, max: 10, minInterval: 1000 }, getIpHash(ctx.ip));
|
||||
} catch (err) {
|
||||
ctx.status = 429;
|
||||
ctx.body = {
|
||||
|
@ -312,7 +312,8 @@ export default async (user: { id: User['id']; username: User['username']; host:
|
||||
endedPollNotificationQueue.add({
|
||||
noteId: note.id,
|
||||
}, {
|
||||
delay
|
||||
delay,
|
||||
removeOnComplete: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user