Merge branch 'chore-api-R30906' into stream-types

This commit is contained in:
tamaina 2021-09-06 01:38:04 +09:00
commit e9b9afbd2a
9 changed files with 130 additions and 8 deletions

View File

@ -7,6 +7,19 @@
--> -->
## 12.x.x (unreleased)
### Improvements
- リモートユーザーのDeleteアクティビティに対応
### Bugfixes
## 12.90.1 (2021/09/05)
### Bugfixes
- Dockerfileを修正
- ノート翻訳時に公開範囲が考慮されていない問題を修正
## 12.90.0 (2021/09/04) ## 12.90.0 (2021/09/04)
### Improvements ### Improvements

View File

@ -1150,6 +1150,10 @@ _permissions:
"write:user-groups": "ユーザーグループを操作する" "write:user-groups": "ユーザーグループを操作する"
"read:channels": "チャンネルを見る" "read:channels": "チャンネルを見る"
"write:channels": "チャンネルを操作する" "write:channels": "チャンネルを操作する"
"read:gallery": "ギャラリーを見る"
"write:gallery": "ギャラリーを操作する"
"read:gallery-likes": "ギャラリーのいいねを見る"
"write:gallery-likes": "ギャラリーのいいねを操作する"
_auth: _auth:
shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?" shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?"

View File

@ -1,7 +1,7 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <syuilotan@yahoo.co.jp>", "author": "syuilo <syuilotan@yahoo.co.jp>",
"version": "12.90.0", "version": "12.90.1",
"codename": "indigo", "codename": "indigo",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -32,3 +32,4 @@ export const kinds = [
'read:gallery-likes', 'read:gallery-likes',
'write:gallery-likes', 'write:gallery-likes',
]; ];
// IF YOU ADD KINDS(PERMISSIONS), YOU MUST ADD TRANSLATIONS (under _permissions).

View File

@ -18,7 +18,57 @@ export class NoteRepository extends Repository<Note> {
return x.trim().length <= 100; return x.trim().length <= 100;
} }
public async isVisibleForMe(note: Note, meId: User['id'] | null): Promise<boolean> {
// visibility が specified かつ自分が指定されていなかったら非表示
if (note.visibility === 'specified') {
if (meId == null) {
return false;
} else if (meId === note.userId) {
return true;
} else {
// 指定されているかどうか
const specified = note.visibleUserIds.some((id: any) => meId === id);
if (specified) {
return true;
} else {
return false;
}
}
}
// visibility が followers かつ自分が投稿者のフォロワーでなかったら非表示
if (note.visibility === 'followers') {
if (meId == null) {
return false;
} else if (meId === note.userId) {
return true;
} else if (note.reply && (meId === note.reply.userId)) {
// 自分の投稿に対するリプライ
return true;
} else if (note.mentions && note.mentions.some(id => meId === id)) {
// 自分へのメンション
return true;
} else {
// フォロワーかどうか
const following = await Followings.findOne({
followeeId: note.userId,
followerId: meId
});
if (following == null) {
return false;
} else {
return true;
}
}
}
return true;
}
private async hideNote(packedNote: PackedNote, meId: User['id'] | null) { private async hideNote(packedNote: PackedNote, meId: User['id'] | null) {
// TODO: isVisibleForMe を使うようにしても良さそう(型違うけど)
let hide = false; let hide = false;
// visibility が specified かつ自分が指定されていなかったら非表示 // visibility が specified かつ自分が指定されていなかったら非表示

View File

@ -7,6 +7,7 @@ import { Note } from '@/models/entities/note';
import { NoteReaction } from '@/models/entities/note-reaction'; import { NoteReaction } from '@/models/entities/note-reaction';
import { User } from '@/models/entities/user'; import { User } from '@/models/entities/user';
import { aggregateNoteEmojis, prefetchEmojis } from '@/misc/populate-emojis'; import { aggregateNoteEmojis, prefetchEmojis } from '@/misc/populate-emojis';
import { notificationTypes } from '@/types';
export type PackedNotification = SchemaType<typeof packedNotificationSchema>; export type PackedNotification = SchemaType<typeof packedNotificationSchema>;
@ -124,20 +125,41 @@ export const packedNotificationSchema = {
optional: false as const, nullable: false as const, optional: false as const, nullable: false as const,
format: 'date-time', format: 'date-time',
}, },
isRead: {
type: 'boolean' as const,
optional: false as const, nullable: false as const,
},
type: { type: {
type: 'string' as const, type: 'string' as const,
optional: false as const, nullable: false as const, optional: false as const, nullable: false as const,
enum: ['follow', 'followRequestAccepted', 'receiveFollowRequest', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote'], enum: [...notificationTypes],
},
userId: {
type: 'string' as const,
optional: true as const, nullable: true as const,
format: 'id',
}, },
user: { user: {
type: 'object' as const, type: 'object' as const,
ref: 'User', ref: 'User',
optional: true as const, nullable: true as const, optional: true as const, nullable: true as const,
}, },
userId: {
type: 'string' as const,
optional: true as const, nullable: true as const,
format: 'id',
},
note: {
type: 'object' as const,
ref: 'Note',
optional: true as const, nullable: true as const,
},
reaction: {
type: 'string' as const,
optional: true as const, nullable: true as const,
},
body: {
type: 'string' as const,
optional: true as const, nullable: true as const,
},
icon: {
type: 'string' as const,
optional: true as const, nullable: true as const,
},
} }
}; };

