integrate migration ui and api backend

This commit is contained in:
cutestnekoaqua 2022-12-12 01:42:40 +01:00
parent f4625da99a
commit 0219ed2c1d
6 changed files with 153 additions and 11 deletions

View file

@ -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",

View file

@ -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\"",

View file

@ -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],

View file

@ -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;
});

View file

@ -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);
}

View file

@ -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,
}); });
} }