From 608ff73907a142de74aca544fbec823d90ed6dc9 Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Sun, 5 Sep 2021 23:35:48 +0900 Subject: feat: リモートからユーザー削除が飛んできたら削除するように (#7768) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Delete Actor * Update src/remote/activitypub/kernel/delete/actor.ts Co-authored-by: syuilo Co-authored-by: syuilo --- src/remote/activitypub/kernel/delete/actor.ts | 26 ++++++++++++++++++++++++++ src/remote/activitypub/kernel/delete/index.ts | 3 ++- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/remote/activitypub/kernel/delete/actor.ts (limited to 'src') diff --git a/src/remote/activitypub/kernel/delete/actor.ts b/src/remote/activitypub/kernel/delete/actor.ts new file mode 100644 index 0000000000..502f8d5ab5 --- /dev/null +++ b/src/remote/activitypub/kernel/delete/actor.ts @@ -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 { + 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}`; +} diff --git a/src/remote/activitypub/kernel/delete/index.ts b/src/remote/activitypub/kernel/delete/index.ts index 474f3f6d60..86a452de76 100644 --- a/src/remote/activitypub/kernel/delete/index.ts +++ b/src/remote/activitypub/kernel/delete/index.ts @@ -2,6 +2,7 @@ import deleteNote from './note'; import { IRemoteUser } from '@/models/entities/user'; import { IDelete, getApId, isTombstone, IObject, validPost, validActor } from '../../type'; import { toSingle } from '@/prelude/array'; +import { deleteActor } from './actor'; /** * 削除アクティビティを捌きます @@ -41,7 +42,7 @@ export default async (actor: IRemoteUser, activity: IDelete): Promise => if (validPost.includes(formarType)) { return await deleteNote(actor, uri); } else if (validActor.includes(formarType)) { - return `Delete Actor is not implanted`; + return await deleteActor(actor, uri); } else { return `Unknown type ${formarType}`; } -- cgit v1.2.3-freya From 935d6473edf259efa3b9c2c167a80cb960b07ad6 Mon Sep 17 00:00:00 2001 From: tamaina Date: Thu, 9 Sep 2021 20:23:31 +0900 Subject: chore: APIドキュメントの修正 (#7771) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * packedNotificationSchemaを更新 * read:gallery, write:gallery, read:gallery-likes, write:gallery-likesに翻訳を追加 * fix * add header, choice, invitation --- locales/ja-JP.yml | 4 ++++ src/misc/api-permissions.ts | 1 + src/models/repositories/notification.ts | 40 ++++++++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index e22f50668f..b9623ef0d0 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1150,6 +1150,10 @@ _permissions: "write:user-groups": "ユーザーグループを操作する" "read:channels": "チャンネルを見る" "write:channels": "チャンネルを操作する" + "read:gallery": "ギャラリーを見る" + "write:gallery": "ギャラリーを操作する" + "read:gallery-likes": "ギャラリーのいいねを見る" + "write:gallery-likes": "ギャラリーのいいねを操作する" _auth: shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?" diff --git a/src/misc/api-permissions.ts b/src/misc/api-permissions.ts index eb20c3d289..160cdf9fd6 100644 --- a/src/misc/api-permissions.ts +++ b/src/misc/api-permissions.ts @@ -32,3 +32,4 @@ export const kinds = [ 'read:gallery-likes', 'write:gallery-likes', ]; +// IF YOU ADD KINDS(PERMISSIONS), YOU MUST ADD TRANSLATIONS (under _permissions). diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts index 55af96b6d7..ed9de7ef4c 100644 --- a/src/models/repositories/notification.ts +++ b/src/models/repositories/notification.ts @@ -7,6 +7,7 @@ import { Note } from '@/models/entities/note'; import { NoteReaction } from '@/models/entities/note-reaction'; import { User } from '@/models/entities/user'; import { aggregateNoteEmojis, prefetchEmojis } from '@/misc/populate-emojis'; +import { notificationTypes } from '@/types'; export type PackedNotification = SchemaType; @@ -124,19 +125,52 @@ export const packedNotificationSchema = { optional: false as const, nullable: false as const, format: 'date-time', }, + isRead: { + type: 'boolean' as const, + optional: false as const, nullable: false as const, + }, type: { type: 'string' as const, optional: false as const, nullable: false as const, - enum: ['follow', 'followRequestAccepted', 'receiveFollowRequest', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote'], + enum: [...notificationTypes], + }, + user: { + type: 'object' as const, + ref: 'User', + optional: true as const, nullable: true as const, }, userId: { type: 'string' as const, optional: true as const, nullable: true as const, format: 'id', }, - user: { + note: { type: 'object' as const, - ref: 'User', + ref: 'Note', + optional: true as const, nullable: true as const, + }, + reaction: { + type: 'string' as const, + optional: true as const, nullable: true as const, + }, + choice: { + type: 'number' as const, + optional: true as const, nullable: true as const, + }, + invitation: { + type: 'object' as const, + optional: true as const, nullable: true as const, + }, + body: { + type: 'string' as const, + optional: true as const, nullable: true as const, + }, + header: { + 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, }, } -- cgit v1.2.3-freya From 53f3b779bf16abcda4f6e026c51384f3b8fbcc62 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 01:12:23 +0900 Subject: refactor: Expand schema (#7772) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * packedNotificationSchemaを更新 * read:gallery, write:gallery, read:gallery-likes, write:gallery-likesに翻訳を追加 * fix * add header, choice, invitation * test * fix * yatta * remove no longer needed "as PackedUser/PackedNote" * clean up * add simple-schema * fix lint * define items in full Schema * revert https://github.com/misskey-dev/misskey/pull/7772#discussion_r706627736 * user packとnote packの型不整合を修正 --- src/misc/schema.ts | 70 +++++++++++++++++++---- src/misc/simple-schema.ts | 15 +++++ src/models/repositories/blocking.ts | 2 +- src/models/repositories/clip.ts | 2 +- src/models/repositories/drive-file.ts | 4 +- src/models/repositories/drive-folder.ts | 2 +- src/models/repositories/following.ts | 4 +- src/models/repositories/gallery-post.ts | 6 +- src/models/repositories/messaging-message.ts | 8 +-- src/models/repositories/muting.ts | 2 +- src/models/repositories/note-favorite.ts | 2 +- src/models/repositories/note-reaction.ts | 2 +- src/models/repositories/note.ts | 33 +++++++---- src/models/repositories/notification.ts | 4 +- src/models/repositories/page.ts | 2 +- src/models/repositories/user.ts | 34 ++++------- src/server/api/endpoints.ts | 4 +- src/server/api/openapi/schemas.ts | 49 ++-------------- src/server/api/stream/channels/global-timeline.ts | 2 +- src/server/api/stream/channels/home-timeline.ts | 2 +- src/server/api/stream/channels/hybrid-timeline.ts | 5 +- src/server/api/stream/channels/local-timeline.ts | 5 +- src/server/api/stream/index.ts | 4 +- src/services/chart/core.ts | 14 ++--- 24 files changed, 148 insertions(+), 129 deletions(-) create mode 100644 src/misc/simple-schema.ts (limited to 'src') diff --git a/src/misc/schema.ts b/src/misc/schema.ts index e14e6e0dd7..d27c9eff99 100644 --- a/src/misc/schema.ts +++ b/src/misc/schema.ts @@ -1,15 +1,57 @@ -export type Schema = { - type: 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any'; - nullable: boolean; - optional: boolean; +import { SimpleObj, SimpleSchema } from './simple-schema'; +import { packedUserSchema } from '@/models/repositories/user'; +import { packedNoteSchema } from '@/models/repositories/note'; +import { packedUserListSchema } from '@/models/repositories/user-list'; +import { packedAppSchema } from '@/models/repositories/app'; +import { packedMessagingMessageSchema } from '@/models/repositories/messaging-message'; +import { packedNotificationSchema } from '@/models/repositories/notification'; +import { packedDriveFileSchema } from '@/models/repositories/drive-file'; +import { packedDriveFolderSchema } from '@/models/repositories/drive-folder'; +import { packedFollowingSchema } from '@/models/repositories/following'; +import { packedMutingSchema } from '@/models/repositories/muting'; +import { packedBlockingSchema } from '@/models/repositories/blocking'; +import { packedNoteReactionSchema } from '@/models/repositories/note-reaction'; +import { packedHashtagSchema } from '@/models/repositories/hashtag'; +import { packedPageSchema } from '@/models/repositories/page'; +import { packedUserGroupSchema } from '@/models/repositories/user-group'; +import { packedNoteFavoriteSchema } from '@/models/repositories/note-favorite'; +import { packedChannelSchema } from '@/models/repositories/channel'; +import { packedAntennaSchema } from '@/models/repositories/antenna'; +import { packedClipSchema } from '@/models/repositories/clip'; +import { packedFederationInstanceSchema } from '@/models/repositories/federation-instance'; +import { packedQueueCountSchema } from '@/models/repositories/queue'; +import { packedGalleryPostSchema } from '@/models/repositories/gallery-post'; + +export const refs = { + User: packedUserSchema, + UserList: packedUserListSchema, + UserGroup: packedUserGroupSchema, + App: packedAppSchema, + MessagingMessage: packedMessagingMessageSchema, + Note: packedNoteSchema, + NoteReaction: packedNoteReactionSchema, + NoteFavorite: packedNoteFavoriteSchema, + Notification: packedNotificationSchema, + DriveFile: packedDriveFileSchema, + DriveFolder: packedDriveFolderSchema, + Following: packedFollowingSchema, + Muting: packedMutingSchema, + Blocking: packedBlockingSchema, + Hashtag: packedHashtagSchema, + Page: packedPageSchema, + Channel: packedChannelSchema, + QueueCount: packedQueueCountSchema, + Antenna: packedAntennaSchema, + Clip: packedClipSchema, + FederationInstance: packedFederationInstanceSchema, + GalleryPost: packedGalleryPostSchema, +}; + +export interface Schema extends SimpleSchema { items?: Schema; properties?: Obj; - description?: string; - example?: any; - format?: string; - ref?: string; - enum?: string[]; -}; + ref?: keyof typeof refs; +} type NonUndefinedPropertyNames = { [K in keyof T]: T[K]['optional'] extends true ? never : K @@ -22,7 +64,7 @@ type UndefinedPropertyNames = { type OnlyRequired = Pick>; type OnlyOptional = Pick>; -export type Obj = { [key: string]: Schema }; +export interface Obj extends SimpleObj { [key: string]: Schema; } export type ObjType = { [P in keyof OnlyOptional]?: SchemaType } & @@ -48,6 +90,10 @@ export type SchemaType

= p['type'] extends 'string' ? NullOrUndefined : p['type'] extends 'boolean' ? NullOrUndefined : p['type'] extends 'array' ? NullOrUndefined>[]> : - p['type'] extends 'object' ? NullOrUndefined>> : + p['type'] extends 'object' ? ( + p['ref'] extends keyof typeof refs + ? NullOrUndefined> + : NullOrUndefined>> + ) : p['type'] extends 'any' ? NullOrUndefined : any; diff --git a/src/misc/simple-schema.ts b/src/misc/simple-schema.ts new file mode 100644 index 0000000000..abbb348e24 --- /dev/null +++ b/src/misc/simple-schema.ts @@ -0,0 +1,15 @@ +export interface SimpleSchema { + type: 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any'; + nullable: boolean; + optional: boolean; + items?: SimpleSchema; + properties?: SimpleObj; + description?: string; + example?: any; + format?: string; + ref?: string; + enum?: string[]; + default?: boolean | null; +} + +export interface SimpleObj { [key: string]: SimpleSchema; } diff --git a/src/models/repositories/blocking.ts b/src/models/repositories/blocking.ts index dd3a10905c..515b3a6b16 100644 --- a/src/models/repositories/blocking.ts +++ b/src/models/repositories/blocking.ts @@ -56,7 +56,7 @@ export const packedBlockingSchema = { blockee: { type: 'object' as const, optional: false as const, nullable: false as const, - ref: 'User', + ref: 'User' as const, }, } }; diff --git a/src/models/repositories/clip.ts b/src/models/repositories/clip.ts index 49dc3a332e..e3d718bef4 100644 --- a/src/models/repositories/clip.ts +++ b/src/models/repositories/clip.ts @@ -53,7 +53,7 @@ export const packedClipSchema = { }, user: { type: 'object' as const, - ref: 'User', + ref: 'User' as const, optional: false as const, nullable: false as const, }, name: { diff --git a/src/models/repositories/drive-file.ts b/src/models/repositories/drive-file.ts index 42a60ff03c..63bd020cbe 100644 --- a/src/models/repositories/drive-file.ts +++ b/src/models/repositories/drive-file.ts @@ -234,7 +234,7 @@ export const packedDriveFileSchema = { folder: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'DriveFolder' + ref: 'DriveFolder' as const, }, userId: { type: 'string' as const, @@ -245,7 +245,7 @@ export const packedDriveFileSchema = { user: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'User' + ref: 'User' as const, } }, }; diff --git a/src/models/repositories/drive-folder.ts b/src/models/repositories/drive-folder.ts index 4228284f82..bc73018f29 100644 --- a/src/models/repositories/drive-folder.ts +++ b/src/models/repositories/drive-folder.ts @@ -87,7 +87,7 @@ export const packedDriveFolderSchema = { parent: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'DriveFolder' + ref: 'DriveFolder' as const, }, }, }; diff --git a/src/models/repositories/following.ts b/src/models/repositories/following.ts index 3bb120bc4b..24ddd0d676 100644 --- a/src/models/repositories/following.ts +++ b/src/models/repositories/following.ts @@ -110,7 +110,7 @@ export const packedFollowingSchema = { followee: { type: 'object' as const, optional: true as const, nullable: false as const, - ref: 'User', + ref: 'User' as const, }, followerId: { type: 'string' as const, @@ -120,7 +120,7 @@ export const packedFollowingSchema = { follower: { type: 'object' as const, optional: true as const, nullable: false as const, - ref: 'User', + ref: 'User' as const, }, } }; diff --git a/src/models/repositories/gallery-post.ts b/src/models/repositories/gallery-post.ts index 03edb35213..afa22e9edf 100644 --- a/src/models/repositories/gallery-post.ts +++ b/src/models/repositories/gallery-post.ts @@ -1,6 +1,6 @@ import { EntityRepository, Repository } from 'typeorm'; import { GalleryPost } from '@/models/entities/gallery-post'; -import { SchemaType } from '../../misc/schema'; +import { SchemaType } from '@/misc/schema'; import { Users, DriveFiles, GalleryLikes } from '../index'; import { awaitAll } from '@/prelude/await-all'; import { User } from '@/models/entities/user'; @@ -76,7 +76,7 @@ export const packedGalleryPostSchema = { }, user: { type: 'object' as const, - ref: 'User', + ref: 'User' as const, optional: false as const, nullable: false as const, }, fileIds: { @@ -94,7 +94,7 @@ export const packedGalleryPostSchema = { items: { type: 'object' as const, optional: false as const, nullable: false as const, - ref: 'DriveFile' + ref: 'DriveFile' as const, } }, tags: { diff --git a/src/models/repositories/messaging-message.ts b/src/models/repositories/messaging-message.ts index 1a4a8eecc4..f97905af2f 100644 --- a/src/models/repositories/messaging-message.ts +++ b/src/models/repositories/messaging-message.ts @@ -67,7 +67,7 @@ export const packedMessagingMessageSchema = { }, user: { type: 'object' as const, - ref: 'User', + ref: 'User' as const, optional: true as const, nullable: false as const, }, text: { @@ -82,7 +82,7 @@ export const packedMessagingMessageSchema = { file: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'DriveFile', + ref: 'DriveFile' as const, }, recipientId: { type: 'string' as const, @@ -92,7 +92,7 @@ export const packedMessagingMessageSchema = { recipient: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'User' + ref: 'User' as const, }, groupId: { type: 'string' as const, @@ -102,7 +102,7 @@ export const packedMessagingMessageSchema = { group: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'UserGroup' + ref: 'UserGroup' as const, }, isRead: { type: 'boolean' as const, diff --git a/src/models/repositories/muting.ts b/src/models/repositories/muting.ts index e46f4ae448..d957b1792d 100644 --- a/src/models/repositories/muting.ts +++ b/src/models/repositories/muting.ts @@ -56,7 +56,7 @@ export const packedMutingSchema = { mutee: { type: 'object' as const, optional: false as const, nullable: false as const, - ref: 'User', + ref: 'User' as const, }, } }; diff --git a/src/models/repositories/note-favorite.ts b/src/models/repositories/note-favorite.ts index 3248c32ded..47586a9116 100644 --- a/src/models/repositories/note-favorite.ts +++ b/src/models/repositories/note-favorite.ts @@ -45,7 +45,7 @@ export const packedNoteFavoriteSchema = { note: { type: 'object' as const, optional: false as const, nullable: false as const, - ref: 'Note', + ref: 'Note' as const, }, noteId: { type: 'string' as const, diff --git a/src/models/repositories/note-reaction.ts b/src/models/repositories/note-reaction.ts index c349edf182..e73a832109 100644 --- a/src/models/repositories/note-reaction.ts +++ b/src/models/repositories/note-reaction.ts @@ -42,7 +42,7 @@ export const packedNoteReactionSchema = { user: { type: 'object' as const, optional: false as const, nullable: false as const, - ref: 'User', + ref: 'User' as const, }, type: { type: 'string' as const, diff --git a/src/models/repositories/note.ts b/src/models/repositories/note.ts index 9e0f5e55f0..376a09d0c6 100644 --- a/src/models/repositories/note.ts +++ b/src/models/repositories/note.ts @@ -95,7 +95,7 @@ export class NoteRepository extends Repository { hide = true; } else if (meId === packedNote.userId) { hide = false; - } else if (packedNote.reply && (meId === (packedNote.reply as PackedNote).userId)) { + } else if (packedNote.reply && (meId === packedNote.reply.userId)) { // 自分の投稿に対するリプライ hide = false; } else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) { @@ -353,7 +353,7 @@ export const packedNoteSchema = { }, user: { type: 'object' as const, - ref: 'User', + ref: 'User' as const, optional: false as const, nullable: false as const, }, replyId: { @@ -371,12 +371,12 @@ export const packedNoteSchema = { reply: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'Note' + ref: 'Note' as const, }, renote: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'Note' + ref: 'Note' as const, }, viaMobile: { type: 'boolean' as const, @@ -423,7 +423,7 @@ export const packedNoteSchema = { items: { type: 'object' as const, optional: false as const, nullable: false as const, - ref: 'DriveFile' + ref: 'DriveFile' as const, } }, tags: { @@ -447,11 +447,24 @@ export const packedNoteSchema = { channel: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'Channel' + items: { + type: 'object' as const, + optional: false as const, nullable: false as const, + properties: { + id: { + type: 'string' as const, + optional: false as const, nullable: false as const, + }, + name: { + type: 'string' as const, + optional: false as const, nullable: true as const, + }, + }, + }, }, localOnly: { type: 'boolean' as const, - optional: false as const, nullable: true as const, + optional: true as const, nullable: false as const, }, emojis: { type: 'array' as const, @@ -466,7 +479,7 @@ export const packedNoteSchema = { }, url: { type: 'string' as const, - optional: false as const, nullable: false as const, + optional: false as const, nullable: true as const, }, }, }, @@ -485,11 +498,11 @@ export const packedNoteSchema = { }, uri: { type: 'string' as const, - optional: false as const, nullable: true as const, + optional: true as const, nullable: false as const, }, url: { type: 'string' as const, - optional: false as const, nullable: true as const, + optional: true as const, nullable: false as const, }, myReaction: { diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts index ed9de7ef4c..b7f9e3643c 100644 --- a/src/models/repositories/notification.ts +++ b/src/models/repositories/notification.ts @@ -136,7 +136,7 @@ export const packedNotificationSchema = { }, user: { type: 'object' as const, - ref: 'User', + ref: 'User' as const, optional: true as const, nullable: true as const, }, userId: { @@ -146,7 +146,7 @@ export const packedNotificationSchema = { }, note: { type: 'object' as const, - ref: 'Note', + ref: 'Note' as const, optional: true as const, nullable: true as const, }, reaction: { diff --git a/src/models/repositories/page.ts b/src/models/repositories/page.ts index 757aaa5a3f..1a61e2c99c 100644 --- a/src/models/repositories/page.ts +++ b/src/models/repositories/page.ts @@ -137,7 +137,7 @@ export const packedPageSchema = { }, user: { type: 'object' as const, - ref: 'User', + ref: 'User' as const, optional: false as const, nullable: false as const, }, } diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts index d4bb995ce2..39c90cf5ed 100644 --- a/src/models/repositories/user.ts +++ b/src/models/repositories/user.ts @@ -375,12 +375,12 @@ export const packedUserSchema = { }, isAdmin: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, isModerator: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, isBot: { @@ -402,23 +402,11 @@ export const packedUserSchema = { type: 'string' as const, nullable: false as const, optional: false as const }, - host: { - type: 'string' as const, - nullable: true as const, optional: false as const - }, url: { type: 'string' as const, nullable: false as const, optional: false as const, format: 'url' }, - aliases: { - type: 'array' as const, - nullable: false as const, optional: false as const, - items: { - type: 'string' as const, - nullable: false as const, optional: false as const - } - } } } }, @@ -457,7 +445,7 @@ export const packedUserSchema = { }, isSuspended: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, example: false }, description: { @@ -476,7 +464,7 @@ export const packedUserSchema = { }, fields: { type: 'array' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, items: { type: 'object' as const, nullable: false as const, optional: false as const, @@ -520,31 +508,31 @@ export const packedUserSchema = { items: { type: 'object' as const, nullable: false as const, optional: false as const, - ref: 'Note' + ref: 'Note' as const, } }, pinnedPageId: { type: 'string' as const, - nullable: true as const, optional: false as const + nullable: true as const, optional: true as const }, pinnedPage: { type: 'object' as const, - nullable: true as const, optional: false as const, - ref: 'Page' + nullable: true as const, optional: true as const, + ref: 'Page' as const, }, twoFactorEnabled: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, usePasswordLessLogin: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, securityKeys: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, avatarId: { diff --git a/src/server/api/endpoints.ts b/src/server/api/endpoints.ts index 640b14ed6a..6d9d2b0782 100644 --- a/src/server/api/endpoints.ts +++ b/src/server/api/endpoints.ts @@ -3,7 +3,7 @@ import { dirname } from 'path'; import { Context } from 'cafy'; import * as path from 'path'; import * as glob from 'glob'; -import { Schema } from '@/misc/schema'; +import { SimpleSchema } from '@/misc/simple-schema'; //const _filename = fileURLToPath(import.meta.url); const _filename = __filename; @@ -34,7 +34,7 @@ export interface IEndpointMeta { }; }; - res?: Schema; + res?: SimpleSchema; /** * このエンドポイントにリクエストするのにユーザー情報が必須か否か diff --git a/src/server/api/openapi/schemas.ts b/src/server/api/openapi/schemas.ts index 5402dc6f48..12fc207c47 100644 --- a/src/server/api/openapi/schemas.ts +++ b/src/server/api/openapi/schemas.ts @@ -1,26 +1,4 @@ -import { packedUserSchema } from '@/models/repositories/user'; -import { Schema } from '@/misc/schema'; -import { packedNoteSchema } from '@/models/repositories/note'; -import { packedUserListSchema } from '@/models/repositories/user-list'; -import { packedAppSchema } from '@/models/repositories/app'; -import { packedMessagingMessageSchema } from '@/models/repositories/messaging-message'; -import { packedNotificationSchema } from '@/models/repositories/notification'; -import { packedDriveFileSchema } from '@/models/repositories/drive-file'; -import { packedDriveFolderSchema } from '@/models/repositories/drive-folder'; -import { packedFollowingSchema } from '@/models/repositories/following'; -import { packedMutingSchema } from '@/models/repositories/muting'; -import { packedBlockingSchema } from '@/models/repositories/blocking'; -import { packedNoteReactionSchema } from '@/models/repositories/note-reaction'; -import { packedHashtagSchema } from '@/models/repositories/hashtag'; -import { packedPageSchema } from '@/models/repositories/page'; -import { packedUserGroupSchema } from '@/models/repositories/user-group'; -import { packedNoteFavoriteSchema } from '@/models/repositories/note-favorite'; -import { packedChannelSchema } from '@/models/repositories/channel'; -import { packedAntennaSchema } from '@/models/repositories/antenna'; -import { packedClipSchema } from '@/models/repositories/clip'; -import { packedFederationInstanceSchema } from '@/models/repositories/federation-instance'; -import { packedQueueCountSchema } from '@/models/repositories/queue'; -import { packedGalleryPostSchema } from '@/models/repositories/gallery-post'; +import { refs, Schema } from '@/misc/schema'; export function convertSchemaToOpenApiSchema(schema: Schema) { const res: any = schema; @@ -72,26 +50,7 @@ export const schemas = { required: ['error'] }, - User: convertSchemaToOpenApiSchema(packedUserSchema), - UserList: convertSchemaToOpenApiSchema(packedUserListSchema), - UserGroup: convertSchemaToOpenApiSchema(packedUserGroupSchema), - App: convertSchemaToOpenApiSchema(packedAppSchema), - MessagingMessage: convertSchemaToOpenApiSchema(packedMessagingMessageSchema), - Note: convertSchemaToOpenApiSchema(packedNoteSchema), - NoteReaction: convertSchemaToOpenApiSchema(packedNoteReactionSchema), - NoteFavorite: convertSchemaToOpenApiSchema(packedNoteFavoriteSchema), - Notification: convertSchemaToOpenApiSchema(packedNotificationSchema), - DriveFile: convertSchemaToOpenApiSchema(packedDriveFileSchema), - DriveFolder: convertSchemaToOpenApiSchema(packedDriveFolderSchema), - Following: convertSchemaToOpenApiSchema(packedFollowingSchema), - Muting: convertSchemaToOpenApiSchema(packedMutingSchema), - Blocking: convertSchemaToOpenApiSchema(packedBlockingSchema), - Hashtag: convertSchemaToOpenApiSchema(packedHashtagSchema), - Page: convertSchemaToOpenApiSchema(packedPageSchema), - Channel: convertSchemaToOpenApiSchema(packedChannelSchema), - QueueCount: convertSchemaToOpenApiSchema(packedQueueCountSchema), - Antenna: convertSchemaToOpenApiSchema(packedAntennaSchema), - Clip: convertSchemaToOpenApiSchema(packedClipSchema), - FederationInstance: convertSchemaToOpenApiSchema(packedFederationInstanceSchema), - GalleryPost: convertSchemaToOpenApiSchema(packedGalleryPostSchema), + ...Object.fromEntries( + Object.entries(refs).map(([key, schema]) => [key, convertSchemaToOpenApiSchema(schema)]) + ), }; diff --git a/src/server/api/stream/channels/global-timeline.ts b/src/server/api/stream/channels/global-timeline.ts index 2cb138966f..384ed61409 100644 --- a/src/server/api/stream/channels/global-timeline.ts +++ b/src/server/api/stream/channels/global-timeline.ts @@ -43,7 +43,7 @@ export default class extends Channel { // 関係ない返信は除外 if (note.reply) { - const reply = note.reply as PackedNote; + const reply = note.reply; // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; } diff --git a/src/server/api/stream/channels/home-timeline.ts b/src/server/api/stream/channels/home-timeline.ts index c7a9728741..0e21ab552e 100644 --- a/src/server/api/stream/channels/home-timeline.ts +++ b/src/server/api/stream/channels/home-timeline.ts @@ -51,7 +51,7 @@ export default class extends Channel { // 関係ない返信は除外 if (note.reply) { - const reply = note.reply as PackedNote; + const reply = note.reply; // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; } diff --git a/src/server/api/stream/channels/hybrid-timeline.ts b/src/server/api/stream/channels/hybrid-timeline.ts index 5c454764ec..0b28ff616b 100644 --- a/src/server/api/stream/channels/hybrid-timeline.ts +++ b/src/server/api/stream/channels/hybrid-timeline.ts @@ -4,7 +4,6 @@ import Channel from '../channel'; import { fetchMeta } from '@/misc/fetch-meta'; import { Notes } from '@/models/index'; import { PackedNote } from '@/models/repositories/note'; -import { PackedUser } from '@/models/repositories/user'; import { checkWordMute } from '@/misc/check-word-mute'; import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; @@ -31,7 +30,7 @@ export default class extends Channel { if (!( (note.channelId == null && this.user!.id === 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 && (note.user.host == null && note.visibility === 'public')) || (note.channelId != null && this.followingChannels.has(note.channelId)) )) return; @@ -60,7 +59,7 @@ export default class extends Channel { // 関係ない返信は除外 if (note.reply) { - const reply = note.reply as PackedNote; + const reply = note.reply; // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; } diff --git a/src/server/api/stream/channels/local-timeline.ts b/src/server/api/stream/channels/local-timeline.ts index 4bf0d02ed3..20061410c4 100644 --- a/src/server/api/stream/channels/local-timeline.ts +++ b/src/server/api/stream/channels/local-timeline.ts @@ -4,7 +4,6 @@ import Channel from '../channel'; import { fetchMeta } from '@/misc/fetch-meta'; import { Notes } from '@/models/index'; import { PackedNote } from '@/models/repositories/note'; -import { PackedUser } from '@/models/repositories/user'; import { checkWordMute } from '@/misc/check-word-mute'; import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; @@ -26,7 +25,7 @@ export default class extends Channel { @autobind private async onNote(note: PackedNote) { - if ((note.user as PackedUser).host !== null) return; + if (note.user.host !== null) return; if (note.visibility !== 'public') return; if (note.channelId != null && !this.followingChannels.has(note.channelId)) return; @@ -45,7 +44,7 @@ export default class extends Channel { // 関係ない返信は除外 if (note.reply) { - const reply = note.reply as PackedNote; + const reply = note.reply; // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; } diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index 469f28f11c..f83bc9331e 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -165,8 +165,8 @@ export default class Connection { }; add(note); - if (note.reply) add(note.reply as PackedNote); - if (note.renote) add(note.renote as PackedNote); + if (note.reply) add(note.reply); + if (note.renote) add(note.renote); } @autobind diff --git a/src/services/chart/core.ts b/src/services/chart/core.ts index eee7d20efb..c0d3280c2b 100644 --- a/src/services/chart/core.ts +++ b/src/services/chart/core.ts @@ -7,7 +7,7 @@ import * as nestedProperty from 'nested-property'; import autobind from 'autobind-decorator'; import Logger from '../logger'; -import { Schema } from '@/misc/schema'; +import { SimpleSchema } from '@/misc/simple-schema'; import { EntitySchema, getRepository, Repository, LessThan, Between } from 'typeorm'; import { dateUTC, isTimeSame, isTimeBefore, subtractTime, addTime } from '@/prelude/time'; import { getChartInsertLock } from '@/misc/app-lock'; @@ -56,7 +56,7 @@ export default abstract class Chart> { diff: DeepPartial; group: string | null; }[] = []; - public schema: Schema; + public schema: SimpleSchema; protected repository: Repository; protected abstract genNewLog(latest: T): DeepPartial; @@ -69,7 +69,7 @@ export default abstract class Chart> { protected abstract fetchActual(group: string | null): Promise>; @autobind - private static convertSchemaToFlatColumnDefinitions(schema: Schema) { + private static convertSchemaToFlatColumnDefinitions(schema: SimpleSchema) { const columns = {} as any; const flatColumns = (x: Obj, path?: string) => { for (const [k, v] of Object.entries(x)) { @@ -181,7 +181,7 @@ export default abstract class Chart> { } @autobind - public static schemaToEntity(name: string, schema: Schema): EntitySchema { + public static schemaToEntity(name: string, schema: SimpleSchema): EntitySchema { return new EntitySchema({ name: `__chart__${camelToSnake(name)}`, columns: { @@ -211,7 +211,7 @@ export default abstract class Chart> { }); } - constructor(name: string, schema: Schema, grouped = false) { + constructor(name: string, schema: SimpleSchema, grouped = false) { this.name = name; this.schema = schema; const entity = Chart.schemaToEntity(name, schema); @@ -546,8 +546,8 @@ export default abstract class Chart> { } } -export function convertLog(logSchema: Schema): Schema { - const v: Schema = JSON.parse(JSON.stringify(logSchema)); // copy +export function convertLog(logSchema: SimpleSchema): SimpleSchema { + const v: SimpleSchema = JSON.parse(JSON.stringify(logSchema)); // copy if (v.type === 'number') { v.type = 'array'; v.items = { -- cgit v1.2.3-freya From d252514a3992c5257f24d6d82c7cc7d9d2c889a1 Mon Sep 17 00:00:00 2001 From: NoriDev <11006910+noridev@users.noreply.github.com> Date: Fri, 17 Sep 2021 20:00:31 +0900 Subject: popupで設定ページを表示すると、アカウントの削除ページにアクセスすることができない問題を修正 (#7797) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + src/client/pages/settings/other.vue | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/CHANGELOG.md b/CHANGELOG.md index ff0a0e6b60..f1caad4304 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - リモートユーザーのDeleteアクティビティに対応 ### Bugfixes +- popupで設定ページを表示すると、アカウントの削除ページにアクセスすることができない問題を修正 ## 12.90.1 (2021/09/05) diff --git a/src/client/pages/settings/other.vue b/src/client/pages/settings/other.vue index 6857950350..21b5439041 100644 --- a/src/client/pages/settings/other.vue +++ b/src/client/pages/settings/other.vue @@ -26,7 +26,7 @@ BIOS CLI - {{ $ts.closeAccount }} + {{ $ts.closeAccount }} -- cgit v1.2.3-freya From 361069314ffaa61a81b2189c2eec000a3d1d9c35 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 17 Sep 2021 22:39:15 +0900 Subject: Refine UI (#7806) * wip * wip * wip * wip * wip * wip * wip * wip * Update default.vue * wip --- src/client/components/global/avatar.vue | 26 ++++++ src/client/components/ui/folder.vue | 3 +- src/client/components/ui/input.vue | 2 +- src/client/components/ui/textarea.vue | 2 +- src/client/init.ts | 4 +- src/client/pages/emojis.category.vue | 134 ++++++++++++++++++++++++++++++ src/client/pages/emojis.emoji.vue | 92 +++++++++++++++++++++ src/client/pages/emojis.vue | 139 +++----------------------------- src/client/pages/favorites.vue | 3 +- src/client/pages/note.vue | 134 +++++++++++++++--------------- src/client/pages/notifications.vue | 1 + src/client/pages/settings/index.vue | 3 +- src/client/pages/timeline.vue | 128 +++++++++-------------------- src/client/pages/user/index.vue | 93 ++++++--------------- src/client/style.scss | 1 - src/client/themes/_dark.json5 | 2 +- src/client/themes/_light.json5 | 2 +- src/client/ui/_common_/header.vue | 99 ++++++++++++++++++++--- src/client/ui/default.vue | 11 ++- src/client/ui/universal.vue | 8 +- 20 files changed, 509 insertions(+), 378 deletions(-) create mode 100644 src/client/pages/emojis.category.vue create mode 100644 src/client/pages/emojis.emoji.vue (limited to 'src') diff --git a/src/client/components/global/avatar.vue b/src/client/components/global/avatar.vue index eea970ec9a..395ed5d8ce 100644 --- a/src/client/components/global/avatar.vue +++ b/src/client/components/global/avatar.vue @@ -73,6 +73,22 @@ export default defineComponent({ diff --git a/src/client/components/ui/folder.vue b/src/client/components/ui/folder.vue index 1f3593a74a..eecf1d8be1 100644 --- a/src/client/components/ui/folder.vue +++ b/src/client/components/ui/folder.vue @@ -99,7 +99,8 @@ export default defineComponent({ z-index: 10; position: sticky; top: var(--stickyTop, 0px); - background: var(--panel); + padding: var(--x-padding); + background: var(--x-header, var(--panel)); /* TODO panelの半透明バージョンをプログラマティックに作りたい background: var(--X17); -webkit-backdrop-filter: var(--blur, blur(8px)); diff --git a/src/client/components/ui/input.vue b/src/client/components/ui/input.vue index 05ce5d3e15..a916a0b035 100644 --- a/src/client/components/ui/input.vue +++ b/src/client/components/ui/input.vue @@ -245,7 +245,7 @@ export default defineComponent({ font-size: 1em; color: var(--fg); background: var(--panel); - border: solid 1px var(--inputBorder); + border: solid 0.5px var(--inputBorder); border-radius: 6px; outline: none; box-shadow: none; diff --git a/src/client/components/ui/textarea.vue b/src/client/components/ui/textarea.vue index 53a141f011..08ac3182a9 100644 --- a/src/client/components/ui/textarea.vue +++ b/src/client/components/ui/textarea.vue @@ -212,7 +212,7 @@ export default defineComponent({ font-size: 1em; color: var(--fg); background: var(--panel); - border: solid 1px var(--inputBorder); + border: solid 0.5px var(--inputBorder); border-radius: 6px; outline: none; box-shadow: none; diff --git a/src/client/init.ts b/src/client/init.ts index 4d2170e03f..aa9cd817c4 100644 --- a/src/client/init.ts +++ b/src/client/init.ts @@ -15,7 +15,7 @@ if (localStorage.getItem('accounts') != null) { import * as Sentry from '@sentry/browser'; import { Integrations } from '@sentry/tracing'; -import { computed, createApp, watch, markRaw } from 'vue'; +import { computed, createApp, watch, markRaw, version as vueVersion } from 'vue'; import compareVersions from 'compare-versions'; import widgets from '@client/widgets'; @@ -47,6 +47,8 @@ window.onunhandledrejection = null; if (_DEV_) { console.warn('Development mode!!!'); + console.info(`vue ${vueVersion}`); + (window as any).$i = $i; (window as any).$store = defaultStore; diff --git a/src/client/pages/emojis.category.vue b/src/client/pages/emojis.category.vue new file mode 100644 index 0000000000..0c24b06d16 --- /dev/null +++ b/src/client/pages/emojis.category.vue @@ -0,0 +1,134 @@ + + + + + diff --git a/src/client/pages/emojis.emoji.vue b/src/client/pages/emojis.emoji.vue new file mode 100644 index 0000000000..3c9bb4debe --- /dev/null +++ b/src/client/pages/emojis.emoji.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/src/client/pages/emojis.vue b/src/client/pages/emojis.vue index 391aff8297..c1f87047d3 100644 --- a/src/client/pages/emojis.vue +++ b/src/client/pages/emojis.vue @@ -1,151 +1,30 @@ diff --git a/src/client/pages/favorites.vue b/src/client/pages/favorites.vue index a2d61b98d9..f13723c2d1 100644 --- a/src/client/pages/favorites.vue +++ b/src/client/pages/favorites.vue @@ -22,7 +22,8 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.favorites, - icon: 'fas fa-star' + icon: 'fas fa-star', + bg: 'var(--bg)', }, pagination: { endpoint: 'i/favorites', diff --git a/src/client/pages/note.vue b/src/client/pages/note.vue index 7725ca14b4..fe85d7364e 100644 --- a/src/client/pages/note.vue +++ b/src/client/pages/note.vue @@ -1,37 +1,39 @@ @@ -63,12 +65,14 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: computed(() => this.note ? { title: this.$ts.note, + subtitle: new Date(this.note.createdAt).toLocaleString(), avatar: this.note.user, path: `/notes/${this.note.id}`, share: { title: this.$t('noteOf', { user: this.note.user.name }), text: this.note.text, }, + bg: 'var(--bg)', } : null), note: null, clips: null, @@ -149,52 +153,54 @@ export default defineComponent({ .fcuexfpr { background: var(--bg); - > .note { - > .main { - > .load { - min-width: 0; - margin: 0 auto; - border-radius: 999px; + > ._root { + > .note { + > .main { + > .load { + min-width: 0; + margin: 0 auto; + border-radius: 999px; - &.next { - margin-bottom: var(--margin); - } + &.next { + margin-bottom: var(--margin); + } - &.prev { - margin-top: var(--margin); + &.prev { + margin-top: var(--margin); + } } - } - > .note { > .note { - border-radius: var(--radius); - background: var(--panel); + > .note { + border-radius: var(--radius); + background: var(--panel); + } } - } - > .clips { - > .title { - font-weight: bold; - padding: 12px; - } + > .clips { + > .title { + font-weight: bold; + padding: 12px; + } - > .item { - display: block; - padding: 16px; + > .item { + display: block; + padding: 16px; - > .description { - padding: 8px 0; - } + > .description { + padding: 8px 0; + } - > .user { - $height: 32px; - padding-top: 16px; - border-top: solid 0.5px var(--divider); - line-height: $height; + > .user { + $height: 32px; + padding-top: 16px; + border-top: solid 0.5px var(--divider); + line-height: $height; - > .avatar { - width: $height; - height: $height; + > .avatar { + width: $height; + height: $height; + } } } } diff --git a/src/client/pages/notifications.vue b/src/client/pages/notifications.vue index 633718a90b..06f8ad3cba 100644 --- a/src/client/pages/notifications.vue +++ b/src/client/pages/notifications.vue @@ -21,6 +21,7 @@ export default defineComponent({ [symbols.PAGE_INFO]: { title: this.$ts.notifications, icon: 'fas fa-bell', + bg: 'var(--bg)', actions: [{ text: this.$ts.markAllAsRead, icon: 'fas fa-check', diff --git a/src/client/pages/settings/index.vue b/src/client/pages/settings/index.vue index e7e2506020..3fb5f5f1e6 100644 --- a/src/client/pages/settings/index.vue +++ b/src/client/pages/settings/index.vue @@ -86,7 +86,8 @@ export default defineComponent({ setup(props, context) { const indexInfo = { title: i18n.locale.settings, - icon: 'fas fa-cog' + icon: 'fas fa-cog', + bg: 'var(--bg)', }; const INFO = ref(indexInfo); const page = ref(props.initialPage); diff --git a/src/client/pages/timeline.vue b/src/client/pages/timeline.vue index f54549b982..125191223c 100644 --- a/src/client/pages/timeline.vue +++ b/src/client/pages/timeline.vue @@ -1,25 +1,10 @@