View File

@ -0,0 +1,26 @@
import { apLogger } from '../../logger';
import { createDeleteAccountJob } from '@/queue';
import { IRemoteUser } from '@/models/entities/user';
import { Users } from '@/models/index';
const logger = apLogger;
export async function deleteActor(actor: IRemoteUser, uri: string): Promise<string> {
logger.info(`Deleting the Actor: ${uri}`);
if (actor.uri !== uri) {
return `skip: delete actor ${actor.uri} !== ${uri}`;
}
if (actor.isDeleted) {
logger.info(`skip: already deleted`);
}
const job = await createDeleteAccountJob(actor);
await Users.update(actor.id, {
isDeleted: true,
});
return `ok: queued ${job.name} ${job.id}`;
}

View File

@ -2,6 +2,7 @@ import deleteNote from './note';
import { IRemoteUser } from '@/models/entities/user'; import { IRemoteUser } from '@/models/entities/user';
import { IDelete, getApId, isTombstone, IObject, validPost, validActor } from '../../type'; import { IDelete, getApId, isTombstone, IObject, validPost, validActor } from '../../type';
import { toSingle } from '@/prelude/array'; import { toSingle } from '@/prelude/array';
import { deleteActor } from './actor';
/** /**
* *
@ -41,7 +42,7 @@ export default async (actor: IRemoteUser, activity: IDelete): Promise<string> =>
if (validPost.includes(formarType)) { if (validPost.includes(formarType)) {
return await deleteNote(actor, uri); return await deleteNote(actor, uri);
} else if (validActor.includes(formarType)) { } else if (validActor.includes(formarType)) {
return `Delete Actor is not implanted`; return await deleteActor(actor, uri);
} else { } else {
return `Unknown type ${formarType}`; return `Unknown type ${formarType}`;
} }

View File

@ -8,6 +8,7 @@ import config from '@/config/index';
import { getAgentByUrl } from '@/misc/fetch'; import { getAgentByUrl } from '@/misc/fetch';
import { URLSearchParams } from 'url'; import { URLSearchParams } from 'url';
import { fetchMeta } from '@/misc/fetch-meta'; import { fetchMeta } from '@/misc/fetch-meta';
import { Notes } from '@/models';
export const meta = { export const meta = {
tags: ['notes'], tags: ['notes'],
@ -43,6 +44,10 @@ export default define(meta, async (ps, user) => {
throw e; throw e;
}); });
if (!(await Notes.isVisibleForMe(note, user ? user.id : null))) {
return 204; // TODO: 良い感じのエラー返す
}
if (note.text == null) { if (note.text == null) {
return 204; return 204;
} }