Skip to content

Commit

Permalink
Merge branch 'develop' into fix-hide-tabs-for-remote-user
Browse files Browse the repository at this point in the history
  • Loading branch information
kakkokari-gtyih authored Dec 22, 2024
2 parents 801add9 + 3c81926 commit cebaab4
Show file tree
Hide file tree
Showing 19 changed files with 259 additions and 44 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,15 @@
-

### Client
- Enhance: PC画面でチャンネルが複数列で表示されるように
(Cherry-picked from https://github.com/Otaku-Social/maniakey/pull/13)
- Enhance: 照会に失敗した場合、その理由を表示するように
- Fix: 画面サイズが変わった際にナビゲーションバーが自動で折りたたまれない問題を修正
- Fix: サーバー情報メニューに区切り線が不足していたのを修正
- Fix: ノートがログインしているユーザーしか見れない場合にログインダイアログを閉じるとその後の動線がなくなる問題を修正
- Fix: 公開範囲がホームのノートの埋め込みウィジェットが読み込まれない問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/803)
- Fix: 絵文字管理画面で一部の絵文字が表示されない問題を修正
- Fix: リモートユーザーのページでは連合されない項目(クリップ・ページ・Playなど)のタブが表示されないように
(Cherry-picked from https://github.com/okayurisotto/wisteria/commit/2b8bdeea431b1e8fc380e3b2bba5f5f37262fbf7)

Expand Down
59 changes: 59 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10601,6 +10601,65 @@ export interface Locale extends ILocale {
*/
"sent": string;
};
"_remoteLookupErrors": {
"_federationNotAllowed": {
/**
* このサーバーとは通信できません
*/
"title": string;
/**
* このサーバーとの通信が無効化されているか、このサーバーをブロックしている・ブロックされている可能性があります。
* サーバー管理者にお問い合わせください。
*/
"description": string;
};
"_uriInvalid": {
/**
* URIが不正です
*/
"title": string;
/**
* 入力されたURIに問題があります。URIに使用できない文字を入力していないか確認してください。
*/
"description": string;
};
"_requestFailed": {
/**
* リクエストに失敗しました
*/
"title": string;
/**
* このサーバーとの通信に失敗しました。相手サーバーがダウンしている可能性があります。また、不正なURIや存在しないURIを入力していないか確認してください。
*/
"description": string;
};
"_responseInvalid": {
/**
* レスポンスが不正です
*/
"title": string;
/**
* このサーバーと通信することはできましたが、得られたデータが不正なものでした。
*/
"description": string;
};
"_responseInvalidIdHostNotMatch": {
/**
* 入力されたURIのドメインと最終的に得られたURIのドメインとが異なります。第三者のサーバーを介してリモートのコンテンツを照会している場合は、発信元のサーバーで取得できるURIを使用して照会し直してください。
*/
"description": string;
};
"_noSuchObject": {
/**
* 見つかりません
*/
"title": string;
/**
* 要求されたリソースは見つかりませんでした。URIをもう一度お確かめください。
*/
"description": string;
};
};
}
declare const locales: {
[lang: string]: Locale;
Expand Down
19 changes: 19 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2826,3 +2826,22 @@ _selfXssPrevention:
_followRequest:
recieved: "受け取った申請"
sent: "送った申請"

_remoteLookupErrors:
_federationNotAllowed:
title: "このサーバーとは通信できません"
description: "このサーバーとの通信が無効化されているか、このサーバーをブロックしている・ブロックされている可能性があります。\nサーバー管理者にお問い合わせください。"
_uriInvalid:
title: "URIが不正です"
description: "入力されたURIに問題があります。URIに使用できない文字を入力していないか確認してください。"
_requestFailed:
title: "リクエストに失敗しました"
description: "このサーバーとの通信に失敗しました。相手サーバーがダウンしている可能性があります。また、不正なURIや存在しないURIを入力していないか確認してください。"
_responseInvalid:
title: "レスポンスが不正です"
description: "このサーバーと通信することはできましたが、得られたデータが不正なものでした。"
_responseInvalidIdHostNotMatch:
description: "入力されたURIのドメインと最終的に得られたURIのドメインとが異なります。第三者のサーバーを介してリモートのコンテンツを照会している場合は、発信元のサーバーで取得できるURIを使用して照会し直してください。"
_noSuchObject:
title: "見つかりません"
description: "要求されたリソースは見つかりませんでした。URIをもう一度お確かめください。"
25 changes: 13 additions & 12 deletions packages/backend/src/core/activitypub/ApResolverService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { ApDbResolverService } from './ApDbResolverService.js';
import { ApRendererService } from './ApRendererService.js';
import { ApRequestService } from './ApRequestService.js';
import type { IObject, ICollection, IOrderedCollection } from './type.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';

export class Resolver {
private history: Set<string>;
Expand Down Expand Up @@ -66,7 +67,7 @@ export class Resolver {
if (isCollectionOrOrderedCollection(collection)) {
return collection;
} else {
throw new Error(`unrecognized collection type: ${collection.type}`);
throw new IdentifiableError('f100eccf-f347-43fb-9b45-96a0831fb635', `unrecognized collection type: ${collection.type}`);
}
}

Expand All @@ -80,15 +81,15 @@ export class Resolver {
// URLs with fragment parts cannot be resolved correctly because
// the fragment part does not get transmitted over HTTP(S).
// Avoid strange behaviour by not trying to resolve these at all.
throw new Error(`cannot resolve URL with fragment: ${value}`);
throw new IdentifiableError('b94fd5b1-0e3b-4678-9df2-dad4cd515ab2', `cannot resolve URL with fragment: ${value}`);
}

if (this.history.has(value)) {
throw new Error('cannot resolve already resolved one');
throw new IdentifiableError('0dc86cf6-7cd6-4e56-b1e6-5903d62d7ea5', 'cannot resolve already resolved one');
}

if (this.history.size > this.recursionLimit) {
throw new Error(`hit recursion limit: ${this.utilityService.extractDbHost(value)}`);
throw new IdentifiableError('d592da9f-822f-4d91-83d7-4ceefabcf3d2', `hit recursion limit: ${this.utilityService.extractDbHost(value)}`);
}

this.history.add(value);
Expand All @@ -99,7 +100,7 @@ export class Resolver {
}

if (!this.utilityService.isFederationAllowedHost(host)) {
throw new Error('Instance is blocked');
throw new IdentifiableError('09d79f9e-64f1-4316-9cfa-e75c4d091574', 'Instance is blocked');
}

if (this.config.signToActivityPubGet && !this.user) {
Expand All @@ -115,19 +116,19 @@ export class Resolver {
!(object['@context'] as unknown[]).includes('https://www.w3.org/ns/activitystreams') :
object['@context'] !== 'https://www.w3.org/ns/activitystreams'
) {
throw new Error('invalid response');
throw new IdentifiableError('72180409-793c-4973-868e-5a118eb5519b', 'invalid response');
}

// HttpRequestService / ApRequestService have already checked that
// `object.id` or `object.url` matches the URL used to fetch the
// object after redirects; here we double-check that no redirects
// bounced between hosts
if (object.id == null) {
throw new Error('invalid AP object: missing id');
throw new IdentifiableError('ad2dc287-75c1-44c4-839d-3d2e64576675', 'invalid AP object: missing id');
}

if (this.utilityService.punyHost(object.id) !== this.utilityService.punyHost(value)) {
throw new Error(`invalid AP object ${value}: id ${object.id} has different host`);
throw new IdentifiableError('fd93c2fa-69a8-440f-880b-bf178e0ec877', `invalid AP object ${value}: id ${object.id} has different host`);
}

return object;
Expand All @@ -136,7 +137,7 @@ export class Resolver {
@bindThis
private resolveLocal(url: string): Promise<IObject> {
const parsed = this.apDbResolverService.parseUri(url);
if (!parsed.local) throw new Error('resolveLocal: not local');
if (!parsed.local) throw new IdentifiableError('02b40cd0-fa92-4b0c-acc9-fb2ada952ab8', 'resolveLocal: not local');

switch (parsed.type) {
case 'notes':
Expand Down Expand Up @@ -165,7 +166,7 @@ export class Resolver {
case 'follows':
return this.followRequestsRepository.findOneBy({ id: parsed.id })
.then(async followRequest => {
if (followRequest == null) throw new Error('resolveLocal: invalid follow request ID');
if (followRequest == null) throw new IdentifiableError('a9d946e5-d276-47f8-95fb-f04230289bb0', 'resolveLocal: invalid follow request ID');
const [follower, followee] = await Promise.all([
this.usersRepository.findOneBy({
id: followRequest.followerId,
Expand All @@ -177,12 +178,12 @@ export class Resolver {
}),
]);
if (follower == null || followee == null) {
throw new Error('resolveLocal: follower or followee does not exist');
throw new IdentifiableError('06ae3170-1796-4d93-a697-2611ea6d83b6', 'resolveLocal: follower or followee does not exist');
}
return this.apRendererService.addContext(this.apRendererService.renderFollow(follower as MiLocalUser | MiRemoteUser, followee as MiLocalUser | MiRemoteUser, url));
});
default:
throw new Error(`resolveLocal: type ${parsed.type} unhandled`);
throw new IdentifiableError('7a5d2fc0-94bc-4db6-b8b8-1bf24a2e23d0', `resolveLocal: type ${parsed.type} unhandled`);
}
}
}
Expand Down
65 changes: 63 additions & 2 deletions packages/backend/src/server/api/endpoints/ap/show.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js';
import { ApiError } from '../../error.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';

export const meta = {
tags: ['federation'],
Expand All @@ -32,6 +33,31 @@ export const meta = {
},

errors: {
federationNotAllowed: {
message: 'Federation for this host is not allowed.',
code: 'FEDERATION_NOT_ALLOWED',
id: '974b799e-1a29-4889-b706-18d4dd93e266',
},
uriInvalid: {
message: 'URI is invalid.',
code: 'URI_INVALID',
id: '1a5eab56-e47b-48c2-8d5e-217b897d70db',
},
requestFailed: {
message: 'Request failed.',
code: 'REQUEST_FAILED',
id: '81b539cf-4f57-4b29-bc98-032c33c0792e',
},
responseInvalid: {
message: 'Response from remote server is invalid.',
code: 'RESPONSE_INVALID',
id: '70193c39-54f3-4813-82f0-70a680f7495b',
},
responseInvalidIdHostNotMatch: {
message: 'Requested URI and response URI host does not match.',
code: 'RESPONSE_INVALID_ID_HOST_NOT_MATCH',
id: 'a2c9c61a-cb72-43ab-a964-3ca5fddb410a',
},
noSuchObject: {
message: 'No such object.',
code: 'NO_SUCH_OBJECT',
Expand Down Expand Up @@ -110,7 +136,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
*/
@bindThis
private async fetchAny(uri: string, me: MiLocalUser | null | undefined): Promise<SchemaType<typeof meta['res']> | null> {
if (!this.utilityService.isFederationAllowedUri(uri)) return null;
if (!this.utilityService.isFederationAllowedUri(uri)) {
throw new ApiError(meta.errors.federationNotAllowed);
}

let local = await this.mergePack(me, ...await Promise.all([
this.apDbResolverService.getUserFromApId(uri),
Expand All @@ -125,7 +153,40 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-

// リモートから一旦オブジェクトフェッチ
const resolver = this.apResolverService.createResolver();
const object = await resolver.resolve(uri) as any;
const object = await resolver.resolve(uri).catch((err) => {
if (err instanceof IdentifiableError) {
switch (err.id) {
// resolve
case 'b94fd5b1-0e3b-4678-9df2-dad4cd515ab2':
throw new ApiError(meta.errors.uriInvalid);
case '0dc86cf6-7cd6-4e56-b1e6-5903d62d7ea5':
case 'd592da9f-822f-4d91-83d7-4ceefabcf3d2':
throw new ApiError(meta.errors.requestFailed);
case '09d79f9e-64f1-4316-9cfa-e75c4d091574':
throw new ApiError(meta.errors.federationNotAllowed);
case '72180409-793c-4973-868e-5a118eb5519b':
case 'ad2dc287-75c1-44c4-839d-3d2e64576675':
throw new ApiError(meta.errors.responseInvalid);
case 'fd93c2fa-69a8-440f-880b-bf178e0ec877':
throw new ApiError(meta.errors.responseInvalidIdHostNotMatch);

// resolveLocal
case '02b40cd0-fa92-4b0c-acc9-fb2ada952ab8':
throw new ApiError(meta.errors.uriInvalid);
case 'a9d946e5-d276-47f8-95fb-f04230289bb0':
case '06ae3170-1796-4d93-a697-2611ea6d83b6':
throw new ApiError(meta.errors.noSuchObject);
case '7a5d2fc0-94bc-4db6-b8b8-1bf24a2e23d0':
throw new ApiError(meta.errors.responseInvalid);
}
}

throw new ApiError(meta.errors.requestFailed);
});

if (object.id == null) {
throw new ApiError(meta.errors.responseInvalid);
}

// /@user のような正規id以外で取得できるURIが指定されていた場合、ここで初めて正規URIが確定する
// これはDBに存在する可能性があるため再度DB検索
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/server/web/ClientServerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,7 @@ export class ClientServerService {
});

if (note == null) return;
if (note.visibility !== 'public') return;
if (['specified', 'followers'].includes(note.visibility)) return;
if (note.userHost != null) return;

const _note = await this.noteEntityService.pack(note, null, { detail: true });
Expand Down
6 changes: 1 addition & 5 deletions packages/backend/test-federation/test/note.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,7 @@ describe('Note', () => {
rejects(
async () => await bob.client.request('ap/show', { uri: `https://a.test/notes/${note.id}` }),
(err: any) => {
/**
* FIXME: this error is not handled
* @see https://github.com/misskey-dev/misskey/issues/12736
*/
strictEqual(err.code, 'INTERNAL_ERROR');
strictEqual(err.code, 'REQUEST_FAILED');
return true;
},
);
Expand Down
2 changes: 2 additions & 0 deletions packages/frontend/src/components/MkChannelPreview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ const bannerStyle = computed(() => {
position: absolute;
top: 16px;
left: 16px;
max-width: calc(100% - 32px);
padding: 12px 16px;
box-sizing: border-box;
background: rgba(0, 0, 0, 0.7);
color: #fff;
font-size: 1.2em;
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/src/pages/about-misskey.vue
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ const patrons = [
'こまつぶり',
'まゆつな空高',
'asata',
'ruru',
];

const thereIsTreasure = ref($i && !claimedAchievements.includes('foundTreasure'));
Expand Down
Loading

0 comments on commit cebaab4

Please sign in to comment.