Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop

This commit is contained in:
syuilo 2022-06-03 23:08:18 +09:00
commit 71c230b7b7
18 changed files with 85 additions and 167 deletions

View file

@ -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 = '';

View 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);
}

View file

@ -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', {

View file

@ -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);

View file

@ -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 = {

View file

@ -312,7 +312,8 @@ export default async (user: { id: User['id']; username: User['username']; host:
endedPollNotificationQueue.add({
noteId: note.id,
}, {
delay
delay,
removeOnComplete: true,
});
}

View file

@ -42,6 +42,7 @@ import MkSignin from '@/components/signin.vue';
import MkButton from '@/components/ui/button.vue';
import * as os from '@/os';
import { login } from '@/account';
import { appendQuery, query } from '@/scripts/url';
export default defineComponent({
components: {
@ -82,7 +83,9 @@ export default defineComponent({
this.state = 'accepted';
if (this.callback) {
location.href = `${this.callback}?session=${this.session}`;
location.href = appendQuery(this.callback, query({
session: this.session
}));
}
},
deny() {

View file

@ -35,7 +35,7 @@
<script lang="ts" setup>
import { computed, defineExpose, ref } from 'vue';
import * as tinycolor from 'tinycolor2';
import tinycolor from 'tinycolor2';
import FormLink from '@/components/form/link.vue';
import FormSwitch from '@/components/form/switch.vue';
import FormSection from '@/components/form/section.vue';

View file

@ -17,7 +17,7 @@
:key="ids[0]"
class="column"
:column="columns.find(c => c.id === ids[0])"
:is-stacked="false"
:is-stacked="false"
:style="columns.find(c => c.id === ids[0])!.flexible ? { flex: 1, minWidth: '350px' } : { width: columns.find(c => c.id === ids[0])!.width + 'px' }"
@parent-focus="moveFocus(ids[0], $event)"
/>

View file

@ -94,10 +94,10 @@ function onStats(connStats) {
inPolygonPoints = `${viewBoxX - (stats.length - 1)},${viewBoxY} ${inPolylinePoints} ${viewBoxX},${viewBoxY}`;
outPolygonPoints = `${viewBoxX - (stats.length - 1)},${viewBoxY} ${outPolylinePoints} ${viewBoxX},${viewBoxY}`;
inHeadX = inPolylinePoints[inPolylinePoints.length - 1][0];
inHeadY = inPolylinePoints[inPolylinePoints.length - 1][1];
outHeadX = outPolylinePoints[outPolylinePoints.length - 1][0];
outHeadY = outPolylinePoints[outPolylinePoints.length - 1][1];
inHeadX = inPolylinePointsStats[inPolylinePointsStats.length - 1][0];
inHeadY = inPolylinePointsStats[inPolylinePointsStats.length - 1][1];
outHeadX = outPolylinePointsStats[outPolylinePointsStats.length - 1][0];
outHeadY = outPolylinePointsStats[outPolylinePointsStats.length - 1][1];
inRecent = connStats.net.rx;
outRecent = connStats.net.tx;

View file

@ -1,71 +0,0 @@
/**
* webpack configuration
*/
const fs = require('fs');
const webpack = require('webpack');
class WebpackOnBuildPlugin {
constructor(callback) {
this.callback = callback;
}
apply(compiler) {
compiler.hooks.done.tap('WebpackOnBuildPlugin', this.callback);
}
}
const isProduction = process.env.NODE_ENV === 'production';
const locales = require('../../locales');
const meta = require('../../package.json');
module.exports = {
target: 'webworker',
entry: {
['sw-lib']: './src/lib.ts'
},
module: {
rules: [{
test: /\.ts$/,
exclude: /node_modules/,
use: [{
loader: 'ts-loader',
options: {
happyPackMode: true,
transpileOnly: true,
configFile: __dirname + '/tsconfig.json',
}
}]
}]
},
plugins: [
new webpack.ProgressPlugin({}),
new webpack.DefinePlugin({
_VERSION_: JSON.stringify(meta.version),
_LANGS_: JSON.stringify(Object.entries(locales).map(([k, v]) => [k, v._lang_])),
_ENV_: JSON.stringify(process.env.NODE_ENV),
_DEV_: process.env.NODE_ENV !== 'production',
_PERF_PREFIX_: JSON.stringify('Misskey:'),
}),
],
output: {
path: __dirname + '/../../built/_sw_dist_',
filename: `[name].js`,
publicPath: `/`,
pathinfo: false,
},
resolve: {
extensions: [
'.js', '.ts', '.json'
],
alias: {
'@': __dirname + '/src/',
}
},
resolveLoader: {
modules: ['node_modules']
},
devtool: false, //'source-map',
mode: isProduction ? 'production' : 'development'
};