From b1d0b291ffce134478f5c80611baec7f91f7c503 Mon Sep 17 00:00:00 2001 From: Namekuji Date: Tue, 30 May 2023 23:10:12 -0400 Subject: [PATCH 1/3] get array for alsoKnownAs --- .../src/server/api/endpoints/i/known-as.ts | 63 ++++++++++--------- .../src/server/api/endpoints/users/show.ts | 35 ++++++----- .../client/src/pages/settings/migration.vue | 54 +++++++++------- 3 files changed, 88 insertions(+), 64 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/i/known-as.ts b/packages/backend/src/server/api/endpoints/i/known-as.ts index 5e86e8b955..d4d9061b30 100644 --- a/packages/backend/src/server/api/endpoints/i/known-as.ts +++ b/packages/backend/src/server/api/endpoints/i/known-as.ts @@ -1,4 +1,4 @@ -import type { User, UserDetailedNotMeOnly } from "@/models/entities/user.js"; +import type { User } from "@/models/entities/user.js"; import { Users } from "@/models/index.js"; import { resolveUser } from "@/remote/resolve-user.js"; import acceptAllFollowRequests from "@/services/following/requests/accept-all.js"; @@ -6,10 +6,9 @@ import { publishToFollowers } from "@/services/i/update.js"; import { publishMainStream } from "@/services/stream.js"; import { DAY } from "@/const.js"; import { apiLogger } from "../../logger.js"; -import { UserProfiles } from "@/models/index.js"; -import config from "@/config/index.js"; import define from "../../define.js"; import { ApiError } from "../../error.js"; +import { parse } from "@/misc/acct.js"; export const meta = { tags: ["users"], @@ -38,49 +37,57 @@ export const meta = { code: "URI_NULL", id: "bf326f31-d430-4f97-9933-5d61e4d48a23", }, + alreadyMoved: { + message: 'You have already moved your account.', + code: 'ALREADY_MOVED', + id: '56f20ec9-fd06-4fa5-841b-edd6d7d4fa31', + }, + yourself: { + message: 'You can\'t set yourself as your own alias.', + code: 'FORBIDDEN_TO_SET_YOURSELF', + id: '25c90186-4ab0-49c8-9bba-a1fa6c202ba4', + }, }, } as const; export const paramDef = { type: "object", properties: { - alsoKnownAs: { type: "string" }, + alsoKnownAs: { + type: 'array', + maxItems: 10, + uniqueItems: true, + items: { type: 'string' }, + }, }, required: ["alsoKnownAs"], } as const; export default define(meta, paramDef, async (ps, user) => { if (!ps.alsoKnownAs) throw new ApiError(meta.errors.noSuchUser); + if (user.movedToUri) throw new ApiError(meta.errors.alreadyMoved); - let unfiltered: string = ps.alsoKnownAs; - const updates = {} as Partial; + const newAka = new Set(); - if (!unfiltered) { - updates.alsoKnownAs = null; - } else { - if (unfiltered.startsWith("acct:")) unfiltered = unfiltered.substring(5); - if (unfiltered.startsWith("@")) unfiltered = unfiltered.substring(1); - if (!unfiltered.includes("@")) throw new ApiError(meta.errors.notRemote); + for (const line of ps.alsoKnownAs) { + if (!line) throw new ApiError(meta.errors.noSuchUser); + const { username, host } = parse(line); - const userAddress: string[] = unfiltered.split("@"); - const knownAs = await resolveUser(userAddress[0], userAddress[1]).catch( - (e) => { - apiLogger.warn(`failed to resolve remote user: ${e}`); - throw new ApiError(meta.errors.noSuchUser); - }, - ); + const aka = await resolveUser(username, host).catch((e) => { + apiLogger.warn(`failed to resolve remote user: ${e}`); + throw new ApiError(meta.errors.noSuchUser); + }); - const toUrl: string | null = knownAs.uri; - if (!toUrl) { - throw new ApiError(meta.errors.uriNull); - } - if (updates.alsoKnownAs == null || updates.alsoKnownAs.length === 0) { - updates.alsoKnownAs = [toUrl]; - } else { - updates.alsoKnownAs.push(toUrl); - } + if (aka.id === user.id) throw new ApiError(meta.errors.yourself); + if (!aka.uri) throw new ApiError(meta.errors.uriNull); + + newAka.add(aka.uri); } + const updates = { + alsoKnownAs: newAka.size > 0 ? Array.from(newAka) : null, + } as Partial; + await Users.update(user.id, updates); const iObj = await Users.pack(user.id, user, { diff --git a/packages/backend/src/server/api/endpoints/users/show.ts b/packages/backend/src/server/api/endpoints/users/show.ts index 49cac81fdb..bead8df0a4 100644 --- a/packages/backend/src/server/api/endpoints/users/show.ts +++ b/packages/backend/src/server/api/endpoints/users/show.ts @@ -54,7 +54,7 @@ export const paramDef = { anyOf: [ { properties: { - userId: { type: "string", format: "misskey:id" }, + userId: { type: "string" }, }, required: ["userId"], }, @@ -65,7 +65,6 @@ export const paramDef = { uniqueItems: true, items: { type: "string", - format: "misskey:id", }, }, }, @@ -95,21 +94,27 @@ export default define(meta, paramDef, async (ps, me) => { return []; } - const users = await Users.findBy( - isAdminOrModerator - ? { - id: In(ps.userIds), - } - : { - id: In(ps.userIds), - isSuspended: false, - }, - ); + const isUrl = ps.userIds[0].startsWith("http"); + let users: User[]; + if (isUrl) { + users = await Users.findBy( + isAdminOrModerator + ? { uri: In(ps.userIds) } + : { uri: In(ps.userIds), isSuspended: false }, + ); + } else { + users = await Users.findBy( + isAdminOrModerator + ? { id: In(ps.userIds) } + : { id: In(ps.userIds), isSuspended: false }, + ); + } // リクエストされた通りに並べ替え const _users: User[] = []; for (const id of ps.userIds) { - _users.push(users.find((x) => x.id === id)!); + const res = users.find((x) => (isUrl ? x.uri === id : x.id === id)); + if (res) _users.push(res); } return await Promise.all( @@ -129,7 +134,9 @@ export default define(meta, paramDef, async (ps, me) => { } else { const q: FindOptionsWhere = ps.userId != null - ? { id: ps.userId } + ? ps.userId.startsWith("http") + ? { uri: ps.userId } + : { id: ps.userId } : { usernameLower: ps.username!.toLowerCase(), host: IsNull() }; user = await Users.findOneBy(q); diff --git a/packages/client/src/pages/settings/migration.vue b/packages/client/src/pages/settings/migration.vue index 6d5b435e3b..610d1ce1fe 100644 --- a/packages/client/src/pages/settings/migration.vue +++ b/packages/client/src/pages/settings/migration.vue @@ -2,14 +2,10 @@
+ {{ i18n.ts.moveAccountDescription }} - + - {{ i18n.ts.moveAccount }} @@ -18,19 +14,15 @@ - - - - + {{ i18n.ts.moveFromDescription }} + + + - + + {{ i18n.ts.add }} + {{ i18n.ts.save }} @@ -42,17 +34,35 @@ import FormSection from "@/components/form/section.vue"; import FormInput from "@/components/form/input.vue"; import FormButton from "@/components/MkButton.vue"; +import FormInfo from "@/components/MkInfo.vue"; import * as os from "@/os"; import { i18n } from "@/i18n"; import { definePageMetadata } from "@/scripts/page-metadata"; +import { $i } from "@/account"; +import { toString } from 'calckey-js/built/acct'; let moveToAccount = $ref(""); -let accountAlias = $ref(""); +let accountAlias = $ref([""]); -async function save(account): Promise { - os.apiWithDialog("i/known-as", { - alsoKnownAs: account, +await init(); + +async function init() { + if ($i?.alsoKnownAs && $i.alsoKnownAs.length > 0) { + const aka = await os.api('users/show', { userIds: $i.alsoKnownAs }); + accountAlias = (aka && aka.length > 0) ? aka.map(user => `@${toString(user)}`) : ['']; + } +} + +async function save(): Promise { + const i = os.apiWithDialog("i/known-as", { + alsoKnownAs: accountAlias.map(e => e.trim()).filter(e => e !== ""), }); + $i.alsoKnownAs = i.alsoKnownAs; + await init(); +} + +function add(): void { + accountAlias.push(''); } async function move(account): Promise { From c321a6ee39080efcb2f3fea08799409dba05e13f Mon Sep 17 00:00:00 2001 From: Namekuji Date: Wed, 31 May 2023 01:02:41 -0400 Subject: [PATCH 2/3] use parse instead --- .../backend/src/server/api/endpoints/i/move.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/i/move.ts b/packages/backend/src/server/api/endpoints/i/move.ts index 3d947063ff..ba2360b196 100644 --- a/packages/backend/src/server/api/endpoints/i/move.ts +++ b/packages/backend/src/server/api/endpoints/i/move.ts @@ -10,9 +10,9 @@ import deleteFollowing from "@/services/following/delete.js"; import create from "@/services/following/create.js"; import { getUser } from "@/server/api/common/getters.js"; import { Followings, Users } from "@/models/index.js"; -import { UserProfiles } from "@/models/index.js"; import config from "@/config/index.js"; import { publishMainStream } from "@/services/stream.js"; +import { parse } from "@/misc/acct.js"; export const meta = { tags: ["users"], @@ -95,17 +95,10 @@ export default define(meta, paramDef, async (ps, user) => { if (user.isAdmin) throw new ApiError(meta.errors.adminForbidden); if (user.movedToUri) throw new ApiError(meta.errors.alreadyMoved); - let unfiltered: string = ps.moveToAccount; - if (!unfiltered) { - throw new ApiError(meta.errors.noSuchMoveTarget); - } + const { username, host } = parse(ps.moveToAccount); + if (!host) throw new ApiError(meta.errors.notRemote); - if (unfiltered.startsWith("acct:")) unfiltered = unfiltered.substring(5); - if (unfiltered.startsWith("@")) unfiltered = unfiltered.substring(1); - if (!unfiltered.includes("@")) throw new ApiError(meta.errors.notRemote); - - const userAddress: string[] = unfiltered.split("@"); - const moveTo: User = await resolveUser(userAddress[0], userAddress[1]).catch( + const moveTo: User = await resolveUser(username, host).catch( (e) => { apiLogger.warn(`failed to resolve remote user: ${e}`); throw new ApiError(meta.errors.noSuchMoveTarget); @@ -134,6 +127,7 @@ export default define(meta, paramDef, async (ps, user) => { if (!toUrl) toUrl = ""; updates.movedToUri = toUrl; + updates.alsoKnownAs = user.alsoKnownAs?.concat(toUrl) ?? [toUrl]; await Users.update(user.id, updates); const iObj = await Users.pack(user.id, user, { From 8480ced256f0822af001e49ee145974d527613e8 Mon Sep 17 00:00:00 2001 From: Namekuji Date: Wed, 31 May 2023 01:14:13 -0400 Subject: [PATCH 3/3] remove empty form input --- .../src/server/api/endpoints/i/known-as.ts | 16 +++--- .../src/server/api/endpoints/i/move.ts | 10 ++-- .../client/src/pages/settings/migration.vue | 55 ++++++++++++++----- 3 files changed, 52 insertions(+), 29 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/i/known-as.ts b/packages/backend/src/server/api/endpoints/i/known-as.ts index d4d9061b30..0d0c06180a 100644 --- a/packages/backend/src/server/api/endpoints/i/known-as.ts +++ b/packages/backend/src/server/api/endpoints/i/known-as.ts @@ -38,14 +38,14 @@ export const meta = { id: "bf326f31-d430-4f97-9933-5d61e4d48a23", }, alreadyMoved: { - message: 'You have already moved your account.', - code: 'ALREADY_MOVED', - id: '56f20ec9-fd06-4fa5-841b-edd6d7d4fa31', + message: "You have already moved your account.", + code: "ALREADY_MOVED", + id: "56f20ec9-fd06-4fa5-841b-edd6d7d4fa31", }, yourself: { - message: 'You can\'t set yourself as your own alias.', - code: 'FORBIDDEN_TO_SET_YOURSELF', - id: '25c90186-4ab0-49c8-9bba-a1fa6c202ba4', + message: "You can't set yourself as your own alias.", + code: "FORBIDDEN_TO_SET_YOURSELF", + id: "25c90186-4ab0-49c8-9bba-a1fa6c202ba4", }, }, } as const; @@ -54,10 +54,10 @@ export const paramDef = { type: "object", properties: { alsoKnownAs: { - type: 'array', + type: "array", maxItems: 10, uniqueItems: true, - items: { type: 'string' }, + items: { type: "string" }, }, }, required: ["alsoKnownAs"], diff --git a/packages/backend/src/server/api/endpoints/i/move.ts b/packages/backend/src/server/api/endpoints/i/move.ts index ba2360b196..d972aaf1d9 100644 --- a/packages/backend/src/server/api/endpoints/i/move.ts +++ b/packages/backend/src/server/api/endpoints/i/move.ts @@ -98,12 +98,10 @@ export default define(meta, paramDef, async (ps, user) => { const { username, host } = parse(ps.moveToAccount); if (!host) throw new ApiError(meta.errors.notRemote); - const moveTo: User = await resolveUser(username, host).catch( - (e) => { - apiLogger.warn(`failed to resolve remote user: ${e}`); - throw new ApiError(meta.errors.noSuchMoveTarget); - }, - ); + const moveTo: User = await resolveUser(username, host).catch((e) => { + apiLogger.warn(`failed to resolve remote user: ${e}`); + throw new ApiError(meta.errors.noSuchMoveTarget); + }); let fromUrl: string | null = user.uri; if (!fromUrl) { fromUrl = `${config.url}/users/${user.id}`; diff --git a/packages/client/src/pages/settings/migration.vue b/packages/client/src/pages/settings/migration.vue index 610d1ce1fe..df65e6e25c 100644 --- a/packages/client/src/pages/settings/migration.vue +++ b/packages/client/src/pages/settings/migration.vue @@ -2,9 +2,13 @@
- {{ i18n.ts.moveAccountDescription }} + {{ + i18n.ts.moveAccountDescription + }} - + @@ -14,14 +18,30 @@ - {{ i18n.ts.moveFromDescription }} - - - + {{ + i18n.ts.moveFromDescription + }} + + + - - {{ i18n.ts.add }} + + {{ i18n.ts.add }} {{ i18n.ts.save }} @@ -39,7 +59,7 @@ import * as os from "@/os"; import { i18n } from "@/i18n"; import { definePageMetadata } from "@/scripts/page-metadata"; import { $i } from "@/account"; -import { toString } from 'calckey-js/built/acct'; +import { toString } from "calckey-js/built/acct"; let moveToAccount = $ref(""); let accountAlias = $ref([""]); @@ -48,21 +68,26 @@ await init(); async function init() { if ($i?.alsoKnownAs && $i.alsoKnownAs.length > 0) { - const aka = await os.api('users/show', { userIds: $i.alsoKnownAs }); - accountAlias = (aka && aka.length > 0) ? aka.map(user => `@${toString(user)}`) : ['']; + const aka = await os.api("users/show", { userIds: $i.alsoKnownAs }); + accountAlias = + aka && aka.length > 0 + ? aka.map((user) => `@${toString(user)}`) + : [""]; + } else { + accountAlias = [""]; } } async function save(): Promise { - const i = os.apiWithDialog("i/known-as", { - alsoKnownAs: accountAlias.map(e => e.trim()).filter(e => e !== ""), + const i = await os.apiWithDialog("i/known-as", { + alsoKnownAs: accountAlias.map((e) => e.trim()).filter((e) => e !== ""), }); $i.alsoKnownAs = i.alsoKnownAs; await init(); } function add(): void { - accountAlias.push(''); + accountAlias.push(""); } async function move(account): Promise {