mirror of
https://github.com/filecoin-project/slate.git
synced 2024-12-26 02:24:44 +03:00
modified backend to recalculate file privacy upon add/remove from public collection
This commit is contained in:
parent
cb697088b0
commit
c86a738266
@ -404,14 +404,6 @@ export const updateFile = async (data) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const toggleFilePrivacy = async (data) => {
|
|
||||||
await Websockets.checkWebsocket();
|
|
||||||
return await returnJSON(`/api/data/toggle-privacy`, {
|
|
||||||
...DEFAULT_OPTIONS,
|
|
||||||
body: JSON.stringify({ data }),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const deleteFiles = async (data) => {
|
export const deleteFiles = async (data) => {
|
||||||
await Websockets.checkWebsocket();
|
await Websockets.checkWebsocket();
|
||||||
return await returnJSON(`/api/data/delete`, {
|
return await returnJSON(`/api/data/delete`, {
|
||||||
|
@ -210,8 +210,8 @@ export default class SidebarCreateSlate extends React.Component {
|
|||||||
marginTop: 12,
|
marginTop: 12,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
All collections are public by default. This means they can be discovered and seen by
|
Public collections can be discovered and seen by anyone on the internet. If you make it
|
||||||
anyone on the internet. If you make it private, only you will be able to see it.
|
private, only you will be able to see it.
|
||||||
</System.P1>
|
</System.P1>
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
name="isPublic"
|
name="isPublic"
|
||||||
|
@ -25,9 +25,8 @@ import getFilesByUserId from "~/node_common/data/methods/get-files-by-user-id";
|
|||||||
import deleteFilesByIds from "~/node_common/data/methods/delete-files-by-ids";
|
import deleteFilesByIds from "~/node_common/data/methods/delete-files-by-ids";
|
||||||
import deleteFilesByUserId from "~/node_common/data/methods/delete-files-by-user-id";
|
import deleteFilesByUserId from "~/node_common/data/methods/delete-files-by-user-id";
|
||||||
import updateFileById from "~/node_common/data/methods/update-file-by-id";
|
import updateFileById from "~/node_common/data/methods/update-file-by-id";
|
||||||
import updateFilePrivacy from "~/node_common/data/methods/update-file-privacy";
|
|
||||||
import updateFilesPublic from "~/node_common/data/methods/update-files-public";
|
|
||||||
import incrementFileSavecount from "~/node_common/data/methods/increment-file-savecount";
|
import incrementFileSavecount from "~/node_common/data/methods/increment-file-savecount";
|
||||||
|
import recalcFilePrivacy from "~/node_common/data/methods/recalc-file-privacy";
|
||||||
|
|
||||||
// NOTE(martina):
|
// NOTE(martina):
|
||||||
// Like postgres queries
|
// Like postgres queries
|
||||||
@ -121,9 +120,8 @@ export {
|
|||||||
deleteFilesByIds,
|
deleteFilesByIds,
|
||||||
deleteFilesByUserId,
|
deleteFilesByUserId,
|
||||||
updateFileById,
|
updateFileById,
|
||||||
updateFilePrivacy,
|
|
||||||
updateFilesPublic,
|
|
||||||
incrementFileSavecount,
|
incrementFileSavecount,
|
||||||
|
recalcFilePrivacy,
|
||||||
// NOTE(martina): Like postgres queries
|
// NOTE(martina): Like postgres queries
|
||||||
createLike,
|
createLike,
|
||||||
deleteLikeByFile,
|
deleteLikeByFile,
|
||||||
|
42
node_common/data/methods/recalc-file-privacy.js
Normal file
42
node_common/data/methods/recalc-file-privacy.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { runQuery } from "~/node_common/data/utilities";
|
||||||
|
|
||||||
|
export default async ({ fileId }) => {
|
||||||
|
return await runQuery({
|
||||||
|
label: "RECALC_FILE_PRIVACY",
|
||||||
|
queryFn: async (DB) => {
|
||||||
|
const slateIds = `(SELECT ?? FROM ?? WHERE ?? = ?)`;
|
||||||
|
const slateIdsFields = ["slateId", "slate_files", "fileId", fileId];
|
||||||
|
|
||||||
|
const filePrivacy = `(SELECT EXISTS (SELECT * FROM ?? JOIN ?? ON ?? = ?? WHERE ?? = ?))`;
|
||||||
|
const filePrivacyFields = [
|
||||||
|
"slates",
|
||||||
|
"slate_ids",
|
||||||
|
"slates.id",
|
||||||
|
"slate_ids.slateId",
|
||||||
|
"isPublic",
|
||||||
|
true,
|
||||||
|
];
|
||||||
|
|
||||||
|
const update = `UPDATE ?? SET ?? = ${filePrivacy} WHERE ?? = ?`;
|
||||||
|
const updateFields = ["files", "isPublic", ...filePrivacyFields, "id", fileId];
|
||||||
|
|
||||||
|
const updatedFile = await DB.raw(`WITH ?? AS ${slateIds} ${update} RETURNING *`, [
|
||||||
|
"slate_ids",
|
||||||
|
...slateIdsFields,
|
||||||
|
...updateFields,
|
||||||
|
]);
|
||||||
|
let rows = updatedFile.rows;
|
||||||
|
if (rows?.length) {
|
||||||
|
return rows.first();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
errorFn: async (e) => {
|
||||||
|
return {
|
||||||
|
error: true,
|
||||||
|
decorator: "RECALC_FILE_PRIVACY",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
@ -6,6 +6,8 @@ import * as Social from "~/node_common/social";
|
|||||||
import * as Logging from "~/common/logging";
|
import * as Logging from "~/common/logging";
|
||||||
import * as ArrayUtilities from "~/node_common/array-utilities";
|
import * as ArrayUtilities from "~/node_common/array-utilities";
|
||||||
import * as Monitor from "~/node_common/monitor";
|
import * as Monitor from "~/node_common/monitor";
|
||||||
|
import * as Arrays from "~/common/arrays";
|
||||||
|
import * as SearchManager from "~/node_common/managers/search";
|
||||||
|
|
||||||
import crypto from "crypto";
|
import crypto from "crypto";
|
||||||
import JWT from "jsonwebtoken";
|
import JWT from "jsonwebtoken";
|
||||||
@ -285,3 +287,35 @@ export const addToSlate = async ({ slate, files, user, saveCopy = false }) => {
|
|||||||
|
|
||||||
return { added: response.length };
|
return { added: response.length };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const removeFromPublicCollectionUpdatePrivacy = async ({ files }) => {
|
||||||
|
let targetFiles = Arrays.filterPublic(files);
|
||||||
|
let madePrivate = [];
|
||||||
|
for (let file of targetFiles) {
|
||||||
|
let updatedFile = await Data.recalcFilePrivacy({ fileId: file.id });
|
||||||
|
if (!updatedFile) continue;
|
||||||
|
if (file.isPublic && !updatedFile.isPublic) {
|
||||||
|
madePrivate.push(updatedFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (madePrivate.length) {
|
||||||
|
SearchManager.updateFile(madePrivate, "REMOVE");
|
||||||
|
}
|
||||||
|
return madePrivate;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addToPublicCollectionUpdatePrivacy = async ({ files }) => {
|
||||||
|
let targetFiles = Arrays.filterPrivate(files);
|
||||||
|
let madePublic = [];
|
||||||
|
for (let file of targetFiles) {
|
||||||
|
let updatedFile = await Data.recalcFilePrivacy({ fileId: file.id });
|
||||||
|
if (!updatedFile) continue;
|
||||||
|
if (!file.isPublic && updatedFile.isPublic) {
|
||||||
|
madePublic.push(updatedFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (madePublic.length) {
|
||||||
|
SearchManager.updateFile(madePublic, "ADD");
|
||||||
|
}
|
||||||
|
return madePublic;
|
||||||
|
};
|
||||||
|
@ -35,20 +35,7 @@ export default async (req, res) => {
|
|||||||
SearchManager.updateSlate(slate, "REMOVE");
|
SearchManager.updateSlate(slate, "REMOVE");
|
||||||
|
|
||||||
if (slate.isPublic) {
|
if (slate.isPublic) {
|
||||||
//NOTE(martina): if any of the files in it are now private (because they are no longer in any public slates) remove them from search
|
Utilities.removeFromPublicCollectionUpdatePrivacy({ files: slate.objects });
|
||||||
const files = slate.objects;
|
|
||||||
|
|
||||||
const publicFiles = await Data.getFilesByIds({
|
|
||||||
ids: files.map((file) => file.id),
|
|
||||||
publicOnly: true,
|
|
||||||
});
|
|
||||||
const publicIds = publicFiles.map((file) => file.id);
|
|
||||||
|
|
||||||
let privateFiles = files.filter((file) => !publicIds.includes(file.id));
|
|
||||||
|
|
||||||
if (privateFiles.length) {
|
|
||||||
SearchManager.updateFile(privateFiles, "REMOVE");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).send({ decorator: "SERVER_DELETE_SLATE", error: false });
|
return res.status(200).send({ decorator: "SERVER_DELETE_SLATE", error: false });
|
||||||
|
@ -20,7 +20,7 @@ export default async (req, res) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const slate = await Data.getSlateById({ id: req.body.data.slateId });
|
const slate = await Data.getSlateById({ id: req.body.data.slateId, includeFiles: true });
|
||||||
|
|
||||||
if (!slate) {
|
if (!slate) {
|
||||||
return res.status(404).send({
|
return res.status(404).send({
|
||||||
@ -46,18 +46,7 @@ export default async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (slate.isPublic) {
|
if (slate.isPublic) {
|
||||||
const publicFiles = await Data.getFilesByIds({ ids: fileIds, publicOnly: true });
|
Utilities.removeFromPublicCollectionUpdatePrivacy({ files: slate.objects });
|
||||||
const publicIds = publicFiles.map((file) => file.id);
|
|
||||||
|
|
||||||
let privateFiles = fileIds
|
|
||||||
.filter((id) => !publicIds.includes(id))
|
|
||||||
.map((id) => {
|
|
||||||
return { id };
|
|
||||||
});
|
|
||||||
|
|
||||||
if (privateFiles.length) {
|
|
||||||
SearchManager.updateFile(privateFiles, "REMOVE");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewerManager.hydratePartial(id, { slates: true });
|
ViewerManager.hydratePartial(id, { slates: true });
|
||||||
|
@ -48,28 +48,6 @@ export default async (req, res) => {
|
|||||||
.status(500)
|
.status(500)
|
||||||
.send({ decorator: "SERVER_UPDATE_SLATE_UPDATE_PRIVACY_FAILED", error: true });
|
.send({ decorator: "SERVER_UPDATE_SLATE_UPDATE_PRIVACY_FAILED", error: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!updates.isPublic) {
|
|
||||||
//NOTE(martina): if any of the files in it are now private (because they are no longer in any public slates) remove them from search
|
|
||||||
const files = slate.objects;
|
|
||||||
|
|
||||||
const publicFiles = await Data.getFilesByIds({
|
|
||||||
ids: files.map((file) => file.id),
|
|
||||||
publicOnly: true,
|
|
||||||
});
|
|
||||||
const publicIds = publicFiles.map((file) => file.id);
|
|
||||||
|
|
||||||
let privateFiles = files.filter((file) => !publicIds.includes(file.id));
|
|
||||||
|
|
||||||
if (privateFiles.length) {
|
|
||||||
SearchManager.updateFile(privateFiles, "REMOVE");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//NOTE(martina): make sure all the now-public files are in search if they weren't already
|
|
||||||
const files = slate.objects;
|
|
||||||
|
|
||||||
SearchManager.updateFile(files, "ADD");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updates.data.name && updates.data.name !== slate.data.name) {
|
if (updates.data.name && updates.data.name !== slate.data.name) {
|
||||||
@ -111,8 +89,12 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
if (slate.isPublic && !updates.isPublic) {
|
if (slate.isPublic && !updates.isPublic) {
|
||||||
SearchManager.updateSlate(response, "REMOVE");
|
SearchManager.updateSlate(response, "REMOVE");
|
||||||
|
|
||||||
|
Utilities.removeFromPublicCollectionUpdatePrivacy({ files: slate.objects });
|
||||||
} else if (!slate.isPublic && updates.isPublic) {
|
} else if (!slate.isPublic && updates.isPublic) {
|
||||||
SearchManager.updateSlate(response, "ADD");
|
SearchManager.updateSlate(response, "ADD");
|
||||||
|
|
||||||
|
Utilities.addToPublicCollectionUpdatePrivacy({ files: slate.objects });
|
||||||
} else {
|
} else {
|
||||||
SearchManager.updateSlate(response, "EDIT");
|
SearchManager.updateSlate(response, "EDIT");
|
||||||
}
|
}
|
||||||
|
@ -59,28 +59,6 @@ export default async (req, res) => {
|
|||||||
if (privacyResponse.error) {
|
if (privacyResponse.error) {
|
||||||
return res.status(500).send({ decorator: "UPDATE_COLLECTION_PRIVACY_FAILED", error: true });
|
return res.status(500).send({ decorator: "UPDATE_COLLECTION_PRIVACY_FAILED", error: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!updates.isPublic) {
|
|
||||||
//NOTE(martina): if any of the files in it are now private (because they are no longer in any public slates) remove them from search
|
|
||||||
const files = slate.objects;
|
|
||||||
|
|
||||||
const publicFiles = await Data.getFilesByIds({
|
|
||||||
ids: files.map((file) => file.id),
|
|
||||||
publicOnly: true,
|
|
||||||
});
|
|
||||||
const publicIds = publicFiles.map((file) => file.id);
|
|
||||||
|
|
||||||
let privateFiles = files.filter((file) => !publicIds.includes(file.id));
|
|
||||||
|
|
||||||
if (privateFiles.length) {
|
|
||||||
SearchManager.updateFile(privateFiles, "REMOVE");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//NOTE(martina): make sure all the now-public files are in search if they weren't already
|
|
||||||
const files = slate.objects;
|
|
||||||
|
|
||||||
SearchManager.updateFile(files, "ADD");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updates.data.name && updates.data.name !== slate.data.name) {
|
if (updates.data.name && updates.data.name !== slate.data.name) {
|
||||||
@ -118,8 +96,10 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
if (slate.isPublic && !updates.isPublic) {
|
if (slate.isPublic && !updates.isPublic) {
|
||||||
SearchManager.updateSlate(updatedSlate, "REMOVE");
|
SearchManager.updateSlate(updatedSlate, "REMOVE");
|
||||||
|
Utilities.removeFromPublicCollectionUpdatePrivacy({ files: slate.objects });
|
||||||
} else if (!slate.isPublic && updates.isPublic) {
|
} else if (!slate.isPublic && updates.isPublic) {
|
||||||
SearchManager.updateSlate(updatedSlate, "ADD");
|
SearchManager.updateSlate(updatedSlate, "ADD");
|
||||||
|
Utilities.addToPublicCollectionUpdatePrivacy({ files: slate.objects });
|
||||||
} else {
|
} else {
|
||||||
SearchManager.updateSlate(updatedSlate, "EDIT");
|
SearchManager.updateSlate(updatedSlate, "EDIT");
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ export default async (req, res) => {
|
|||||||
//NOTE(martina): cleans the input to remove fields they should not be changing like ownerId, createdAt, filename, size, type etc.
|
//NOTE(martina): cleans the input to remove fields they should not be changing like ownerId, createdAt, filename, size, type etc.
|
||||||
let updates = {
|
let updates = {
|
||||||
id: req.body.data.id,
|
id: req.body.data.id,
|
||||||
isPublic: req.body.data.isPublic,
|
|
||||||
data: {
|
data: {
|
||||||
name: req.body.data.data?.name,
|
name: req.body.data.data?.name,
|
||||||
body: req.body.data.data?.body,
|
body: req.body.data.data?.body,
|
||||||
@ -34,24 +33,6 @@ export default async (req, res) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof updates.isPublic !== "undefined" && updates.isPublic !== file.isPublic) {
|
|
||||||
let response = await Data.updateFilePrivacy({
|
|
||||||
ownerId: file.ownerId,
|
|
||||||
id: updates.id,
|
|
||||||
isPublic: updates.isPublic,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response || response.error) {
|
|
||||||
return res.status(500).send({ decorator: "UPDATE_FILE_PRIVACY_FAILED", error: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.isPublic) {
|
|
||||||
SearchManager.updateFile(response, "ADD");
|
|
||||||
} else {
|
|
||||||
SearchManager.updateFile(response, "REMOVE");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let response = await Data.updateFileById(updates);
|
let response = await Data.updateFileById(updates);
|
||||||
|
|
||||||
if (!response || response.error) {
|
if (!response || response.error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user