integrate migration ui and api backend
This commit is contained in:
parent
06746e73b5
commit
91e39fa829
|
@ -19,6 +19,7 @@
|
||||||
"start:test": "yarn workspace backend run start:test",
|
"start:test": "yarn workspace backend run start:test",
|
||||||
"init": "yarn migrate",
|
"init": "yarn migrate",
|
||||||
"migrate": "yarn workspace backend run migrate",
|
"migrate": "yarn workspace backend run migrate",
|
||||||
|
"revertMig": "yarn workspace backend run revertMig",
|
||||||
"migrateandstart": "yarn migrate && yarn start",
|
"migrateandstart": "yarn migrate && yarn start",
|
||||||
"gulp": "gulp build",
|
"gulp": "gulp build",
|
||||||
"watch": "yarn dev",
|
"watch": "yarn dev",
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
"start": "node ./built/index.js",
|
"start": "node ./built/index.js",
|
||||||
"start:test": "NODE_ENV=test node ./built/index.js",
|
"start:test": "NODE_ENV=test node ./built/index.js",
|
||||||
"migrate": "typeorm migration:run -d ormconfig.js",
|
"migrate": "typeorm migration:run -d ormconfig.js",
|
||||||
|
"revertMig": "typeorm migration:revert -d ormconfig.js",
|
||||||
"build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json",
|
"build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json",
|
||||||
"watch": "node watch.mjs",
|
"watch": "node watch.mjs",
|
||||||
"lint": "eslint --quiet \"src/**/*.ts\"",
|
"lint": "eslint --quiet \"src/**/*.ts\"",
|
||||||
|
|
|
@ -325,6 +325,10 @@ import * as ep___users_stats from './endpoints/users/stats.js';
|
||||||
import * as ep___fetchRss from './endpoints/fetch-rss.js';
|
import * as ep___fetchRss from './endpoints/fetch-rss.js';
|
||||||
import * as ep___admin_driveCapOverride from './endpoints/admin/drive-capacity-override.js';
|
import * as ep___admin_driveCapOverride from './endpoints/admin/drive-capacity-override.js';
|
||||||
|
|
||||||
|
//Calckey Move
|
||||||
|
import * as ep___i_move from './endpoints/i/move.js';
|
||||||
|
import * as ep___i_known_as from './endpoints/i/known-as.js';
|
||||||
|
|
||||||
const eps = [
|
const eps = [
|
||||||
['admin/meta', ep___admin_meta],
|
['admin/meta', ep___admin_meta],
|
||||||
['admin/abuse-user-reports', ep___admin_abuseUserReports],
|
['admin/abuse-user-reports', ep___admin_abuseUserReports],
|
||||||
|
@ -489,6 +493,8 @@ const eps = [
|
||||||
['hashtags/trend', ep___hashtags_trend],
|
['hashtags/trend', ep___hashtags_trend],
|
||||||
['hashtags/users', ep___hashtags_users],
|
['hashtags/users', ep___hashtags_users],
|
||||||
['i', ep___i],
|
['i', ep___i],
|
||||||
|
['i/known-as', ep___i_known_as],
|
||||||
|
['i/move', ep___i_move],
|
||||||
['i/2fa/done', ep___i_2fa_done],
|
['i/2fa/done', ep___i_2fa_done],
|
||||||
['i/2fa/key-done', ep___i_2fa_keyDone],
|
['i/2fa/key-done', ep___i_2fa_keyDone],
|
||||||
['i/2fa/password-less', ep___i_2fa_passwordLess],
|
['i/2fa/password-less', ep___i_2fa_passwordLess],
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
import { In } from 'typeorm';
|
||||||
|
import { User } from '@/models/entities/user.js';
|
||||||
|
import { Users, DriveFiles, Notes, Channels, Blockings } from '@/models/index.js';
|
||||||
|
import { resolveUser } from '@/remote/resolve-user.js';
|
||||||
|
import { ApiError } from '../../error.js';
|
||||||
|
import acceptAllFollowRequests from '@/services/following/requests/accept-all.js';
|
||||||
|
import { publishToFollowers } from '@/services/i/update.js';
|
||||||
|
import { apiLogger } from '../../logger.js';
|
||||||
|
import { publishMainStream, publishUserEvent } from '@/services/stream.js';
|
||||||
|
import define from '../../define.js';
|
||||||
|
import { DAY } from '@/const.js';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
tags: ['users'],
|
||||||
|
|
||||||
|
secure: true,
|
||||||
|
requireCredential: true,
|
||||||
|
|
||||||
|
limit: {
|
||||||
|
duration: DAY,
|
||||||
|
max: 30,
|
||||||
|
},
|
||||||
|
|
||||||
|
errors: {
|
||||||
|
noSuchUser: {
|
||||||
|
message: 'No such user.',
|
||||||
|
code: 'NO_SUCH_USER',
|
||||||
|
id: 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5',
|
||||||
|
},
|
||||||
|
notRemote: {
|
||||||
|
message: 'User not remote.',
|
||||||
|
code: 'NOT_REMOTE',
|
||||||
|
id: '4362f8dc-731f-4ad8-a694-be2a88922a24',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const paramDef = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
alsoKnownAs: { type: 'string' },
|
||||||
|
},
|
||||||
|
required: ['alsoKnownAs'],
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-default-export
|
||||||
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
|
|
||||||
|
if(!ps.alsoKnownAs) throw new ApiError(meta.errors.noSuchUser);
|
||||||
|
|
||||||
|
let unfiltered: string = ps.alsoKnownAs;
|
||||||
|
|
||||||
|
if(unfiltered.startsWith('@')) unfiltered = unfiltered.substring(1);
|
||||||
|
if(!unfiltered.includes('@')) throw new ApiError(meta.errors.notRemote);
|
||||||
|
|
||||||
|
let userAddress: string[] = unfiltered.split("@");
|
||||||
|
|
||||||
|
const knownAs: User = await resolveUser(userAddress[0], userAddress[1]).catch(e => {
|
||||||
|
apiLogger.warn(`failed to resolve remote user: ${e}`);
|
||||||
|
throw new ApiError(meta.errors.noSuchUser);
|
||||||
|
});
|
||||||
|
|
||||||
|
const updates = {} as Partial<User>;
|
||||||
|
|
||||||
|
if(!knownAs.uri) knownAs.uri = "";
|
||||||
|
updates.alsoKnownAs = [knownAs.uri];
|
||||||
|
|
||||||
|
await Users.update(user.id, updates);
|
||||||
|
|
||||||
|
const iObj = await Users.pack<true, true>(user.id, user, {
|
||||||
|
detail: true,
|
||||||
|
includeSecrets: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Publish meUpdated event
|
||||||
|
publishMainStream(user.id, 'meUpdated', iObj);
|
||||||
|
|
||||||
|
if (user.isLocked === false) {
|
||||||
|
acceptAllFollowRequests(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
publishToFollowers(user.id);
|
||||||
|
|
||||||
|
return iObj;
|
||||||
|
});
|
|
@ -2,11 +2,15 @@ import { In } from 'typeorm';
|
||||||
import { User } from '@/models/entities/user.js';
|
import { User } from '@/models/entities/user.js';
|
||||||
import { Users, DriveFiles, Notes, Channels, Blockings } from '@/models/index.js';
|
import { Users, DriveFiles, Notes, Channels, Blockings } from '@/models/index.js';
|
||||||
import { ApiError } from '../../error.js';
|
import { ApiError } from '../../error.js';
|
||||||
|
import { resolveUser } from '@/remote/resolve-user.js';
|
||||||
import define from '../../define.js';
|
import define from '../../define.js';
|
||||||
import { DAY } from '@/const.js';
|
import { DAY } from '@/const.js';
|
||||||
|
import DeliverManager from '@/remote/activitypub/deliver-manager.js';
|
||||||
|
import { renderActivity } from '@/remote/activitypub/renderer/index.js';
|
||||||
|
import { apiLogger } from '../../logger.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['notes'],
|
tags: ['users'],
|
||||||
|
|
||||||
secure: true,
|
secure: true,
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
@ -27,19 +31,64 @@ export const meta = {
|
||||||
code: 'REMOTE_ACCOUNT_FORBIDS',
|
code: 'REMOTE_ACCOUNT_FORBIDS',
|
||||||
id: 'b5c90186-4ab0-49c8-9bba-a1f766282ba4',
|
id: 'b5c90186-4ab0-49c8-9bba-a1f766282ba4',
|
||||||
},
|
},
|
||||||
|
notRemote: {
|
||||||
|
message: 'User not remote.',
|
||||||
|
code: 'NOT_REMOTE',
|
||||||
|
id: '4362f8dc-731f-4ad8-a694-be2a88922a24',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const paramDef = {
|
export const paramDef = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
alsoKnownAs: { type: 'string' },
|
moveToAccount: { type: 'string' },
|
||||||
},
|
},
|
||||||
required: ['alsoKnownAs'],
|
required: ['moveToAccount'],
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-default-export
|
// eslint-disable-next-line import/no-default-export
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
// TODO
|
|
||||||
return;
|
if(!ps.moveToAccount) throw new ApiError(meta.errors.noSuchMoveTarget);
|
||||||
|
|
||||||
|
let unfiltered: string = ps.moveToAccount;
|
||||||
|
|
||||||
|
if(unfiltered.startsWith('@')) unfiltered = unfiltered.substring(1);
|
||||||
|
if(!unfiltered.includes('@')) throw new ApiError(meta.errors.notRemote);
|
||||||
|
let userAddress: string[] = unfiltered.split("@");
|
||||||
|
|
||||||
|
const moveTo: User = await resolveUser(userAddress[0], userAddress[1]).catch(e => {
|
||||||
|
apiLogger.warn(`failed to resolve remote user: ${e}`);
|
||||||
|
throw new ApiError(meta.errors.noSuchMoveTarget);
|
||||||
|
});
|
||||||
|
|
||||||
|
let allowed = false;
|
||||||
|
|
||||||
|
moveTo.alsoKnownAs?.array.forEach(element => {
|
||||||
|
if(user.uri?.includes(element)) allowed = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!allowed || !moveTo.uri || !user.uri) throw new ApiError(meta.errors.remoteAccountForbids);
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const moveAct = await moveActivity(moveTo.uri!, user.uri!);
|
||||||
|
const dm = new DeliverManager(user, moveAct);
|
||||||
|
dm.addFollowersRecipe();
|
||||||
|
dm.execute();
|
||||||
|
})();
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function moveActivity(to: string, from: string) {
|
||||||
|
|
||||||
|
const activity = {
|
||||||
|
id: `foo`,
|
||||||
|
actor: from,
|
||||||
|
type: 'Move',
|
||||||
|
object: from,
|
||||||
|
target: to,
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
return renderActivity(activity);
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="_formRoot">
|
<div class="_formRoot">
|
||||||
<FormSection>
|
<FormSection>
|
||||||
<template #label>{{ i18n.ts.moveTo }}</template>
|
<template #label>{{ i18n.ts.moveTo }}</template>
|
||||||
<FormInput v-model="alsoKnownAs" class="_formBlock">
|
<FormInput v-model="moveToAccount" class="_formBlock">
|
||||||
<template #prefix><i class="ph-airplane-takeoff-bold ph-lg"></i></template>
|
<template #prefix><i class="ph-airplane-takeoff-bold ph-lg"></i></template>
|
||||||
<template #label>{{ i18n.ts.moveToLabel }}</template>
|
<template #label>{{ i18n.ts.moveToLabel }}</template>
|
||||||
</FormInput>
|
</FormInput>
|
||||||
|
@ -30,19 +30,19 @@ import * as os from '@/os';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||||
|
|
||||||
let alsoKnownAs = $ref('');
|
let moveToAccount = $ref('');
|
||||||
let accountAlias = $ref('');
|
let accountAlias = $ref('');
|
||||||
|
|
||||||
async function save(): Promise<void> {
|
async function save(): Promise<void> {
|
||||||
// os.apiWithDialog('i/move', {
|
os.apiWithDialog('i/known-as', {
|
||||||
// alsoKnownAs: alsoKnownAs,
|
alsoKnownAs: accountAlias,
|
||||||
// });
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function move(): Promise<void> {
|
async function move(): Promise<void> {
|
||||||
// TODO: PROMPT FOR CONFIRMATION
|
// TODO: PROMPT FOR CONFIRMATION
|
||||||
os.api('i/move', {
|
os.api('i/move', {
|
||||||
alsoKnownAs: alsoKnownAs,
|
moveToAccount: moveToAccount,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue