@plank-cms/plank 0.17.0 → 0.17.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,7 @@
12
12
  href="https://fonts.googleapis.com/css2?family=Google+Sans:ital,opsz,wght@0,17..18,400..700;1,17..18,400..700&display=swap"
13
13
  rel="stylesheet"
14
14
  />
15
- <script type="module" crossorigin src="/admin/assets/index-D7pl1GEz.js"></script>
15
+ <script type="module" crossorigin src="/admin/assets/index-CK0r25Im.js"></script>
16
16
  <link rel="stylesheet" crossorigin href="/admin/assets/index-BUxIRJB1.css">
17
17
  </head>
18
18
  <body>
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import { randomBytes } from "crypto";
7
7
  import { resolve, join } from "path";
8
8
  import fs from "fs-extra";
9
9
  import { execa } from "execa";
10
- var PACKAGE_VERSION = "0.17.0";
10
+ var PACKAGE_VERSION = "0.17.2";
11
11
  function generateSecret() {
12
12
  return randomBytes(32).toString("hex");
13
13
  }
@@ -101,7 +101,7 @@ import { dirname, join as join2, resolve as resolve2 } from "path";
101
101
  async function start() {
102
102
  config({ path: resolve2(process.cwd(), ".env") });
103
103
  process.env.PLANK_ADMIN_DIST = join2(dirname(fileURLToPath(import.meta.url)), "admin");
104
- const { start: startServer } = await import("./server-P4JVP3GT.js");
104
+ const { start: startServer } = await import("./server-AQR4YXZQ.js");
105
105
  await startServer();
106
106
  }
107
107
 
@@ -0,0 +1,30 @@
1
+ -- Backfill editorial workflow columns on all content type tables.
2
+
3
+ DO $$
4
+ DECLARE
5
+ tbl TEXT;
6
+ BEGIN
7
+ FOR tbl IN SELECT table_name FROM plank_content_types LOOP
8
+ IF NOT EXISTS (
9
+ SELECT 1 FROM information_schema.columns
10
+ WHERE table_name = tbl AND column_name = 'editor_id'
11
+ ) THEN
12
+ EXECUTE format('ALTER TABLE %I ADD COLUMN editor_id TEXT REFERENCES plank_users(id) ON DELETE SET NULL', tbl);
13
+ END IF;
14
+
15
+ IF NOT EXISTS (
16
+ SELECT 1 FROM information_schema.columns
17
+ WHERE table_name = tbl AND column_name = 'review_locked_by_editor'
18
+ ) THEN
19
+ EXECUTE format('ALTER TABLE %I ADD COLUMN review_locked_by_editor BOOLEAN NOT NULL DEFAULT FALSE', tbl);
20
+ END IF;
21
+
22
+ IF NOT EXISTS (
23
+ SELECT 1 FROM information_schema.columns
24
+ WHERE table_name = tbl AND column_name = 'review_rejected'
25
+ ) THEN
26
+ EXECUTE format('ALTER TABLE %I ADD COLUMN review_rejected BOOLEAN NOT NULL DEFAULT FALSE', tbl);
27
+ END IF;
28
+ END LOOP;
29
+ END;
30
+ $$;
@@ -84,13 +84,17 @@ async function appliedMigrations(client) {
84
84
  return new Set(rows.map((r2) => r2.filename));
85
85
  }
86
86
  async function seedDefaultRoles(client) {
87
- const { rows } = await client.query("SELECT COUNT(*) as count FROM plank_roles");
88
- if (parseInt(rows[0].count) > 0)
89
- return;
87
+ let created = 0;
90
88
  for (const [name, permissions] of Object.entries(DEFAULT_ROLE_PERMISSIONS)) {
91
- await client.query("INSERT INTO plank_roles (id, name, permissions) VALUES ($1, $2, $3)", [createId(), name, JSON.stringify(permissions)]);
89
+ const result = await client.query(`
90
+ INSERT INTO plank_roles (id, name, permissions)
91
+ VALUES ($1, $2, $3)
92
+ ON CONFLICT (name) DO NOTHING
93
+ `, [createId(), name, JSON.stringify(permissions)]);
94
+ created += result.rowCount ?? 0;
92
95
  }
93
- console.log("[plank/db] Seeded default roles.");
96
+ if (created > 0)
97
+ console.log(`[plank/db] Seeded missing default roles: ${created}.`);
94
98
  }
