diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts index c6bc35030..c4c9503e0 100644 --- a/src/models/repositories/user.ts +++ b/src/models/repositories/user.ts @@ -289,7 +289,7 @@ export class UserRepository extends Repository { //#region Validators public validateLocalUsername = $.str.match(/^\w{1,20}$/); - public validateRemoteUsername = $.str.match(/^\w([\w-]*\w)?$/); + public validateRemoteUsername = $.str.match(/^\w([\w-.]*\w)?$/); public validatePassword = $.str.min(1); public validateName = $.str.min(1).max(50); public validateDescription = $.str.min(1).max(500); diff --git a/src/remote/activitypub/kernel/flag/index.ts b/src/remote/activitypub/kernel/flag/index.ts new file mode 100644 index 000000000..9b3065b11 --- /dev/null +++ b/src/remote/activitypub/kernel/flag/index.ts @@ -0,0 +1,28 @@ +import { IRemoteUser } from '../../../../models/entities/user'; +import config from '../../../../config'; +import { IFlag, getApIds } from '../../type'; +import { AbuseUserReports, Users } from '../../../../models'; +import { In } from 'typeorm'; +import { genId } from '../../../../misc/gen-id'; + +export default async (actor: IRemoteUser, activity: IFlag): Promise => { + // objectは `(User|Note) | (User|Note)[]` だけど、全パターンDBスキーマと対応させられないので + // 対象ユーザーは一番最初のユーザー として あとはコメントとして格納する + const uris = getApIds(activity.object); + + const userIds = uris.filter(uri => uri.startsWith(config.url + '/users/')).map(uri => uri.split('/').pop()); + const users = await Users.find({ + id: In(userIds) + }); + if (users.length < 1) return `skip`; + + await AbuseUserReports.insert({ + id: genId(), + createdAt: new Date(), + userId: users[0].id, + reporterId: actor.id, + comment: `${activity.content}\n${JSON.stringify(uris, null, 2)}` + }); + + return `ok`; +}; diff --git a/src/remote/activitypub/kernel/index.ts b/src/remote/activitypub/kernel/index.ts index 615edff88..abf5a436c 100644 --- a/src/remote/activitypub/kernel/index.ts +++ b/src/remote/activitypub/kernel/index.ts @@ -1,4 +1,4 @@ -import { IObject, isCreate, isDelete, isUpdate, isRead, isFollow, isAccept, isReject, isAdd, isRemove, isAnnounce, isLike, isUndo, isBlock, isCollectionOrOrderedCollection, isCollection } from '../type'; +import { IObject, isCreate, isDelete, isUpdate, isRead, isFollow, isAccept, isReject, isAdd, isRemove, isAnnounce, isLike, isUndo, isBlock, isCollectionOrOrderedCollection, isCollection, isFlag } from '../type'; import { IRemoteUser } from '../../../models/entities/user'; import create from './create'; import performDeleteActivity from './delete'; @@ -13,6 +13,7 @@ import reject from './reject'; import add from './add'; import remove from './remove'; import block from './block'; +import flag from './flag'; import { apLogger } from '../logger'; import Resolver from '../resolver'; import { toArray } from '../../../prelude/array'; @@ -62,6 +63,8 @@ async function performOneActivity(actor: IRemoteUser, activity: IObject): Promis await undo(actor, activity); } else if (isBlock(activity)) { await block(actor, activity); + } else if (isFlag(activity)) { + await flag(actor, activity); } else { apLogger.warn(`unknown activity type: ${(activity as any).type}`); } diff --git a/src/remote/activitypub/type.ts b/src/remote/activitypub/type.ts index 1a1a9d647..d47a0967f 100644 --- a/src/remote/activitypub/type.ts +++ b/src/remote/activitypub/type.ts @@ -120,10 +120,10 @@ interface IQuestionChoice { _misskey_votes?: number; } -export const validActor = ['Person', 'Service', 'Group', 'Organization']; +export const validActor = ['Person', 'Service', 'Group', 'Organization', 'Application']; export interface IPerson extends IObject { - type: 'Person'; + type: 'Person' | 'Service' | 'Organization' | 'Group' | 'Application'; name?: string; preferredUsername?: string; manuallyApprovesFollowers?: boolean; @@ -243,6 +243,10 @@ export interface IBlock extends IActivity { type: 'Block'; } +export interface IFlag extends IActivity { + type: 'Flag'; +} + export const isCreate = (object: IObject): object is ICreate => object.type === 'Create'; export const isDelete = (object: IObject): object is IDelete => object.type === 'Delete'; export const isUpdate = (object: IObject): object is IUpdate => object.type === 'Update'; @@ -256,3 +260,4 @@ export const isRemove = (object: IObject): object is IRemove => object.type === export const isLike = (object: IObject): object is ILike => object.type === 'Like' || object.type === 'EmojiReaction' || object.type === 'EmojiReact'; export const isAnnounce = (object: IObject): object is IAnnounce => object.type === 'Announce'; export const isBlock = (object: IObject): object is IBlock => object.type === 'Block'; +export const isFlag = (object: IObject): object is IFlag => object.type === 'Flag';