From ff67fb337ea74099ba45e705473d46cd1eb65128 Mon Sep 17 00:00:00 2001 From: Ehsan Javadynia <31900907+ehsanjavadynia@users.noreply.github.com> Date: Sat, 30 Jan 2021 05:39:46 +0330 Subject: using set instead of array for search (#7126) * Resolve #6905 * Resolve #6905 * Resolve #6905 --- src/server/api/stream/channels/home-timeline.ts | 4 ++-- src/server/api/stream/channels/hybrid-timeline.ts | 4 ++-- src/server/api/stream/channels/local-timeline.ts | 2 +- src/server/api/stream/channels/main.ts | 4 ++-- src/server/api/stream/index.ts | 12 ++++++------ 5 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/server/api') diff --git a/src/server/api/stream/channels/home-timeline.ts b/src/server/api/stream/channels/home-timeline.ts index 15fe7fa6f0..6cfa6eae7b 100644 --- a/src/server/api/stream/channels/home-timeline.ts +++ b/src/server/api/stream/channels/home-timeline.ts @@ -19,10 +19,10 @@ export default class extends Channel { @autobind private async onNote(note: PackedNote) { if (note.channelId) { - if (!this.followingChannels.includes(note.channelId)) return; + if (!this.followingChannels.has(note.channelId)) return; } else { // その投稿のユーザーをフォローしていなかったら弾く - if ((this.user!.id !== note.userId) && !this.following.includes(note.userId)) return; + if ((this.user!.id !== note.userId) && !this.following.has(note.userId)) return; } if (['followers', 'specified'].includes(note.visibility)) { diff --git a/src/server/api/stream/channels/hybrid-timeline.ts b/src/server/api/stream/channels/hybrid-timeline.ts index 4dc5f01a32..a9e577cacb 100644 --- a/src/server/api/stream/channels/hybrid-timeline.ts +++ b/src/server/api/stream/channels/hybrid-timeline.ts @@ -29,9 +29,9 @@ export default class extends Channel { // フォローしているチャンネルの投稿 の場合だけ if (!( (note.channelId == null && this.user!.id === note.userId) || - (note.channelId == null && this.following.includes(note.userId)) || + (note.channelId == null && this.following.has(note.userId)) || (note.channelId == null && ((note.user as PackedUser).host == null && note.visibility === 'public')) || - (note.channelId != null && this.followingChannels.includes(note.channelId)) + (note.channelId != null && this.followingChannels.has(note.channelId)) )) return; if (['followers', 'specified'].includes(note.visibility)) { diff --git a/src/server/api/stream/channels/local-timeline.ts b/src/server/api/stream/channels/local-timeline.ts index baeae86603..a3a5e491fc 100644 --- a/src/server/api/stream/channels/local-timeline.ts +++ b/src/server/api/stream/channels/local-timeline.ts @@ -27,7 +27,7 @@ export default class extends Channel { private async onNote(note: PackedNote) { if ((note.user as PackedUser).host !== null) return; if (note.visibility !== 'public') return; - if (note.channelId != null && !this.followingChannels.includes(note.channelId)) return; + if (note.channelId != null && !this.followingChannels.has(note.channelId)) return; // リプライなら再pack if (note.replyId != null) { diff --git a/src/server/api/stream/channels/main.ts b/src/server/api/stream/channels/main.ts index 22e664baca..b69c2ec355 100644 --- a/src/server/api/stream/channels/main.ts +++ b/src/server/api/stream/channels/main.ts @@ -16,7 +16,7 @@ export default class extends Channel { switch (type) { case 'notification': { - if (this.muting.includes(body.userId)) return; + if (this.muting.has(body.userId)) return; if (body.note && body.note.isHidden) { body.note = await Notes.pack(body.note.id, this.user, { detail: true @@ -25,7 +25,7 @@ export default class extends Channel { break; } case 'mention': { - if (this.muting.includes(body.userId)) return; + if (this.muting.has(body.userId)) return; if (body.isHidden) { body = await Notes.pack(body.id, this.user, { detail: true diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index 36e08ec05f..5b975d07db 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -19,9 +19,9 @@ import { UserProfile } from '../../../models/entities/user-profile'; export default class Connection { public user?: User; public userProfile?: UserProfile; - public following: User['id'][] = []; - public muting: User['id'][] = []; - public followingChannels: ChannelModel['id'][] = []; + public following: Set = new Set(); + public muting: Set = new Set(); + public followingChannels: Set = new Set(); public token?: AccessToken; private wsConnection: websocket.connection; public subscriber: EventEmitter; @@ -267,7 +267,7 @@ export default class Connection { select: ['followeeId'] }); - this.following = followings.map(x => x.followeeId); + this.following = new Set(followings.map(x => x.followeeId)); } @autobind @@ -279,7 +279,7 @@ export default class Connection { select: ['muteeId'] }); - this.muting = mutings.map(x => x.muteeId); + this.muting = new Set(mutings.map(x => x.muteeId)); } @autobind @@ -291,7 +291,7 @@ export default class Connection { select: ['followeeId'] }); - this.followingChannels = followings.map(x => x.followeeId); + this.followingChannels = new Set(followings.map(x => x.followeeId)); } @autobind -- cgit v1.2.3-freya From 41d7515f853c59627177a2d654415c5515ac3586 Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Sat, 6 Feb 2021 11:44:46 +0900 Subject: discordapp.com → discord.com (#7140) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/client/pages/settings/integration.vue | 2 +- src/server/api/service/discord.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/server/api') diff --git a/src/client/pages/settings/integration.vue b/src/client/pages/settings/integration.vue index 4516f490d9..7ae1f5e014 100644 --- a/src/client/pages/settings/integration.vue +++ b/src/client/pages/settings/integration.vue @@ -9,7 +9,7 @@
Discord
-

{{ $ts.connectedTo }}: @{{ integrations.discord.username }}#{{ integrations.discord.discriminator }}

+

{{ $ts.connectedTo }}: @{{ integrations.discord.username }}#{{ integrations.discord.discriminator }}

{{ $ts.disconnectSerice }} {{ $ts.connectSerice }}
diff --git a/src/server/api/service/discord.ts b/src/server/api/service/discord.ts index a5ad18d99c..007458066d 100644 --- a/src/server/api/service/discord.ts +++ b/src/server/api/service/discord.ts @@ -70,7 +70,7 @@ async function getOAuth2() { return new OAuth2( meta.discordClientId!, meta.discordClientSecret!, - 'https://discordapp.com/', + 'https://discord.com/', 'api/oauth2/authorize', 'api/oauth2/token'); } else { @@ -174,7 +174,7 @@ router.get('/dc/cb', async ctx => { } })); - const { id, username, discriminator } = await getJson('https://discordapp.com/api/users/@me', '*/*', 10 * 1000, { + const { id, username, discriminator } = await getJson('https://discord.com/api/users/@me', '*/*', 10 * 1000, { 'Authorization': `Bearer ${accessToken}`, }); @@ -245,7 +245,7 @@ router.get('/dc/cb', async ctx => { } })); - const { id, username, discriminator } = await getJson('https://discordapp.com/api/users/@me', '*/*', 10 * 1000, { + const { id, username, discriminator } = await getJson('https://discord.com/api/users/@me', '*/*', 10 * 1000, { 'Authorization': `Bearer ${accessToken}`, }); if (!id || !username || !discriminator) { -- cgit v1.2.3-freya From 0e45f10d99589348cc95bd044e9d06bc8dc1a10a Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Sat, 6 Feb 2021 11:46:47 +0900 Subject: Improve captcha (#7138) --- package.json | 2 -- src/@types/recaptcha-promise.d.ts | 16 ----------- src/misc/captcha.ts | 56 +++++++++++++++++++++++++++++++++++++++ src/server/api/private/signup.ts | 24 +++++------------ yarn.lock | 24 ----------------- 5 files changed, 62 insertions(+), 60 deletions(-) delete mode 100644 src/@types/recaptcha-promise.d.ts create mode 100644 src/misc/captcha.ts (limited to 'src/server/api') diff --git a/package.json b/package.json index efc20ae894..35ccc0be58 100644 --- a/package.json +++ b/package.json @@ -152,7 +152,6 @@ "gulp-tslint": "8.1.4", "gulp-typescript": "6.0.0-alpha.1", "hard-source-webpack-plugin": "0.13.1", - "hcaptcha": "0.0.2", "html-minifier": "4.0.0", "http-proxy-agent": "4.0.1", "http-signature": "1.3.5", @@ -208,7 +207,6 @@ "random-seed": "0.3.0", "ratelimiter": "3.4.1", "re2": "1.15.9", - "recaptcha-promise": "1.0.0", "reconnecting-websocket": "4.4.0", "redis": "3.0.2", "redis-lock": "0.1.4", diff --git a/src/@types/recaptcha-promise.d.ts b/src/@types/recaptcha-promise.d.ts deleted file mode 100644 index cfbd5eebf2..0000000000 --- a/src/@types/recaptcha-promise.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -declare module 'recaptcha-promise' { - interface IVerifyOptions { - secret_key?: string; - } - - interface IVerify { - (response: string, remoteAddress?: string): Promise; - init(options: IVerifyOptions): IVerify; - } - - namespace recaptchaPromise {} // Hack - - const verify: IVerify; - - export = verify; -} diff --git a/src/misc/captcha.ts b/src/misc/captcha.ts new file mode 100644 index 0000000000..87ec143ca8 --- /dev/null +++ b/src/misc/captcha.ts @@ -0,0 +1,56 @@ +import fetch from 'node-fetch'; +import { URLSearchParams } from 'url'; +import { getAgentByUrl } from './fetch'; +import config from '../config'; + +export async function verifyRecaptcha(secret: string, response: string) { + const result = await getCaptchaResponse('https://www.recaptcha.net/recaptcha/api/siteverify', secret, response).catch(e => { + throw `recaptcha-request-failed: ${e}`; + }); + + if (result.success !== true) { + const errorCodes = result['error-codes'] ? result['error-codes']?.join(', ') : ''; + throw `recaptcha-failed: ${errorCodes}`; + } +} + +export async function verifyHcaptcha(secret: string, response: string) { + const result = await getCaptchaResponse('https://hcaptcha.com/siteverify', secret, response).catch(e => { + throw `hcaptcha-request-failed: ${e}`; + }); + + if (result.success !== true) { + const errorCodes = result['error-codes'] ? result['error-codes']?.join(', ') : ''; + throw `hcaptcha-failed: ${errorCodes}`; + } +} + +type CaptchaResponse = { + success: boolean; + 'error-codes'?: string[]; +}; + +async function getCaptchaResponse(url: string, secret: string, response: string): Promise { + const params = new URLSearchParams({ + secret, + response + }); + + const res = await fetch(url, { + method: 'POST', + body: params, + headers: { + 'User-Agent': config.userAgent + }, + timeout: 10 * 1000, + agent: getAgentByUrl + }).catch(e => { + throw `${e.message || e}`; + }); + + if (!res.ok) { + throw `${res.status}`; + } + + return await res.json() as CaptchaResponse; +} diff --git a/src/server/api/private/signup.ts b/src/server/api/private/signup.ts index 6dc252ac45..3d467a0e68 100644 --- a/src/server/api/private/signup.ts +++ b/src/server/api/private/signup.ts @@ -1,7 +1,6 @@ import * as Koa from 'koa'; import { fetchMeta } from '../../../misc/fetch-meta'; -import { verify } from 'hcaptcha'; -import * as recaptcha from 'recaptcha-promise'; +import { verifyHcaptcha, verifyRecaptcha } from '../../../misc/captcha'; import { Users, RegistrationTickets } from '../../../models'; import { signup } from '../common/signup'; @@ -14,26 +13,15 @@ export default async (ctx: Koa.Context) => { // ただしテスト時はこの機構は障害となるため無効にする if (process.env.NODE_ENV !== 'test') { if (instance.enableHcaptcha && instance.hcaptchaSecretKey) { - const success = await verify(instance.hcaptchaSecretKey, body['hcaptcha-response']).then( - ({ success }) => success, - () => false, - ); - - if (!success) { - ctx.throw(400, 'hcaptcha-failed'); - } + await verifyHcaptcha(instance.hcaptchaSecretKey, body['hcaptcha-response']).catch(e => { + ctx.throw(400, e); + }); } if (instance.enableRecaptcha && instance.recaptchaSecretKey) { - recaptcha.init({ - secret_key: instance.recaptchaSecretKey + await verifyRecaptcha(instance.recaptchaSecretKey, body['g-recaptcha-response']).catch(e => { + ctx.throw(400, e); }); - - const success = await recaptcha(body['g-recaptcha-response']); - - if (!success) { - ctx.throw(400, 'recaptcha-failed'); - } } } diff --git a/yarn.lock b/yarn.lock index c34ee573a6..8c12fcc034 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1773,13 +1773,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== -axios@^0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.20.0.tgz#057ba30f04884694993a8cd07fa394cff11c50bd" - integrity sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA== - dependencies: - follow-redirects "^1.10.0" - bach@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880" @@ -4275,11 +4268,6 @@ flush-write-stream@^1.0.2: inherits "^2.0.3" readable-stream "^2.3.6" -follow-redirects@^1.10.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" - integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== - for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -4825,11 +4813,6 @@ hash-sum@^2.0.0: resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-2.0.0.tgz#81d01bb5de8ea4a214ad5d6ead1b523460b0b45a" integrity sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg== -hcaptcha@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/hcaptcha/-/hcaptcha-0.0.2.tgz#18f4c055a2315db9f732ac77f9d0e30026bb2eb7" - integrity sha512-wWOncj/sY+q8s7tV12tjn3cFNoQhSu3l/7nTJi4QkFKALQi9XnduoXrV/KFzLg5lnB+5560zSAoi9YdYPDw6Eg== - he@1.2.0, he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -8701,13 +8684,6 @@ readdirp@~3.3.0: dependencies: picomatch "^2.0.7" -recaptcha-promise@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/recaptcha-promise/-/recaptcha-promise-1.0.0.tgz#df16f208197fbfd571950cfb32ec3160e3909e0f" - integrity sha512-aiJNjKa13YqjF0QmiBUSFpUHjgjJAkRGBndbhHUrwyaxpGdzTxnsLlVEKZvh0gj75AJ/H8H6Bn9qCs8fVc3X1g== - dependencies: - axios "^0.20.0" - rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" -- cgit v1.2.3-freya From c88902e640e6ac7f7c9ea4b66f8a6005273636ab Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Sat, 6 Feb 2021 11:48:57 +0900 Subject: s3ForcePathStyle (#7122) Co-authored-by: ybw2016v --- migration/1611547387175-objectStorageS3ForcePathStyle.ts | 14 ++++++++++++++ src/client/pages/instance/settings.vue | 4 ++++ src/models/entities/meta.ts | 5 +++++ src/server/api/endpoints/admin/update-meta.ts | 10 +++++++++- src/server/api/endpoints/meta.ts | 1 + src/services/drive/s3.ts | 4 +++- 6 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 migration/1611547387175-objectStorageS3ForcePathStyle.ts (limited to 'src/server/api') diff --git a/migration/1611547387175-objectStorageS3ForcePathStyle.ts b/migration/1611547387175-objectStorageS3ForcePathStyle.ts new file mode 100644 index 0000000000..1506a29007 --- /dev/null +++ b/migration/1611547387175-objectStorageS3ForcePathStyle.ts @@ -0,0 +1,14 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class objectStorageS3ForcePathStyle1611547387175 implements MigrationInterface { + name = 'objectStorageS3ForcePathStyle1611547387175' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "meta" ADD "objectStorageS3ForcePathStyle" boolean NOT NULL DEFAULT true`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "objectStorageS3ForcePathStyle"`); + } + +} diff --git a/src/client/pages/instance/settings.vue b/src/client/pages/instance/settings.vue index 761044b011..cea621ba2d 100644 --- a/src/client/pages/instance/settings.vue +++ b/src/client/pages/instance/settings.vue @@ -175,6 +175,7 @@ {{ $ts.objectStorageUseSSL }} {{ $ts.objectStorageUseProxy }} {{ $ts.objectStorageSetPublicRead }} + s3ForcePathStyle