mirror of
https://iceshrimp.dev/crimekillz/trashposs
synced 2024-11-22 00:43:49 +01:00
[backend/frontend] Disable post imports for security reasons
This commit is contained in:
parent
3dff9eac78
commit
f14c5ed4ef
@ -11,41 +11,5 @@ export async function importCkPost(
|
|||||||
job: Bull.Job<DbUserImportMastoPostJobData>,
|
job: Bull.Job<DbUserImportMastoPostJobData>,
|
||||||
done: any,
|
done: any,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const user = await Users.findOneBy({ id: job.data.user.id });
|
|
||||||
if (user == null) {
|
|
||||||
done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const post = job.data.post;
|
|
||||||
if (post.replyId != null) {
|
|
||||||
done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (post.renoteId != null) {
|
|
||||||
done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (post.visibility !== "public") {
|
|
||||||
done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { text, cw, localOnly, createdAt } = Post.parse(post);
|
|
||||||
const note = await create(user, {
|
|
||||||
createdAt: createdAt,
|
|
||||||
files: undefined,
|
|
||||||
poll: undefined,
|
|
||||||
text: text || undefined,
|
|
||||||
reply: null,
|
|
||||||
renote: null,
|
|
||||||
cw: cw,
|
|
||||||
localOnly,
|
|
||||||
visibility: "hidden",
|
|
||||||
visibleUsers: [],
|
|
||||||
channel: null,
|
|
||||||
apMentions: new Array(0),
|
|
||||||
apHashtags: undefined,
|
|
||||||
apEmojis: undefined,
|
|
||||||
});
|
|
||||||
logger.succ("Imported");
|
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
@ -15,77 +15,5 @@ export async function importMastoPost(
|
|||||||
job: Bull.Job<DbUserImportMastoPostJobData>,
|
job: Bull.Job<DbUserImportMastoPostJobData>,
|
||||||
done: any,
|
done: any,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const user = await Users.findOneBy({ id: job.data.user.id });
|
|
||||||
if (user == null) {
|
|
||||||
done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const post = job.data.post;
|
|
||||||
let reply: Note | null = null;
|
|
||||||
job.progress(20);
|
|
||||||
if (post.object.inReplyTo != null) {
|
|
||||||
reply = await resolveNote(post.object.inReplyTo);
|
|
||||||
}
|
|
||||||
job.progress(40);
|
|
||||||
if (post.directMessage) {
|
|
||||||
done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (job.data.signatureCheck) {
|
|
||||||
if (!post.signature) {
|
|
||||||
done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
job.progress(60);
|
|
||||||
let text;
|
|
||||||
try {
|
|
||||||
text = await htmlToMfm(post.object.content, post.object.tag);
|
|
||||||
} catch (e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
job.progress(80);
|
|
||||||
|
|
||||||
let files: DriveFile[] = (post.object.attachment || [])
|
|
||||||
.map((x: any) => x?.driveFile)
|
|
||||||
.filter((x: any) => x);
|
|
||||||
|
|
||||||
if (files.length == 0) {
|
|
||||||
const urls = post.object.attachment
|
|
||||||
.map((x: any) => x.url)
|
|
||||||
.filter((x: String) => x.startsWith("http"));
|
|
||||||
files = [];
|
|
||||||
for (const url of urls) {
|
|
||||||
try {
|
|
||||||
const file = await uploadFromUrl({
|
|
||||||
url: url,
|
|
||||||
user: user,
|
|
||||||
});
|
|
||||||
files.push(file);
|
|
||||||
} catch (e) {
|
|
||||||
logger.error(`Skipped adding file to drive: ${url}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const note = await create(user, {
|
|
||||||
createdAt: new Date(post.object.published),
|
|
||||||
files: files.length == 0 ? undefined : files,
|
|
||||||
poll: undefined,
|
|
||||||
text: text || undefined,
|
|
||||||
reply,
|
|
||||||
renote: null,
|
|
||||||
cw: post.object.sensitive ? post.object.summary : undefined,
|
|
||||||
localOnly: false,
|
|
||||||
visibility: "hidden",
|
|
||||||
visibleUsers: [],
|
|
||||||
channel: null,
|
|
||||||
apMentions: new Array(0),
|
|
||||||
apHashtags: undefined,
|
|
||||||
apEmojis: undefined,
|
|
||||||
});
|
|
||||||
job.progress(100);
|
|
||||||
done();
|
done();
|
||||||
|
|
||||||
logger.succ("Imported");
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
import define from "../../define.js";
|
import define from "../../define.js";
|
||||||
import { createImportPostsJob } from "@/queue/index.js";
|
|
||||||
import { ApiError } from "../../error.js";
|
import { ApiError } from "../../error.js";
|
||||||
import { DriveFiles } from "@/models/index.js";
|
|
||||||
import { DAY } from "@/const.js";
|
import { DAY } from "@/const.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
secure: true,
|
secure: true,
|
||||||
@ -26,7 +23,7 @@ export const meta = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
importsDisabled: {
|
importsDisabled: {
|
||||||
message: "Post imports are disabled.",
|
message: "Post imports are disabled for security reasons.",
|
||||||
code: "IMPORTS_DISABLED",
|
code: "IMPORTS_DISABLED",
|
||||||
id: " bc9227e4-fb82-11ed-be56-0242ac120002",
|
id: " bc9227e4-fb82-11ed-be56-0242ac120002",
|
||||||
},
|
},
|
||||||
@ -43,13 +40,5 @@ export const paramDef = {
|
|||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
const file = await DriveFiles.findOneBy({ id: ps.fileId });
|
throw new ApiError(meta.errors.importsDisabled);
|
||||||
|
|
||||||
const instanceMeta = await fetchMeta();
|
|
||||||
if (instanceMeta.experimentalFeatures?.postImports === false)
|
|
||||||
throw new ApiError(meta.errors.importsDisabled);
|
|
||||||
|
|
||||||
if (file == null) throw new ApiError(meta.errors.noSuchFile);
|
|
||||||
if (file.size === 0) throw new ApiError(meta.errors.emptyFile);
|
|
||||||
createImportPostsJob(user, file.id, ps.signatureCheck);
|
|
||||||
});
|
});
|
||||||
|
@ -16,24 +16,6 @@
|
|||||||
{{ i18n.ts.export }}</MkButton
|
{{ i18n.ts.export }}</MkButton
|
||||||
>
|
>
|
||||||
</FormFolder>
|
</FormFolder>
|
||||||
<FormFolder class="_formBlock">
|
|
||||||
<template #label>{{ i18n.ts.import }}</template>
|
|
||||||
<template #icon
|
|
||||||
><i class="ph-upload-simple ph-bold ph-lg"></i
|
|
||||||
></template>
|
|
||||||
<FormRadios v-model="importType" class="_formBlock">
|
|
||||||
<option value="iceshrimp">Iceshrimp/Misskey</option>
|
|
||||||
<option value="mastodon">Mastodon/Akkoma/Pleroma</option>
|
|
||||||
</FormRadios>
|
|
||||||
<MkButton
|
|
||||||
primary
|
|
||||||
:class="$style.button"
|
|
||||||
inline
|
|
||||||
@click="importPosts($event)"
|
|
||||||
><i class="ph-upload-simple ph-bold ph-lg"></i>
|
|
||||||
{{ i18n.ts.import }}</MkButton
|
|
||||||
>
|
|
||||||
</FormFolder>
|
|
||||||
</FormSection>
|
</FormSection>
|
||||||
<FormSection>
|
<FormSection>
|
||||||
<template #label>{{
|
<template #label>{{
|
||||||
@ -213,16 +195,6 @@ const exportNotes = () => {
|
|||||||
os.api("i/export-notes", {}).then(onExportSuccess).catch(onError);
|
os.api("i/export-notes", {}).then(onExportSuccess).catch(onError);
|
||||||
};
|
};
|
||||||
|
|
||||||
const importPosts = async (ev) => {
|
|
||||||
const file = await selectFile(ev.currentTarget ?? ev.target);
|
|
||||||
os.api("i/import-posts", {
|
|
||||||
fileId: file.id,
|
|
||||||
signatureCheck: false,
|
|
||||||
})
|
|
||||||
.then(onImportSuccess)
|
|
||||||
.catch(onError);
|
|
||||||
};
|
|
||||||
|
|
||||||
const exportFollowing = () => {
|
const exportFollowing = () => {
|
||||||
os.api("i/export-following", {
|
os.api("i/export-following", {
|
||||||
excludeMuting: excludeMutingUsers.value,
|
excludeMuting: excludeMutingUsers.value,
|
||||||
|
Loading…
Reference in New Issue
Block a user