95
99
  async function migrate() {
96
100
  const client = await pool_default.connect();
@@ -296,6 +300,9 @@ async function createTable(contentType) {
296
300
  ` published_at TIMESTAMP,`,
297
301
  ` scheduled_for TIMESTAMP,`,
298
302
  ` created_by TEXT REFERENCES plank_users(id) ON DELETE SET NULL,`,
303
+ ` editor_id TEXT REFERENCES plank_users(id) ON DELETE SET NULL,`,
304
+ ` review_locked_by_editor BOOLEAN NOT NULL DEFAULT FALSE,`,
305
+ ` review_rejected BOOLEAN NOT NULL DEFAULT FALSE,`,
299
306
  ` created_at TIMESTAMP NOT NULL DEFAULT NOW(),`,
300
307
  ` updated_at TIMESTAMP NOT NULL DEFAULT NOW()`,
301
308
  `)`
@@ -417,6 +424,27 @@ async function syncAllTables() {
417
424
  } catch {
418
425
  }
419
426
  }
427
+ if (!existingColumns.has("editor_id")) {
428
+ try {
429
+ await pool_default.query(`ALTER TABLE ${quotedTableName} ADD COLUMN IF NOT EXISTS editor_id TEXT REFERENCES plank_users(id) ON DELETE SET NULL`);
430
+ existingColumns.add("editor_id");
431
+ } catch {
432
+ }
433
+ }
434
+ if (!existingColumns.has("review_locked_by_editor")) {
435
+ try {
436
+ await pool_default.query(`ALTER TABLE ${quotedTableName} ADD COLUMN IF NOT EXISTS review_locked_by_editor BOOLEAN NOT NULL DEFAULT FALSE`);
437
+ existingColumns.add("review_locked_by_editor");
438
+ } catch {
439
+ }
440
+ }
441
+ if (!existingColumns.has("review_rejected")) {
442
+ try {
443
+ await pool_default.query(`ALTER TABLE ${quotedTableName} ADD COLUMN IF NOT EXISTS review_rejected BOOLEAN NOT NULL DEFAULT FALSE`);
444
+ existingColumns.add("review_rejected");
445
+ } catch {
446
+ }
447
+ }
420
448
  for (const field of ct.fields) {
421
449
  if (!isVirtualRelation(field) && !existingColumns.has(field.name)) {
422
450
  assertSafeIdentifier(field.name);
@@ -2624,8 +2652,13 @@ async function register(req, res) {
2624
2652
  const { email, password } = parsed.data;
2625
2653
  const hashed = await bcrypt.hash(password, 12);
2626
2654
  const { rows: roleRows } = await pool_default.query("SELECT id, name FROM plank_roles WHERE name = $1", ["Super Admin"]);
2655
+ const superAdminRole = roleRows[0];
2656
+ if (!superAdminRole) {
2657
+ res.status(500).json({ error: "Super Admin role is not configured." });
2658
+ return;
2659
+ }
2627
2660
  const id = createId();
2628
- await pool_default.query("INSERT INTO plank_users (id, email, password, role_id) VALUES ($1, $2, $3, $4)", [id, email, hashed, roleRows[0].id]);
2661
+ await pool_default.query("INSERT INTO plank_users (id, email, password, role_id) VALUES ($1, $2, $3, $4)", [id, email, hashed, superAdminRole.id]);
2629
2662
  res.status(201).json({ id, email });
2630
2663
  }
2631
2664
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plank-cms/plank",
3
- "version": "0.17.0",
3
+ "version": "0.17.2",
4
4
  "description": "Self-hosted headless CMS. Deploy in minutes on your own infrastructure.",
5
5
  "type": "module",
6
6
  "files": [
@@ -55,9 +55,9 @@
55
55
  "devDependencies": {
56
56
  "@types/fs-extra": "^11.0.4",
57
57
  "tsup": "^8.5.0",
58
- "@plank-cms/db": "0.17.0",
59
- "@plank-cms/core": "0.17.0",
60
- "@plank-cms/schema": "0.17.0"
58
+ "@plank-cms/core": "0.17.2",
59
+ "@plank-cms/schema": "0.17.2",
60
+ "@plank-cms/db": "0.17.2"
61
61
  },
62
62
  "scripts": {
63
63
  "build": "tsup",