fix(custom-widgets): harden v2 authoring
This commit is contained in:
171 files changed
+20311
-50527
No files matched your search
@@ -12,43 +12,27 @@ migrate(
|
||||
if (!users.fields.getByName("displayName"))
|
||||
users.fields.add(new TextField({ name: "displayName", required: true, min: 1, max: 100 }));
|
||||
if (!users.fields.getByName("avatarUrl")) users.fields.add(new URLField({ name: "avatarUrl" }));
|
||||
app.save(users);
|
||||
if (!users.fields.getByName("isAdmin")) users.fields.add(new BoolField({ name: "isAdmin" }));
|
||||
|
||||
const admins = new Collection({
|
||||
type: "base",
|
||||
name: "workshop_admins",
|
||||
listRule: "user = @request.auth.id",
|
||||
viewRule: "user = @request.auth.id",
|
||||
createRule: null,
|
||||
updateRule: null,
|
||||
deleteRule: null,
|
||||
fields: [
|
||||
{ type: "relation", name: "user", required: true, maxSelect: 1, collectionId: users.id, cascadeDelete: true },
|
||||
{ type: "autodate", name: "created", onCreate: true },
|
||||
],
|
||||
});
|
||||
admins.addIndex("idx_workshop_admin_user", true, "user", "");
|
||||
app.save(admins);
|
||||
const adminRule = "@collection.workshop_admins.user ?= @request.auth.id";
|
||||
const adminRule = "@request.auth.isAdmin = true";
|
||||
users.listRule = adminRule;
|
||||
users.viewRule = `id = @request.auth.id || ${adminRule}`;
|
||||
users.updateRule = "id = @request.auth.id";
|
||||
users.updateRule = "id = @request.auth.id && @request.body.isAdmin:isset = false";
|
||||
users.deleteRule = null;
|
||||
app.save(users);
|
||||
|
||||
const submissions = new Collection({
|
||||
type: "base",
|
||||
name: "submissions",
|
||||
listRule: adminRule,
|
||||
listRule: "",
|
||||
viewRule: "",
|
||||
createRule: "@request.auth.id != '' && @request.body.author = @request.auth.id",
|
||||
updateRule: "author = @request.auth.id",
|
||||
updateRule: "author = @request.auth.id && @request.body.author:changed = false",
|
||||
deleteRule: `author = @request.auth.id || ${adminRule}`,
|
||||
fields: [
|
||||
{ type: "text", name: "title", required: true, min: 3, max: 100 },
|
||||
{ type: "text", name: "description", max: 2000 },
|
||||
{ type: "text", name: "content", required: true, max: 1000000 },
|
||||
{ type: "text", name: "contentHash", required: true, max: 64 },
|
||||
{
|
||||
type: "file",
|
||||
name: "screenshots",
|
||||
@@ -58,9 +42,6 @@ migrate(
|
||||
thumbs: ["480x320", "960x640"],
|
||||
},
|
||||
{ type: "relation", name: "author", required: true, maxSelect: 1, collectionId: users.id, cascadeDelete: true },
|
||||
{ type: "text", name: "authorName", required: true, max: 100 },
|
||||
{ type: "number", name: "revision", required: true, onlyInt: true, min: 1 },
|
||||
{ type: "text", name: "changelog", max: 2000 },
|
||||
{ type: "autodate", name: "created", onCreate: true },
|
||||
{ type: "autodate", name: "updated", onCreate: true, onUpdate: true },
|
||||
],
|
||||
@@ -74,8 +55,10 @@ migrate(
|
||||
name: "votes",
|
||||
listRule: "user = @request.auth.id",
|
||||
viewRule: "user = @request.auth.id",
|
||||
createRule: "@request.auth.id != '' && @request.body.user = @request.auth.id",
|
||||
updateRule: "user = @request.auth.id",
|
||||
createRule:
|
||||
"@request.auth.id != '' && @request.body.user = @request.auth.id && (@request.body.value = 1 || @request.body.value = -1)",
|
||||
updateRule:
|
||||
"user = @request.auth.id && @request.body.user:changed = false && @request.body.submission:changed = false && (@request.body.value = 1 || @request.body.value = -1)",
|
||||
deleteRule: "user = @request.auth.id",
|
||||
fields: [
|
||||
{
|
||||
@@ -102,8 +85,8 @@ migrate(
|
||||
listRule: adminRule,
|
||||
viewRule: `reporter = @request.auth.id || ${adminRule}`,
|
||||
createRule: "@request.auth.id != '' && @request.body.reporter = @request.auth.id",
|
||||
updateRule: adminRule,
|
||||
deleteRule: null,
|
||||
updateRule: null,
|
||||
deleteRule: adminRule,
|
||||
fields: [
|
||||
{
|
||||
type: "relation",
|
||||
@@ -129,55 +112,29 @@ migrate(
|
||||
values: ["malicious", "spam", "copyright", "inappropriate", "other"],
|
||||
},
|
||||
{ type: "text", name: "explanation", required: true, min: 3, max: 1000 },
|
||||
{ type: "select", name: "status", required: true, maxSelect: 1, values: ["open", "dismissed"] },
|
||||
{ type: "text", name: "dismissalReason", max: 1000 },
|
||||
{ type: "autodate", name: "created", onCreate: true },
|
||||
{ type: "autodate", name: "updated", onCreate: true, onUpdate: true },
|
||||
],
|
||||
});
|
||||
reports.addIndex("idx_reports_reporter_submission", true, "reporter, submission", "");
|
||||
reports.addIndex("idx_reports_status_created", false, "status, created", "");
|
||||
reports.addIndex("idx_reports_created", false, "created", "");
|
||||
app.save(reports);
|
||||
|
||||
const actions = new Collection({
|
||||
type: "base",
|
||||
name: "workshop_admin_actions",
|
||||
listRule: adminRule,
|
||||
viewRule: adminRule,
|
||||
createRule: null,
|
||||
updateRule: null,
|
||||
deleteRule: null,
|
||||
fields: [
|
||||
{ type: "relation", name: "actor", required: true, maxSelect: 1, collectionId: users.id },
|
||||
{
|
||||
type: "select",
|
||||
name: "action",
|
||||
required: true,
|
||||
maxSelect: 1,
|
||||
values: ["delete_submission", "dismiss_report"],
|
||||
},
|
||||
{ type: "text", name: "submissionId", max: 30 },
|
||||
{ type: "text", name: "reportId", max: 30 },
|
||||
{ type: "text", name: "reason", max: 1000 },
|
||||
{ type: "text", name: "snapshot", max: 100000 },
|
||||
{ type: "autodate", name: "created", onCreate: true },
|
||||
],
|
||||
});
|
||||
actions.addIndex("idx_workshop_admin_actions_created", false, "created", "");
|
||||
app.save(actions);
|
||||
|
||||
const listings = new Collection({
|
||||
type: "view",
|
||||
name: "workshop_listings",
|
||||
listRule: "",
|
||||
viewRule: "",
|
||||
viewQuery: `
|
||||
SELECT s.id, s.title, s.description, s.contentHash, s.screenshots,
|
||||
s.revision, s.changelog, s.author, s.authorName, s.created, s.updated,
|
||||
SELECT s.id, s.title, s.description, s.screenshots, s.author, u.displayName AS authorName,
|
||||
s.created, s.updated,
|
||||
COALESCE(SUM(CASE WHEN v.value = 1 THEN 1 ELSE 0 END), 0) AS upvotes,
|
||||
COALESCE(SUM(CASE WHEN v.value = -1 THEN 1 ELSE 0 END), 0) AS downvotes,
|
||||
COALESCE(SUM(v.value), 0) AS score
|
||||
FROM submissions s LEFT JOIN votes v ON v.submission = s.id GROUP BY s.id
|
||||
FROM submissions s
|
||||
JOIN users u ON u.id = s.author
|
||||
LEFT JOIN votes v ON v.submission = s.id
|
||||
GROUP BY s.id
|
||||
`,
|
||||
});
|
||||
app.save(listings);
|
||||
@@ -195,14 +152,7 @@ migrate(
|
||||
app.save(settings);
|
||||
},
|
||||
(app) => {
|
||||
for (const name of [
|
||||
"workshop_listings",
|
||||
"workshop_admin_actions",
|
||||
"reports",
|
||||
"votes",
|
||||
"submissions",
|
||||
"workshop_admins",
|
||||
]) {
|
||||
for (const name of ["workshop_listings", "reports", "votes", "submissions"]) {
|
||||
try {
|
||||
app.delete(app.findCollectionByNameOrId(name));
|
||||
} catch {}
|
||||
|
||||
Reference in new issue
Block a user