Merge pull request 'fix: followers transfer via account migration' (#9822) from nmkj/calckey:fix-move into develop

Reviewed-on: https://codeberg.org/calckey/calckey/pulls/9822
This commit is contained in:
Kainoa Kanter 2023-04-08 00:06:08 +00:00
commit 49c44771e5
2 changed files with 40 additions and 68 deletions

View file

@ -1,19 +1,14 @@
import type { CacheableRemoteUser } from "@/models/entities/user.js";
import { IRemoteUser, User } from "@/models/entities/user.js";
import DbResolver from "@/remote/activitypub/db-resolver.js";
import { getRemoteUser } from "@/server/api/common/getters.js";
import { updatePerson } from "@/remote/activitypub/models/person.js";
import { Followings, Users } from "@/models/index.js";
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
import deleteFollowing from "@/services/following/delete.js";
import {
resolvePerson,
updatePerson,
} from "@/remote/activitypub/models/person.js";
import create from "@/services/following/create.js";
import { getUser } from "@/server/api/common/getters.js";
import { IdentifiableError } from "@/misc/identifiable-error.js";
import { ApiError } from "@/server/api/error.js";
import { meta } from "@/server/api/endpoints/following/create.js";
import { IObject } from "../../type.js";
import type { IMove, IActor } from "../../type.js";
import Resolver from "@/remote/activitypub/resolver.js";
import deleteFollowing from "@/services/following/delete.js";
import type { IMove } from "../../type.js";
import { getApHrefNullable } from "../../type.js";
export default async (
actor: CacheableRemoteUser,
@ -21,68 +16,46 @@ export default async (
): Promise<string> => {
// ※ There is a block target in activity.object, which should be a local user that exists.
const dbResolver = new DbResolver();
const resolver = new Resolver();
let new_acc = await dbResolver.getUserFromApId(activity.target);
let actor_new;
if (!new_acc)
actor_new = (await resolver.resolve(<string>activity.target)) as IActor;
// fetch the new and old accounts
const targetUri = getApHrefNullable(activity.target);
if (!targetUri) return "move: target uri is null";
const new_acc = await resolvePerson(targetUri);
if (!actor.uri) return "move: actor uri is null";
const old_acc = await resolvePerson(actor.uri);
if (
(!new_acc || new_acc.uri === null) &&
(!actor_new || actor_new.id === null)
) {
return "move: new acc not found";
// update them if they're remote
if (new_acc.uri) await updatePerson(new_acc.uri);
if (old_acc.uri) await updatePerson(old_acc.uri);
// check if alsoKnownAs of the new account is valid
let isValidMove = true;
if (old_acc.uri) {
if (!new_acc.alsoKnownAs?.includes(old_acc.uri)) {
isValidMove = false;
}
} else if (!new_acc.alsoKnownAs?.includes(old_acc.id)) {
isValidMove = false;
}
if (!isValidMove) {
return "skip: accounts invalid";
}
const newUri = new_acc ? new_acc.uri : actor_new?.url?.toString();
if (newUri === null || newUri === undefined)
return "move: new acc not found #2";
await updatePerson(newUri);
await updatePerson(actor.uri!);
new_acc = await dbResolver.getUserFromApId(newUri);
const old = await dbResolver.getUserFromApId(actor.uri!);
if (
old === null ||
old.uri === null ||
!new_acc?.alsoKnownAs?.includes(old.uri)
)
return "move: accounts invalid";
old.movedToUri = new_acc.uri;
const followee = await getUser(actor.id).catch((e) => {
if (e.id === "15348ddd-432d-49c2-8a5a-8069753becff")
throw new ApiError(meta.errors.noSuchUser);
throw e;
});
const followeeNew = await getUser(new_acc.id).catch((e) => {
if (e.id === "15348ddd-432d-49c2-8a5a-8069753becff")
throw new ApiError(meta.errors.noSuchUser);
throw e;
});
// add target uri to movedToUri in order to indicate that the user has moved
await Users.update(old_acc.id, { movedToUri: targetUri });
// follow the new account and unfollow the old one
const followings = await Followings.findBy({
followeeId: followee.id,
followeeId: old_acc.id,
});
followings.forEach(async (following) => {
//if follower is local
// If follower is local
if (!following.followerHost) {
const follower = await getUser(following.followerId).catch((e) => {
if (e.id === "15348ddd-432d-49c2-8a5a-8069753becff")
throw new ApiError(meta.errors.noSuchUser);
throw e;
});
await deleteFollowing(follower!, followee);
try {
await create(follower!, followeeNew);
} catch (e) {
const follower = await Users.findOneBy({ id: following.followerId });
if (!follower) return;
await create(follower, new_acc);
await deleteFollowing(follower, old_acc);
} catch {
/* empty */
}
}

View file

@ -3,7 +3,6 @@ import { resolveUser } from "@/remote/resolve-user.js";
import { DAY } from "@/const.js";
import DeliverManager from "@/remote/activitypub/deliver-manager.js";
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
import { genId } from "@/misc/gen-id.js";
import define from "../../define.js";
import { ApiError } from "../../error.js";
import { apiLogger } from "../../logger.js";
@ -81,7 +80,7 @@ export const paramDef = {
function moveActivity(toUrl: string, fromUrl: string) {
const activity = {
id: genId(),
id: null,
actor: fromUrl,
type: "Move",
object: fromUrl,