From 605f1492350c6f90108018d895e47fbc37197c4a Mon Sep 17 00:00:00 2001 From: Ebise Lutica <7106976+EbiseLutica@users.noreply.github.com> Date: Thu, 13 Apr 2023 13:17:32 +0900 Subject: feat: 自分用メモ機能 (#10516) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 自分用メモを作成する機能 * 不要なCSSを削除 * メモ: デザイン調整 * デザイン崩れを修正 * fix: メモ機能のe2eテストで見つかった不具合を修正 * デザイン調整 * fix(frontend): 自分用メモtextareaにline-heightが適用されない問題を修正 --- .../src/server/api/endpoints/users/update-memo.ts | 85 ++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 packages/backend/src/server/api/endpoints/users/update-memo.ts (limited to 'packages/backend/src/server/api/endpoints') diff --git a/packages/backend/src/server/api/endpoints/users/update-memo.ts b/packages/backend/src/server/api/endpoints/users/update-memo.ts new file mode 100644 index 0000000000..300435b9ff --- /dev/null +++ b/packages/backend/src/server/api/endpoints/users/update-memo.ts @@ -0,0 +1,85 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { IdService } from '@/core/IdService.js'; +import type { UserMemoRepository } from '@/models/index.js'; +import { DI } from '@/di-symbols.js'; +import { GetterService } from '@/server/api/GetterService.js'; +import { ApiError } from '../../error.js'; + +export const meta = { + tags: ['account'], + + requireCredential: true, + + kind: 'write:account', + + errors: { + noSuchUser: { + message: 'No such user.', + code: 'NO_SUCH_USER', + id: '6fef56f3-e765-4957-88e5-c6f65329b8a5', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + memo: { + type: 'string', + nullable: true, + description: 'A personal memo for the target user. If null or empty, delete the memo.', + }, + }, + required: ['userId', 'memo'], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + @Inject(DI.userMemoRepository) + private userMemoRepository: UserMemoRepository, + private getterService: GetterService, + private idService: IdService, + ) { + super(meta, paramDef, async (ps, me) => { + // Get target + const target = await this.getterService.getUser(ps.userId).catch(err => { + if (err.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + throw err; + }); + + // 引数がnullか空文字であれば、パーソナルメモを削除する + if (ps.memo === '' || ps.memo == null) { + await this.userMemoRepository.delete({ + userId: me.id, + targetUserId: target.id, + }); + return; + } + + // 以前に作成されたパーソナルメモがあるかどうか確認 + const previousMemo = await this.userMemoRepository.findOneBy({ + userId: me.id, + targetUserId: target.id, + }); + + if (!previousMemo) { + await this.userMemoRepository.insert({ + id: this.idService.genId(), + userId: me.id, + targetUserId: target.id, + memo: ps.memo, + }); + } else { + await this.userMemoRepository.update(previousMemo.id, { + userId: me.id, + targetUserId: target.id, + memo: ps.memo, + }); + } + }); + } +} -- cgit v1.2.3-freya From 97abfd48ceaebaa0f8e5ee60fcc0a656a3eb13c7 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 13 Apr 2023 13:31:54 +0900 Subject: refactor(backend): tweak repository name --- packages/backend/src/core/entities/UserEntityService.ts | 6 +++--- packages/backend/src/di-symbols.ts | 2 +- packages/backend/src/models/RepositoryModule.ts | 8 ++++---- .../backend/src/server/api/endpoints/users/update-memo.ts | 12 ++++++------ 4 files changed, 14 insertions(+), 14 deletions(-) (limited to 'packages/backend/src/server/api/endpoints') diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index 3f8254bb6c..68d30fe174 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -114,8 +114,8 @@ export class UserEntityService implements OnModuleInit { @Inject(DI.pagesRepository) private pagesRepository: PagesRepository, - @Inject(DI.userMemoRepository) - private userMemoRepository: UserMemoRepository, + @Inject(DI.userMemosRepository) + private userMemosRepository: UserMemoRepository, //private noteEntityService: NoteEntityService, //private driveFileEntityService: DriveFileEntityService, @@ -340,7 +340,7 @@ export class UserEntityService implements OnModuleInit { const falsy = opts.detail ? false : undefined; - const memo = meId == null ? null : await this.userMemoRepository.findOneBy({ + const memo = meId == null ? null : await this.userMemosRepository.findOneBy({ userId: meId, targetUserId: user.id, }).then(row => row?.memo ?? null); diff --git a/packages/backend/src/di-symbols.ts b/packages/backend/src/di-symbols.ts index b93ba899fb..190d8d65c2 100644 --- a/packages/backend/src/di-symbols.ts +++ b/packages/backend/src/di-symbols.ts @@ -70,6 +70,6 @@ export const DI = { roleAssignmentsRepository: Symbol('roleAssignmentsRepository'), flashsRepository: Symbol('flashsRepository'), flashLikesRepository: Symbol('flashLikesRepository'), - userMemoRepository: Symbol('userMemoRepository'), + userMemosRepository: Symbol('userMemosRepository'), //#endregion }; diff --git a/packages/backend/src/models/RepositoryModule.ts b/packages/backend/src/models/RepositoryModule.ts index a415e37904..588c98b58d 100644 --- a/packages/backend/src/models/RepositoryModule.ts +++ b/packages/backend/src/models/RepositoryModule.ts @@ -388,8 +388,8 @@ const $roleAssignmentsRepository: Provider = { inject: [DI.db], }; -const $userMemoRepository: Provider = { - provide: DI.userMemoRepository, +const $userMemosRepository: Provider = { + provide: DI.userMemosRepository, useFactory: (db: DataSource) => db.getRepository(UserMemo), inject: [DI.db], }; @@ -462,7 +462,7 @@ const $userMemoRepository: Provider = { $roleAssignmentsRepository, $flashsRepository, $flashLikesRepository, - $userMemoRepository, + $userMemosRepository, ], exports: [ $usersRepository, @@ -529,7 +529,7 @@ const $userMemoRepository: Provider = { $roleAssignmentsRepository, $flashsRepository, $flashLikesRepository, - $userMemoRepository, + $userMemosRepository, ], }) export class RepositoryModule {} diff --git a/packages/backend/src/server/api/endpoints/users/update-memo.ts b/packages/backend/src/server/api/endpoints/users/update-memo.ts index 300435b9ff..ca7756ef75 100644 --- a/packages/backend/src/server/api/endpoints/users/update-memo.ts +++ b/packages/backend/src/server/api/endpoints/users/update-memo.ts @@ -39,8 +39,8 @@ export const paramDef = { @Injectable() export default class extends Endpoint { constructor( - @Inject(DI.userMemoRepository) - private userMemoRepository: UserMemoRepository, + @Inject(DI.userMemosRepository) + private userMemosRepository: UserMemoRepository, private getterService: GetterService, private idService: IdService, ) { @@ -53,7 +53,7 @@ export default class extends Endpoint { // 引数がnullか空文字であれば、パーソナルメモを削除する if (ps.memo === '' || ps.memo == null) { - await this.userMemoRepository.delete({ + await this.userMemosRepository.delete({ userId: me.id, targetUserId: target.id, }); @@ -61,20 +61,20 @@ export default class extends Endpoint { } // 以前に作成されたパーソナルメモがあるかどうか確認 - const previousMemo = await this.userMemoRepository.findOneBy({ + const previousMemo = await this.userMemosRepository.findOneBy({ userId: me.id, targetUserId: target.id, }); if (!previousMemo) { - await this.userMemoRepository.insert({ + await this.userMemosRepository.insert({ id: this.idService.genId(), userId: me.id, targetUserId: target.id, memo: ps.memo, }); } else { - await this.userMemoRepository.update(previousMemo.id, { + await this.userMemosRepository.update(previousMemo.id, { userId: me.id, targetUserId: target.id, memo: ps.memo, -- cgit v1.2.3-freya From a67439981b009410160b2d428aa83b5411241907 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 14 Apr 2023 13:50:05 +0900 Subject: fix types --- packages/backend/check_connect.js | 2 +- packages/backend/src/GlobalModule.ts | 8 ++++---- packages/backend/src/core/AntennaService.ts | 2 +- packages/backend/src/core/AppLockService.ts | 2 +- packages/backend/src/core/CacheService.ts | 2 +- packages/backend/src/core/CustomEmojiService.ts | 2 +- packages/backend/src/core/FederatedInstanceService.ts | 2 +- packages/backend/src/core/GlobalEventService.ts | 2 +- packages/backend/src/core/MetaService.ts | 2 +- packages/backend/src/core/NoteCreateService.ts | 2 +- packages/backend/src/core/NotificationService.ts | 4 ++-- packages/backend/src/core/PushNotificationService.ts | 2 +- packages/backend/src/core/RoleService.ts | 2 +- packages/backend/src/core/UserKeypairService.ts | 2 +- packages/backend/src/core/WebhookService.ts | 2 +- packages/backend/src/core/entities/UserEntityService.ts | 2 +- packages/backend/src/misc/cache.ts | 6 +++--- packages/backend/src/server/api/RateLimiterService.ts | 2 +- packages/backend/src/server/api/StreamingApiServerService.ts | 2 +- packages/backend/src/server/api/endpoints/admin/server-info.ts | 2 +- packages/backend/src/server/api/endpoints/antennas/notes.ts | 2 +- packages/backend/src/server/api/endpoints/channels/timeline.ts | 2 +- packages/backend/src/server/api/endpoints/i/notifications.ts | 2 +- packages/backend/src/server/api/endpoints/reset-db.ts | 2 +- packages/backend/src/server/api/endpoints/roles/notes.ts | 2 +- 25 files changed, 31 insertions(+), 31 deletions(-) (limited to 'packages/backend/src/server/api/endpoints') diff --git a/packages/backend/check_connect.js b/packages/backend/check_connect.js index ef0a350fbf..ce31bd8fb6 100644 --- a/packages/backend/check_connect.js +++ b/packages/backend/check_connect.js @@ -1,4 +1,4 @@ -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { loadConfig } from './built/config.js'; const config = loadConfig(); diff --git a/packages/backend/src/GlobalModule.ts b/packages/backend/src/GlobalModule.ts index 174d0d8beb..4574429c43 100644 --- a/packages/backend/src/GlobalModule.ts +++ b/packages/backend/src/GlobalModule.ts @@ -1,6 +1,6 @@ import { setTimeout } from 'node:timers/promises'; import { Global, Inject, Module } from '@nestjs/common'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { DataSource } from 'typeorm'; import { DI } from './di-symbols.js'; import { loadConfig } from './config.js'; @@ -25,7 +25,7 @@ const $db: Provider = { const $redis: Provider = { provide: DI.redis, useFactory: (config) => { - return new Redis({ + return new Redis.Redis({ port: config.redis.port, host: config.redis.host, family: config.redis.family == null ? 0 : config.redis.family, @@ -40,7 +40,7 @@ const $redis: Provider = { const $redisForPub: Provider = { provide: DI.redisForPub, useFactory: (config) => { - const redis = new Redis({ + const redis = new Redis.Redis({ port: config.redisForPubsub.port, host: config.redisForPubsub.host, family: config.redisForPubsub.family == null ? 0 : config.redisForPubsub.family, @@ -56,7 +56,7 @@ const $redisForPub: Provider = { const $redisForSub: Provider = { provide: DI.redisForSub, useFactory: (config) => { - const redis = new Redis({ + const redis = new Redis.Redis({ port: config.redisForPubsub.port, host: config.redisForPubsub.host, family: config.redisForPubsub.family == null ? 0 : config.redisForPubsub.family, diff --git a/packages/backend/src/core/AntennaService.ts b/packages/backend/src/core/AntennaService.ts index 166c78f479..2d4226a32d 100644 --- a/packages/backend/src/core/AntennaService.ts +++ b/packages/backend/src/core/AntennaService.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import type { Antenna } from '@/models/entities/Antenna.js'; import type { Note } from '@/models/entities/Note.js'; import type { User } from '@/models/entities/User.js'; diff --git a/packages/backend/src/core/AppLockService.ts b/packages/backend/src/core/AppLockService.ts index ee179b7f01..8dd805552b 100644 --- a/packages/backend/src/core/AppLockService.ts +++ b/packages/backend/src/core/AppLockService.ts @@ -1,7 +1,7 @@ import { promisify } from 'node:util'; import { Inject, Injectable } from '@nestjs/common'; import redisLock from 'redis-lock'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; diff --git a/packages/backend/src/core/CacheService.ts b/packages/backend/src/core/CacheService.ts index 561face5c3..cf1e81ffc8 100644 --- a/packages/backend/src/core/CacheService.ts +++ b/packages/backend/src/core/CacheService.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import type { BlockingsRepository, ChannelFollowingsRepository, FollowingsRepository, MutingsRepository, RenoteMutingsRepository, UserProfile, UserProfilesRepository, UsersRepository } from '@/models/index.js'; import { MemoryKVCache, RedisKVCache } from '@/misc/cache.js'; import type { LocalUser, User } from '@/models/entities/User.js'; diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts index 185171dee2..4ffa179cab 100644 --- a/packages/backend/src/core/CustomEmojiService.ts +++ b/packages/backend/src/core/CustomEmojiService.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { DataSource, In, IsNull } from 'typeorm'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { DI } from '@/di-symbols.js'; import { IdService } from '@/core/IdService.js'; import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; diff --git a/packages/backend/src/core/FederatedInstanceService.ts b/packages/backend/src/core/FederatedInstanceService.ts index 56660ae0d0..e028265bdc 100644 --- a/packages/backend/src/core/FederatedInstanceService.ts +++ b/packages/backend/src/core/FederatedInstanceService.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import type { InstancesRepository } from '@/models/index.js'; import type { Instance } from '@/models/entities/Instance.js'; import { MemoryKVCache, RedisKVCache } from '@/misc/cache.js'; diff --git a/packages/backend/src/core/GlobalEventService.ts b/packages/backend/src/core/GlobalEventService.ts index 2c2687a90c..0ed5241148 100644 --- a/packages/backend/src/core/GlobalEventService.ts +++ b/packages/backend/src/core/GlobalEventService.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import type { User } from '@/models/entities/User.js'; import type { Note } from '@/models/entities/Note.js'; import type { UserList } from '@/models/entities/UserList.js'; diff --git a/packages/backend/src/core/MetaService.ts b/packages/backend/src/core/MetaService.ts index 1322927c2c..0b861be8d0 100644 --- a/packages/backend/src/core/MetaService.ts +++ b/packages/backend/src/core/MetaService.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { DI } from '@/di-symbols.js'; import { Meta } from '@/models/entities/Meta.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index 79629cb2a8..50081f831b 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -1,7 +1,7 @@ import { setImmediate } from 'node:timers/promises'; import * as mfm from 'mfm-js'; import { In, DataSource } from 'typeorm'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import { extractMentions } from '@/misc/extract-mentions.js'; import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm.js'; diff --git a/packages/backend/src/core/NotificationService.ts b/packages/backend/src/core/NotificationService.ts index 6691c42836..a245908c98 100644 --- a/packages/backend/src/core/NotificationService.ts +++ b/packages/backend/src/core/NotificationService.ts @@ -1,5 +1,5 @@ import { setTimeout } from 'node:timers/promises'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import { In } from 'typeorm'; import { DI } from '@/di-symbols.js'; @@ -111,7 +111,7 @@ export class NotificationService implements OnApplicationShutdown { // 2秒経っても(今回作成した)通知が既読にならなかったら「未読の通知がありますよ」イベントを発行する setTimeout(2000, 'unread notification', { signal: this.#shutdownController.signal }).then(async () => { const latestReadNotificationId = await this.redisClient.get(`latestReadNotification:${notifieeId}`); - if (latestReadNotificationId && (latestReadNotificationId >= await redisIdPromise)) return; + if (latestReadNotificationId && (latestReadNotificationId >= (await redisIdPromise)!)) return; this.globalEventService.publishMainStream(notifieeId, 'unreadNotification', packed); this.pushNotificationService.pushNotification(notifieeId, 'notification', packed); diff --git a/packages/backend/src/core/PushNotificationService.ts b/packages/backend/src/core/PushNotificationService.ts index 9b44cf6413..a4c569bdec 100644 --- a/packages/backend/src/core/PushNotificationService.ts +++ b/packages/backend/src/core/PushNotificationService.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import push from 'web-push'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import type { Packed } from '@/misc/json-schema'; diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index 2a4271aa98..3878c147d0 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { In } from 'typeorm'; import type { Role, RoleAssignment, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/index.js'; import { MemoryKVCache, MemorySingleCache } from '@/misc/cache.js'; diff --git a/packages/backend/src/core/UserKeypairService.ts b/packages/backend/src/core/UserKeypairService.ts index 22a9fb2b8e..72c35c529c 100644 --- a/packages/backend/src/core/UserKeypairService.ts +++ b/packages/backend/src/core/UserKeypairService.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import type { User } from '@/models/entities/User.js'; import type { UserKeypairsRepository } from '@/models/index.js'; import { RedisKVCache } from '@/misc/cache.js'; diff --git a/packages/backend/src/core/WebhookService.ts b/packages/backend/src/core/WebhookService.ts index 926115613b..57baade777 100644 --- a/packages/backend/src/core/WebhookService.ts +++ b/packages/backend/src/core/WebhookService.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import type { WebhooksRepository } from '@/models/index.js'; import type { Webhook } from '@/models/entities/Webhook.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index 51e6b1d7ab..2c67cb772b 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { In, Not } from 'typeorm'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import Ajv from 'ajv'; import { ModuleRef } from '@nestjs/core'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/misc/cache.ts b/packages/backend/src/misc/cache.ts index f413246a1f..5610929648 100644 --- a/packages/backend/src/misc/cache.ts +++ b/packages/backend/src/misc/cache.ts @@ -1,4 +1,4 @@ -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { bindThis } from '@/decorators.js'; export class RedisKVCache { @@ -38,7 +38,7 @@ export class RedisKVCache { await this.redisClient.set( `kvcache:${this.name}:${key}`, this.toRedisConverter(value), - 'ex', Math.round(this.lifetime / 1000), + 'EX', Math.round(this.lifetime / 1000), ); } } @@ -122,7 +122,7 @@ export class RedisSingleCache { await this.redisClient.set( `singlecache:${this.name}`, this.toRedisConverter(value), - 'ex', Math.round(this.lifetime / 1000), + 'EX', Math.round(this.lifetime / 1000), ); } } diff --git a/packages/backend/src/server/api/RateLimiterService.ts b/packages/backend/src/server/api/RateLimiterService.ts index 1f8915ecca..fe2db1d66a 100644 --- a/packages/backend/src/server/api/RateLimiterService.ts +++ b/packages/backend/src/server/api/RateLimiterService.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import Limiter from 'ratelimiter'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { DI } from '@/di-symbols.js'; import type Logger from '@/logger.js'; import { LoggerService } from '@/core/LoggerService.js'; diff --git a/packages/backend/src/server/api/StreamingApiServerService.ts b/packages/backend/src/server/api/StreamingApiServerService.ts index 769a4490d6..258e8de034 100644 --- a/packages/backend/src/server/api/StreamingApiServerService.ts +++ b/packages/backend/src/server/api/StreamingApiServerService.ts @@ -1,6 +1,6 @@ import { EventEmitter } from 'events'; import { Inject, Injectable } from '@nestjs/common'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import * as websocket from 'websocket'; import { DI } from '@/di-symbols.js'; import type { UsersRepository, BlockingsRepository, ChannelFollowingsRepository, FollowingsRepository, MutingsRepository, UserProfilesRepository, RenoteMutingsRepository } from '@/models/index.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/server-info.ts b/packages/backend/src/server/api/endpoints/admin/server-info.ts index 9c576dffe9..4ef4fdc665 100644 --- a/packages/backend/src/server/api/endpoints/admin/server-info.ts +++ b/packages/backend/src/server/api/endpoints/admin/server-info.ts @@ -2,7 +2,7 @@ import * as os from 'node:os'; import si from 'systeminformation'; import { Inject, Injectable } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; diff --git a/packages/backend/src/server/api/endpoints/antennas/notes.ts b/packages/backend/src/server/api/endpoints/antennas/notes.ts index 88623ce26a..dca0f443b7 100644 --- a/packages/backend/src/server/api/endpoints/antennas/notes.ts +++ b/packages/backend/src/server/api/endpoints/antennas/notes.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { NotesRepository, AntennasRepository } from '@/models/index.js'; import { QueryService } from '@/core/QueryService.js'; diff --git a/packages/backend/src/server/api/endpoints/channels/timeline.ts b/packages/backend/src/server/api/endpoints/channels/timeline.ts index 2491d14235..c881074bab 100644 --- a/packages/backend/src/server/api/endpoints/channels/timeline.ts +++ b/packages/backend/src/server/api/endpoints/channels/timeline.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { ChannelsRepository, Note, NotesRepository } from '@/models/index.js'; import { QueryService } from '@/core/QueryService.js'; diff --git a/packages/backend/src/server/api/endpoints/i/notifications.ts b/packages/backend/src/server/api/endpoints/i/notifications.ts index ba0487f223..e141be764a 100644 --- a/packages/backend/src/server/api/endpoints/i/notifications.ts +++ b/packages/backend/src/server/api/endpoints/i/notifications.ts @@ -1,5 +1,5 @@ import { Brackets, In } from 'typeorm'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { Inject, Injectable } from '@nestjs/common'; import type { UsersRepository, FollowingsRepository, MutingsRepository, UserProfilesRepository, NotesRepository } from '@/models/index.js'; import { obsoleteNotificationTypes, notificationTypes } from '@/types.js'; diff --git a/packages/backend/src/server/api/endpoints/reset-db.ts b/packages/backend/src/server/api/endpoints/reset-db.ts index 655dd7cd83..4ced6d3ff1 100644 --- a/packages/backend/src/server/api/endpoints/reset-db.ts +++ b/packages/backend/src/server/api/endpoints/reset-db.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { resetDb } from '@/misc/reset-db.js'; diff --git a/packages/backend/src/server/api/endpoints/roles/notes.ts b/packages/backend/src/server/api/endpoints/roles/notes.ts index b45d4af1fe..90c8281a49 100644 --- a/packages/backend/src/server/api/endpoints/roles/notes.ts +++ b/packages/backend/src/server/api/endpoints/roles/notes.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import Redis from 'ioredis'; +import * as Redis from 'ioredis'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { NotesRepository, RolesRepository } from '@/models/index.js'; import { QueryService } from '@/core/QueryService.js'; -- cgit v1.2.3-freya From 9469b26eb25caf89cd9b1919e8ba380c0d33708a Mon Sep 17 00:00:00 2001 From: nenohi Date: Fri, 14 Apr 2023 14:49:41 +0900 Subject: カスタム絵文字の検索を絵文字ピッカー使用できるように (#10335) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix( #10013) * add changelog * also in about.emojis.vue * fix changelog --------- Co-authored-by: tamaina --- .../backend/src/server/api/endpoints/admin/emoji/list.ts | 16 +++++++++++----- packages/frontend/src/pages/about.emojis.vue | 10 +++++++++- 2 files changed, 20 insertions(+), 6 deletions(-) (limited to 'packages/backend/src/server/api/endpoints') diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts index 814668294f..4aa4ad82b4 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts @@ -87,12 +87,18 @@ export default class extends Endpoint { //const emojis = await q.take(ps.limit).getMany(); emojis = await q.getMany(); + const queryarry = ps.query.match(/\:([a-z0-9_]*)\:/g); - emojis = emojis.filter(emoji => - emoji.name.includes(ps.query!) || - emoji.aliases.some(a => a.includes(ps.query!)) || - emoji.category?.includes(ps.query!)); - + if (queryarry) { + emojis = emojis.filter(emoji => + queryarry.includes(`:${emoji.name}:`) + ); + } else { + emojis = emojis.filter(emoji => + emoji.name.includes(ps.query!) || + emoji.aliases.some(a => a.includes(ps.query!)) || + emoji.category?.includes(ps.query!)); + } emojis.splice(ps.limit + 1); } else { emojis = await q.take(ps.limit).getMany(); diff --git a/packages/frontend/src/pages/about.emojis.vue b/packages/frontend/src/pages/about.emojis.vue index d461430234..2d82fcf277 100644 --- a/packages/frontend/src/pages/about.emojis.vue +++ b/packages/frontend/src/pages/about.emojis.vue @@ -53,7 +53,15 @@ function search() { } if (selectedTags.size === 0) { - searchEmojis = customEmojis.value.filter(emoji => emoji.name.includes(q) || emoji.aliases.includes(q)); + const queryarry = q.match(/\:([a-z0-9_]*)\:/g); + + if (queryarry) { + searchEmojis = customEmojis.value.filter(emoji => + queryarry.includes(`:${emoji.name}:`) + ); + } else { + searchEmojis = customEmojis.value.filter(emoji => emoji.name.includes(q) || emoji.aliases.includes(q)); + } } else { searchEmojis = customEmojis.value.filter(emoji => (emoji.name.includes(q) || emoji.aliases.includes(q)) && [...selectedTags].every(t => emoji.aliases.includes(t))); } -- cgit v1.2.3-freya From 0ddc79bb9127eb6de0ba5110329bf15a506a6540 Mon Sep 17 00:00:00 2001 From: Nanashia Date: Sun, 16 Apr 2023 15:23:49 +0900 Subject: fix(backend): アバターとバナーがリセットできない (#10643) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(backend): avatar and banner couldn't be reset * Update CHANGELOG.md --- CHANGELOG.md | 1 + packages/backend/src/server/api/endpoints/i/update.ts | 8 ++++++++ packages/backend/test/e2e/users.ts | 2 -- 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'packages/backend/src/server/api/endpoints') diff --git a/CHANGELOG.md b/CHANGELOG.md index deb5b3e978..d0c662a54b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ ### Server - Fix: エクスポートデータの拡張子がunknownになる問題を修正 - Fix: Content-Dispositionのパースでエラーが発生した場合にダウンロードが完了しない問題を修正 +- Fix: API: i/update avatarIdとbannerIdにnullを渡した時、画像がリセットされない問題を修正 ## 13.11.3 diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index be1c72b207..97699f3bef 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -221,6 +221,10 @@ export default class extends Endpoint { updates.avatarId = avatar.id; updates.avatarUrl = this.driveFileEntityService.getPublicUrl(avatar, 'avatar'); updates.avatarBlurhash = avatar.blurhash; + } else if (ps.avatarId === null) { + updates.avatarId = null; + updates.avatarUrl = null; + updates.avatarBlurhash = null; } if (ps.bannerId) { @@ -232,6 +236,10 @@ export default class extends Endpoint { updates.bannerId = banner.id; updates.bannerUrl = this.driveFileEntityService.getPublicUrl(banner); updates.bannerBlurhash = banner.blurhash; + } else if (ps.bannerId === null) { + updates.bannerId = null; + updates.bannerUrl = null; + updates.bannerBlurhash = null; } if (ps.pinnedPageId) { diff --git a/packages/backend/test/e2e/users.ts b/packages/backend/test/e2e/users.ts index 444fb284b3..2c4716c060 100644 --- a/packages/backend/test/e2e/users.ts +++ b/packages/backend/test/e2e/users.ts @@ -508,7 +508,6 @@ describe('ユーザー', () => { }; assert.deepStrictEqual(response, expected, inspect(parameters)); - if (1) return; // BUG 521eb95 以降アバターのリセットができない。 const parameters2 = { avatarId: null }; const response2 = await successfulApiCall({ endpoint: 'i/update', parameters: parameters2, user: alice }); const expected2 = { @@ -534,7 +533,6 @@ describe('ユーザー', () => { }; assert.deepStrictEqual(response, expected, inspect(parameters)); - if (1) return; // BUG 521eb95 以降バナーのリセットができない。 const parameters2 = { bannerId: null }; const response2 = await successfulApiCall({ endpoint: 'i/update', parameters: parameters2, user: alice }); const expected2 = { -- cgit v1.2.3-freya From 65ff2c24980b7989a2925772721c0b2bc503d515 Mon Sep 17 00:00:00 2001 From: nenohi Date: Wed, 19 Apr 2023 08:25:24 +0900 Subject: カスタム絵文字のライセンスを一括でできるように (#10671) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * setlicensebulk追加 * 5時に誤字った!w * 並び順の変更(set,add,removeの順 * add changelog --- CHANGELOG.md | 1 + packages/backend/src/core/CustomEmojiService.ts | 16 ++++++++++ packages/backend/src/server/api/EndpointsModule.ts | 4 +++ packages/backend/src/server/api/endpoints.ts | 2 ++ .../api/endpoints/admin/emoji/set-license-bulk.ts | 37 ++++++++++++++++++++++ .../frontend/src/pages/custom-emojis-manager.vue | 15 ++++++++- 6 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 packages/backend/src/server/api/endpoints/admin/emoji/set-license-bulk.ts (limited to 'packages/backend/src/server/api/endpoints') diff --git a/CHANGELOG.md b/CHANGELOG.md index edad9abc77..979caa8a89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ### Client - +- カスタム絵文字のライセンスを複数でセットできるようになりました。 ### Server - diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts index 4ffa179cab..93557ce617 100644 --- a/packages/backend/src/core/CustomEmojiService.ts +++ b/packages/backend/src/core/CustomEmojiService.ts @@ -197,6 +197,22 @@ export class CustomEmojiService { emojis: await this.emojiEntityService.packDetailedMany(ids), }); } + + @bindThis + public async setLicenseBulk(ids: Emoji['id'][], license: string | null) { + await this.emojisRepository.update({ + id: In(ids), + }, { + updatedAt: new Date(), + license: license, + }); + + this.localEmojisCache.refresh(); + + this.globalEventService.publishBroadcastStream('emojiUpdated', { + emojis: await this.emojiEntityService.packDetailedMany(ids), + }); + } @bindThis public async delete(id: Emoji['id']) { diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index 737bf0c84c..e4e594ec54 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -29,6 +29,7 @@ import * as ep___admin_emoji_list from './endpoints/admin/emoji/list.js'; import * as ep___admin_emoji_removeAliasesBulk from './endpoints/admin/emoji/remove-aliases-bulk.js'; import * as ep___admin_emoji_setAliasesBulk from './endpoints/admin/emoji/set-aliases-bulk.js'; import * as ep___admin_emoji_setCategoryBulk from './endpoints/admin/emoji/set-category-bulk.js'; +import * as ep___admin_emoji_setLicenseBulk from './endpoints/admin/emoji/set-license-bulk.js'; import * as ep___admin_emoji_update from './endpoints/admin/emoji/update.js'; import * as ep___admin_federation_deleteAllFiles from './endpoints/admin/federation/delete-all-files.js'; import * as ep___admin_federation_refreshRemoteInstanceMetadata from './endpoints/admin/federation/refresh-remote-instance-metadata.js'; @@ -365,6 +366,7 @@ const $admin_emoji_list: Provider = { provide: 'ep:admin/emoji/list', useClass: const $admin_emoji_removeAliasesBulk: Provider = { provide: 'ep:admin/emoji/remove-aliases-bulk', useClass: ep___admin_emoji_removeAliasesBulk.default }; const $admin_emoji_setAliasesBulk: Provider = { provide: 'ep:admin/emoji/set-aliases-bulk', useClass: ep___admin_emoji_setAliasesBulk.default }; const $admin_emoji_setCategoryBulk: Provider = { provide: 'ep:admin/emoji/set-category-bulk', useClass: ep___admin_emoji_setCategoryBulk.default }; +const $admin_emoji_setLicenseBulk: Provider = { provide: 'ep:admin/emoji/set-license-bulk', useClass: ep___admin_emoji_setLicenseBulk.default }; const $admin_emoji_update: Provider = { provide: 'ep:admin/emoji/update', useClass: ep___admin_emoji_update.default }; const $admin_federation_deleteAllFiles: Provider = { provide: 'ep:admin/federation/delete-all-files', useClass: ep___admin_federation_deleteAllFiles.default }; const $admin_federation_refreshRemoteInstanceMetadata: Provider = { provide: 'ep:admin/federation/refresh-remote-instance-metadata', useClass: ep___admin_federation_refreshRemoteInstanceMetadata.default }; @@ -705,6 +707,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention $admin_emoji_removeAliasesBulk, $admin_emoji_setAliasesBulk, $admin_emoji_setCategoryBulk, + $admin_emoji_setLicenseBulk, $admin_emoji_update, $admin_federation_deleteAllFiles, $admin_federation_refreshRemoteInstanceMetadata, @@ -1039,6 +1042,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention $admin_emoji_removeAliasesBulk, $admin_emoji_setAliasesBulk, $admin_emoji_setCategoryBulk, + $admin_emoji_setLicenseBulk, $admin_emoji_update, $admin_federation_deleteAllFiles, $admin_federation_refreshRemoteInstanceMetadata, diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index dc82c04e4e..305ce3b34c 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -29,6 +29,7 @@ import * as ep___admin_emoji_list from './endpoints/admin/emoji/list.js'; import * as ep___admin_emoji_removeAliasesBulk from './endpoints/admin/emoji/remove-aliases-bulk.js'; import * as ep___admin_emoji_setAliasesBulk from './endpoints/admin/emoji/set-aliases-bulk.js'; import * as ep___admin_emoji_setCategoryBulk from './endpoints/admin/emoji/set-category-bulk.js'; +import * as ep___admin_emoji_setLicenseBulk from './endpoints/admin/emoji/set-license-bulk.js'; import * as ep___admin_emoji_update from './endpoints/admin/emoji/update.js'; import * as ep___admin_federation_deleteAllFiles from './endpoints/admin/federation/delete-all-files.js'; import * as ep___admin_federation_refreshRemoteInstanceMetadata from './endpoints/admin/federation/refresh-remote-instance-metadata.js'; @@ -363,6 +364,7 @@ const eps = [ ['admin/emoji/remove-aliases-bulk', ep___admin_emoji_removeAliasesBulk], ['admin/emoji/set-aliases-bulk', ep___admin_emoji_setAliasesBulk], ['admin/emoji/set-category-bulk', ep___admin_emoji_setCategoryBulk], + ['admin/emoji/set-license-bulk', ep___admin_emoji_setLicenseBulk], ['admin/emoji/update', ep___admin_emoji_update], ['admin/federation/delete-all-files', ep___admin_federation_deleteAllFiles], ['admin/federation/refresh-remote-instance-metadata', ep___admin_federation_refreshRemoteInstanceMetadata], diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/set-license-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/set-license-bulk.ts new file mode 100644 index 0000000000..b90b9757be --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/emoji/set-license-bulk.ts @@ -0,0 +1,37 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { CustomEmojiService } from '@/core/CustomEmojiService.js'; + +export const meta = { + tags: ['admin'], + + requireCredential: true, + requireRolePolicy: 'canManageCustomEmojis', +} as const; + +export const paramDef = { + type: 'object', + properties: { + ids: { type: 'array', items: { + type: 'string', format: 'misskey:id', + } }, + license: { + type: 'string', + nullable: true, + description: 'Use `null` to reset the license.', + }, + }, + required: ['ids'], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + private customEmojiService: CustomEmojiService, + ) { + super(meta, paramDef, async (ps, me) => { + await this.customEmojiService.setLicenseBulk(ps.ids, ps.license ?? null); + }); + } +} diff --git a/packages/frontend/src/pages/custom-emojis-manager.vue b/packages/frontend/src/pages/custom-emojis-manager.vue index 59cb3262b7..3f13f0787d 100644 --- a/packages/frontend/src/pages/custom-emojis-manager.vue +++ b/packages/frontend/src/pages/custom-emojis-manager.vue @@ -15,9 +15,10 @@
Select all Set category + Set tag Add tag Remove tag - Set tag + Set Lisence Delete
@@ -221,6 +222,18 @@ const setCategoryBulk = async () => { emojisPaginationComponent.value.reload(); }; +const setLisenceBulk = async () => { + const { canceled, result } = await os.inputText({ + title: 'License', + }); + if (canceled) return; + await os.apiWithDialog('admin/emoji/set-license-bulk', { + ids: selectedEmojis.value, + license: result, + }); + emojisPaginationComponent.value.reload(); +}; + const addTagBulk = async () => { const { canceled, result } = await os.inputText({ title: 'Tag', -- cgit v1.2.3-freya From e1f9ab77f86f5a12091c864cdb502970715cd46e Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 19 Apr 2023 21:24:31 +0900 Subject: feat: Server rules (#10660) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * enhance(frontend): サーバールールのデザイン調整 * enhance(frontend): i18n * enhance(frontend): 利用規約URLの設定を「モデレーション」ページへ移動 * enhance(frontend): サーバールールのデザイン調整 * Update CHANGELOG.md * 不要な差分を削除 * fix(frontend): lint * ui tweak * test: add stories * tweak * test: bind args * test: add interaction tests * fix bug * Update packages/frontend/src/pages/admin/server-rules.vue Co-authored-by: Ebise Lutica <7106976+EbiseLutica@users.noreply.github.com> * Update misskey-js.api.md * chore: windowを明示 * :art: * refactor * :art: * :art: * fix e2e test * :art: * :art: * fix icon * fix e2e --------- Co-authored-by: Ebise Lutica <7106976+EbiseLutica@users.noreply.github.com> Co-authored-by: Acid Chicken (硫酸鶏) --- CHANGELOG.md | 1 + cypress/e2e/basic.cy.js | 12 + locales/ja-JP.yml | 9 +- .../backend/migration/1681400427971-serverRules.js | 11 + packages/backend/src/models/entities/Meta.ts | 7 + .../src/server/api/endpoints/admin/update-meta.ts | 5 + packages/backend/src/server/api/endpoints/meta.ts | 2 + packages/frontend/.storybook/generate.tsx | 1 + packages/frontend/src/components/MkFolder.vue | 8 +- packages/frontend/src/components/MkModal.vue | 6 - packages/frontend/src/components/MkModalWindow.vue | 5 +- packages/frontend/src/components/MkSignup.vue | 263 -------------------- .../src/components/MkSignupDialog.form.vue | 272 +++++++++++++++++++++ .../MkSignupDialog.rules.stories.impl.ts | 94 +++++++ .../src/components/MkSignupDialog.rules.vue | 114 +++++++++ .../frontend/src/components/MkSignupDialog.vue | 45 +++- packages/frontend/src/components/MkSwitch.vue | 2 +- packages/frontend/src/pages/about.vue | 2 +- packages/frontend/src/pages/admin/moderation.vue | 9 + packages/frontend/src/pages/admin/server-rules.vue | 128 ++++++++++ packages/frontend/src/pages/admin/settings.vue | 8 - packages/frontend/src/router.ts | 4 + packages/frontend/src/store.ts | 4 +- packages/misskey-js/etc/misskey-js.api.md | 1 + packages/misskey-js/src/entities.ts | 1 + 25 files changed, 719 insertions(+), 295 deletions(-) create mode 100644 packages/backend/migration/1681400427971-serverRules.js delete mode 100644 packages/frontend/src/components/MkSignup.vue create mode 100644 packages/frontend/src/components/MkSignupDialog.form.vue create mode 100644 packages/frontend/src/components/MkSignupDialog.rules.stories.impl.ts create mode 100644 packages/frontend/src/components/MkSignupDialog.rules.vue create mode 100644 packages/frontend/src/pages/admin/server-rules.vue (limited to 'packages/backend/src/server/api/endpoints') diff --git a/CHANGELOG.md b/CHANGELOG.md index 979caa8a89..ec626d1447 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Node.js 18.6.0以上が必要になりました ### General +- 新規登録前に簡潔なルールをユーザーに表示できる、サーバールール機能を追加 - ユーザーへの自分用メモ機能 * ユーザーに対して、自分だけが見られるメモを追加できるようになりました。 (自分自身に対してもメモを追加できます。) diff --git a/cypress/e2e/basic.cy.js b/cypress/e2e/basic.cy.js index 8dc07c1800..b0c3d4c19a 100644 --- a/cypress/e2e/basic.cy.js +++ b/cypress/e2e/basic.cy.js @@ -52,6 +52,12 @@ describe('After setup instance', () => { cy.intercept('POST', '/api/signup').as('signup'); cy.get('[data-cy-signup]').click(); + cy.get('[data-cy-signup-rules-continue]').should('be.disabled'); + cy.get('[data-cy-signup-rules-notes] [data-cy-folder-header]').click(); + cy.get('[data-cy-signup-rules-notes-agree] [data-cy-switch-toggle]').click(); + cy.get('[data-cy-signup-rules-continue]').should('not.be.disabled'); + cy.get('[data-cy-signup-rules-continue]').click(); + cy.get('[data-cy-signup-submit]').should('be.disabled'); cy.get('[data-cy-signup-username] input').type('alice'); cy.get('[data-cy-signup-submit]').should('be.disabled'); @@ -71,6 +77,12 @@ describe('After setup instance', () => { // ユーザー名が重複している場合の挙動確認 cy.get('[data-cy-signup]').click(); + cy.get('[data-cy-signup-rules-continue]').should('be.disabled'); + cy.get('[data-cy-signup-rules-notes] [data-cy-folder-header]').click(); + cy.get('[data-cy-signup-rules-notes-agree] [data-cy-switch-toggle]').click(); + cy.get('[data-cy-signup-rules-continue]').should('not.be.disabled'); + cy.get('[data-cy-signup-rules-continue]').click(); + cy.get('[data-cy-signup-username] input').type('alice'); cy.get('[data-cy-signup-password] input').type('alice1234'); cy.get('[data-cy-signup-password-retype] input').type('alice1234'); diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 9a526e67e9..cd9521a9f8 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -263,9 +263,10 @@ noMoreHistory: "これより過去の履歴はありません" startMessaging: "チャットを開始" nUsersRead: "{n}人が読みました" agreeTo: "{0}に同意" +agree: "同意する" agreeBelow: "下記に同意する" basicNotesBeforeCreateAccount: "基本的な注意事項" -tos: "利用規約" +termsOfService: "利用規約" start: "始める" home: "ホーム" remoteUserCaution: "リモートユーザーのため、情報が不完全です。" @@ -1010,6 +1011,12 @@ stackAxis: "スタック方向" vertical: "縦" horizontal: "横" position: "位置" +serverRules: "サーバールール" +pleaseConfirmBelowBeforeSignup: "このサーバーに登録する前に、以下を確認してください。" +continue: "続ける" + +_serverRules: + description: "新規登録前に表示する、サーバーの簡潔なルールを設定します。内容は利用規約の要約とすることを推奨します。" _accountMigration: moveTo: "このアカウントを新しいアカウントに引っ越す" diff --git a/packages/backend/migration/1681400427971-serverRules.js b/packages/backend/migration/1681400427971-serverRules.js new file mode 100644 index 0000000000..2364e8e1d2 --- /dev/null +++ b/packages/backend/migration/1681400427971-serverRules.js @@ -0,0 +1,11 @@ +export class ServerRules1681400427971 { + name = 'ServerRules1681400427971' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "serverRules" character varying(280) array NOT NULL DEFAULT '{}'`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "serverRules"`); + } +} diff --git a/packages/backend/src/models/entities/Meta.ts b/packages/backend/src/models/entities/Meta.ts index 2e4f90b57f..c8df141a0b 100644 --- a/packages/backend/src/models/entities/Meta.ts +++ b/packages/backend/src/models/entities/Meta.ts @@ -405,4 +405,11 @@ export class Meta { default: { }, }) public policies: Record; + + @Column('varchar', { + length: 280, + array: true, + default: '{}', + }) + public serverRules: string[]; } diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index 11de29bf83..ae2fc84b50 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -94,6 +94,7 @@ export const paramDef = { enableActiveEmailValidation: { type: 'boolean' }, enableChartsForRemoteUser: { type: 'boolean' }, enableChartsForFederatedInstances: { type: 'boolean' }, + serverRules: { type: 'array', items: { type: 'string' } }, }, required: [], } as const; @@ -387,6 +388,10 @@ export default class extends Endpoint { set.enableChartsForFederatedInstances = ps.enableChartsForFederatedInstances; } + if (ps.serverRules !== undefined) { + set.serverRules = ps.serverRules; + } + await this.metaService.update(set); this.moderationLogService.insertModerationLog(me, 'updateMeta'); }); diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 37974ce2a3..a5cb3fa7ee 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -310,6 +310,8 @@ export default class extends Endpoint { translatorAvailable: instance.deeplAuthKey != null, + serverRules: instance.serverRules, + policies: { ...DEFAULT_POLICIES, ...instance.policies }, mediaProxy: this.config.mediaProxy, diff --git a/packages/frontend/.storybook/generate.tsx b/packages/frontend/.storybook/generate.tsx index bb98805743..dbe9729170 100644 --- a/packages/frontend/.storybook/generate.tsx +++ b/packages/frontend/.storybook/generate.tsx @@ -398,6 +398,7 @@ Promise.all([ glob('src/components/global/*.vue'), glob('src/components/Mk{A,B}*.vue'), glob('src/components/MkGalleryPostPreview.vue'), + glob('src/components/MkSignupServerRules.vue'), glob('src/pages/user/home.vue'), ]) .then((globs) => globs.flat()) diff --git a/packages/frontend/src/components/MkFolder.vue b/packages/frontend/src/components/MkFolder.vue index 58cc0de5c8..fd070a5f13 100644 --- a/packages/frontend/src/components/MkFolder.vue +++ b/packages/frontend/src/components/MkFolder.vue @@ -1,8 +1,8 @@