@tanglemedia/directus-core-settings 0.0.1
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.
- package/README.md +46 -0
- package/dist/index.js +34 -0
- package/migrations/20260101A-tngl_directus_core-~-create-website-role.mjs +22 -0
- package/migrations/20260101B-tngl_directus_core-~-create-staff-role.mjs +22 -0
- package/migrations/20260101C-tngl_directus_core-~-create-website-policy.mjs +25 -0
- package/migrations/20260101D-tngl_directus_core-~-create-staff-policy.mjs +25 -0
- package/migrations/20260101E-tngl_directus_core-~-add-site-user.mjs +30 -0
- package/migrations/20260101F-tngl_directus_core-~-add-staff-user.mjs +30 -0
- package/migrations/20260101G-tngl_directus_core-~-add-site-access.mjs +26 -0
- package/migrations/20260101H-tngl_directus_core-~-add-staff-access.mjs +26 -0
- package/migrations/helpers/generator.mjs +19 -0
- package/migrations/helpers/permission.mjs +45 -0
- package/migrations/helpers/policy.mjs +12 -0
- package/migrations/helpers/role.mjs +12 -0
- package/package.json +47 -0
- package/src/index.js +8 -0
- package/src/shared/utility/migrations.js +30 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { generateUUIDv4 } from "./helpers/generator.mjs";
|
|
2
|
+
|
|
3
|
+
export async function up(knex) {
|
|
4
|
+
const roleInfo = {
|
|
5
|
+
name: "Website",
|
|
6
|
+
icon: "public",
|
|
7
|
+
description: "Role meant for website access so that it can build public pages.",
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const existingRole = await knex("directus_roles")
|
|
11
|
+
.where({ name: "Website" })
|
|
12
|
+
.first();
|
|
13
|
+
if (!existingRole) {
|
|
14
|
+
await knex("directus_roles").insert({...roleInfo, id: generateUUIDv4()});
|
|
15
|
+
} else {
|
|
16
|
+
await knex("directus_roles").where({ name: "Website" }).update(roleInfo);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function down(knex) {
|
|
21
|
+
await knex("directus_roles").where({ name: "Website" }).del();
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { generateUUIDv4 } from "./helpers/generator.mjs";
|
|
2
|
+
|
|
3
|
+
export async function up(knex) {
|
|
4
|
+
const roleInfo = {
|
|
5
|
+
name: "Staff",
|
|
6
|
+
icon: "people",
|
|
7
|
+
description: "Role meant for staff access to the admin panel.",
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const existingRole = await knex("directus_roles")
|
|
11
|
+
.where({ name: "Staff" })
|
|
12
|
+
.first();
|
|
13
|
+
if (!existingRole) {
|
|
14
|
+
await knex("directus_roles").insert({...roleInfo, id: generateUUIDv4()});
|
|
15
|
+
} else {
|
|
16
|
+
await knex("directus_roles").where({ name: "Staff" }).update(roleInfo);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function down(knex) {
|
|
21
|
+
await knex("directus_roles").where({ name: "Staff" }).del();
|
|
22
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { generateUUIDv4 } from "./helpers/generator.mjs";
|
|
2
|
+
|
|
3
|
+
export async function up(knex) {
|
|
4
|
+
const policyInfo = {
|
|
5
|
+
name: "Website",
|
|
6
|
+
icon: "public",
|
|
7
|
+
description: "Access the data to use to prebuild data into the static Website",
|
|
8
|
+
enforce_tfa: 0,
|
|
9
|
+
admin_access: 0,
|
|
10
|
+
app_access: 0,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const existingPolicy = await knex("directus_policies")
|
|
14
|
+
.where({ name: "Website" })
|
|
15
|
+
.first();
|
|
16
|
+
if (!existingPolicy) {
|
|
17
|
+
await knex("directus_policies").insert({...policyInfo, id: generateUUIDv4()});
|
|
18
|
+
} else {
|
|
19
|
+
await knex("directus_policies").where({ name: "Website" }).update(policyInfo);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function down(knex) {
|
|
24
|
+
await knex("directus_policies").where({ name: "Website" }).del();
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { generateUUIDv4 } from "./helpers/generator.mjs";
|
|
2
|
+
|
|
3
|
+
export async function up(knex) {
|
|
4
|
+
const policyInfo = {
|
|
5
|
+
name: "Staff",
|
|
6
|
+
icon: "people",
|
|
7
|
+
description: "Access the data to use within the Directus Admin App for staff users",
|
|
8
|
+
enforce_tfa: 0,
|
|
9
|
+
admin_access: 0,
|
|
10
|
+
app_access: 1,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const existingPolicy = await knex("directus_policies")
|
|
14
|
+
.where({ name: "Staff" })
|
|
15
|
+
.first();
|
|
16
|
+
if (!existingPolicy) {
|
|
17
|
+
await knex("directus_policies").insert({...policyInfo, id: generateUUIDv4()});
|
|
18
|
+
} else {
|
|
19
|
+
await knex("directus_policies").where({ name: "Staff" }).update(policyInfo);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function down(knex) {
|
|
24
|
+
await knex("directus_policies").where({ name: "Staff" }).del();
|
|
25
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { generateUUIDv4, generateUserToken } from "./helpers/generator.mjs";
|
|
2
|
+
import { getRoleID } from "./helpers/role.mjs";
|
|
3
|
+
|
|
4
|
+
export async function up(knex) {
|
|
5
|
+
const role = await getRoleID(knex, "Website");
|
|
6
|
+
const userInfo = {
|
|
7
|
+
first_name: "Site",
|
|
8
|
+
last_name: "User",
|
|
9
|
+
email: "site@tangle.ca",
|
|
10
|
+
description: "$site",
|
|
11
|
+
role: role,
|
|
12
|
+
status: "active",
|
|
13
|
+
provider: "default",
|
|
14
|
+
token: generateUserToken(),
|
|
15
|
+
};
|
|
16
|
+
const existingUser = await knex("directus_users")
|
|
17
|
+
.where({ description: "$site" })
|
|
18
|
+
.first();
|
|
19
|
+
if (!existingUser) {
|
|
20
|
+
await knex("directus_users").insert({ ...userInfo, id: generateUUIDv4() });
|
|
21
|
+
} else {
|
|
22
|
+
await knex("directus_users")
|
|
23
|
+
.where({ description: "$site" })
|
|
24
|
+
.update(userInfo);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function down(knex) {
|
|
29
|
+
await knex("directus_users").where({ description: "$site" }).del();
|
|
30
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { generateUUIDv4, generateUserToken } from "./helpers/generator.mjs";
|
|
2
|
+
import { getRoleID } from "./helpers/role.mjs";
|
|
3
|
+
|
|
4
|
+
export async function up(knex) {
|
|
5
|
+
const role = await getRoleID(knex, "Staff");
|
|
6
|
+
const userInfo = {
|
|
7
|
+
first_name: process.env.ADMIN_CLIENT_NAME || "Staff",
|
|
8
|
+
last_name: null,
|
|
9
|
+
email: process.env.ADMIN_CLIENT_EMAIL || "staff@tangle.ca",
|
|
10
|
+
description: "$staff",
|
|
11
|
+
role: role,
|
|
12
|
+
status: "active",
|
|
13
|
+
provider: "default",
|
|
14
|
+
token: generateUserToken(),
|
|
15
|
+
};
|
|
16
|
+
const existingUser = await knex("directus_users")
|
|
17
|
+
.where({ description: "$staff" })
|
|
18
|
+
.first();
|
|
19
|
+
if (!existingUser) {
|
|
20
|
+
await knex("directus_users").insert({ ...userInfo, id: generateUUIDv4() });
|
|
21
|
+
} else {
|
|
22
|
+
await knex("directus_users")
|
|
23
|
+
.where({ description: "$staff" })
|
|
24
|
+
.update(userInfo);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function down(knex) {
|
|
29
|
+
await knex("directus_users").where({ description: "$staff" }).del();
|
|
30
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { generateUUIDv4 } from "./helpers/generator.mjs";
|
|
2
|
+
import { getPolicyID } from "./helpers/policy.mjs";
|
|
3
|
+
import { getRoleID } from "./helpers/role.mjs";
|
|
4
|
+
|
|
5
|
+
export async function up(knex) {
|
|
6
|
+
const role = await getRoleID(knex, "Website");
|
|
7
|
+
const policy = await getPolicyID(knex, "Website");
|
|
8
|
+
const accessInfo = {
|
|
9
|
+
role: role,
|
|
10
|
+
policy: policy,
|
|
11
|
+
};
|
|
12
|
+
const existingAccess = await knex("directus_access")
|
|
13
|
+
.where({ role: role, policy: policy })
|
|
14
|
+
.first();
|
|
15
|
+
if (!existingAccess) {
|
|
16
|
+
await knex("directus_access").insert({ ...accessInfo, id: generateUUIDv4() });
|
|
17
|
+
} else {
|
|
18
|
+
await knex("directus_access")
|
|
19
|
+
.where({ role: role, policy: policy })
|
|
20
|
+
.update(accessInfo);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function down(knex) {
|
|
25
|
+
await knex("directus_access").where({ role: role, policy: policy }).del();
|
|
26
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { generateUUIDv4 } from "./helpers/generator.mjs";
|
|
2
|
+
import { getPolicyID } from "./helpers/policy.mjs";
|
|
3
|
+
import { getRoleID } from "./helpers/role.mjs";
|
|
4
|
+
|
|
5
|
+
export async function up(knex) {
|
|
6
|
+
const role = await getRoleID(knex, "Staff");
|
|
7
|
+
const policy = await getPolicyID(knex, "Staff");
|
|
8
|
+
const accessInfo = {
|
|
9
|
+
role: role,
|
|
10
|
+
policy: policy,
|
|
11
|
+
};
|
|
12
|
+
const existingAccess = await knex("directus_access")
|
|
13
|
+
.where({ role: role, policy: policy })
|
|
14
|
+
.first();
|
|
15
|
+
if (!existingAccess) {
|
|
16
|
+
await knex("directus_access").insert({ ...accessInfo, id: generateUUIDv4() });
|
|
17
|
+
} else {
|
|
18
|
+
await knex("directus_access")
|
|
19
|
+
.where({ role: role, policy: policy })
|
|
20
|
+
.update(accessInfo);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function down(knex) {
|
|
25
|
+
await knex("directus_access").where({ role: role, policy: policy }).del();
|
|
26
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export function generateUUIDv4() {
|
|
5
|
+
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
|
|
6
|
+
(c ^ ((crypto.randomBytes(1)[0] & 15) >> (c / 4))).toString(16),
|
|
7
|
+
);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function generateUserToken() {
|
|
11
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
|
|
12
|
+
const length = 32;
|
|
13
|
+
const bytes = crypto.randomBytes(length);
|
|
14
|
+
let result = "";
|
|
15
|
+
for (let i = 0; i < length; i++) {
|
|
16
|
+
result += chars[bytes[i] % chars.length];
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { getPolicyID } from "./policy.mjs";
|
|
2
|
+
|
|
3
|
+
export function permissionExists(knex, collection, action, policy) {
|
|
4
|
+
return knex("directus_permissions")
|
|
5
|
+
.where({ collection: collection, action: action, policy: policy })
|
|
6
|
+
.first();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function insertPermission(knex, info, fields = "*") {
|
|
10
|
+
await knex("directus_permissions").insert({
|
|
11
|
+
...info,
|
|
12
|
+
fields: fields,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function updatePermission(knex, info, fields = "*") {
|
|
17
|
+
await knex("directus_permissions")
|
|
18
|
+
.where(info)
|
|
19
|
+
.update({
|
|
20
|
+
...info,
|
|
21
|
+
fields: fields,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function createPermission(knex, collectionName, policyName, actions) {
|
|
26
|
+
const policy = await getPolicyID(knex, policyName);
|
|
27
|
+
|
|
28
|
+
for (const action of actions) {
|
|
29
|
+
const permissionInfo = {
|
|
30
|
+
collection: collectionName,
|
|
31
|
+
action: action,
|
|
32
|
+
policy: policy,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const exist = await knex("directus_permissions")
|
|
36
|
+
.where(permissionInfo)
|
|
37
|
+
.first();
|
|
38
|
+
|
|
39
|
+
if (!exist) {
|
|
40
|
+
await insertPermission(knex, permissionInfo);
|
|
41
|
+
} else {
|
|
42
|
+
await updatePermission(knex, permissionInfo);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tanglemedia/directus-core-settings",
|
|
3
|
+
"description": "Directus core settings",
|
|
4
|
+
"author": {
|
|
5
|
+
"name": "Tangle Media, Inc."
|
|
6
|
+
},
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"icon": "extension",
|
|
9
|
+
"version": "0.0.1",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"directus",
|
|
12
|
+
"directus-extension",
|
|
13
|
+
"directus-extension-hook",
|
|
14
|
+
"core-settings-collection",
|
|
15
|
+
"directus-collection",
|
|
16
|
+
"collection"
|
|
17
|
+
],
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"src",
|
|
21
|
+
"migrations",
|
|
22
|
+
"scripts",
|
|
23
|
+
"docs"
|
|
24
|
+
],
|
|
25
|
+
"directus:extension": {
|
|
26
|
+
"type": "hook",
|
|
27
|
+
"path": "dist/index.js",
|
|
28
|
+
"source": "src/index.js",
|
|
29
|
+
"host": "^10.10.1 || ^11.0.0",
|
|
30
|
+
"sandbox": {
|
|
31
|
+
"enabled": false,
|
|
32
|
+
"requestedScopes": {
|
|
33
|
+
"log": {}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@directus/extensions-sdk": "13.0.0",
|
|
39
|
+
"@types/node": "^22.10.7",
|
|
40
|
+
"typescript": "^5.7.3"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "directus-extension build",
|
|
44
|
+
"dev": "directus-extension build -w --no-minify",
|
|
45
|
+
"link": "directus-extension link"
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const { defineHook } = require("@directus/extensions-sdk");
|
|
2
|
+
const moveMigrationScripts = require("./shared/utility/migrations");
|
|
3
|
+
|
|
4
|
+
module.exports = defineHook(
|
|
5
|
+
async ({ action, init }, { services, database, getSchema, logger }) => {
|
|
6
|
+
await moveMigrationScripts(logger);
|
|
7
|
+
},
|
|
8
|
+
);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const { exec } = require("child_process");
|
|
2
|
+
const { promisify } = require("util");
|
|
3
|
+
const path = require("node:path");
|
|
4
|
+
const execPromise = promisify(exec);
|
|
5
|
+
|
|
6
|
+
const moveMigrationScripts = async (logger) => {
|
|
7
|
+
const ROOT = process.cwd();
|
|
8
|
+
const EXTENSION_PATH = __dirname;
|
|
9
|
+
|
|
10
|
+
let migrationSrcPath = EXTENSION_PATH.split("/");
|
|
11
|
+
migrationSrcPath.pop();
|
|
12
|
+
migrationSrcPath.push("migrations");
|
|
13
|
+
migrationSrcPath = path.join("/", ...migrationSrcPath);
|
|
14
|
+
|
|
15
|
+
let migrationDestPath = ROOT.split("/");
|
|
16
|
+
migrationDestPath.push("migrations");
|
|
17
|
+
migrationDestPath = path.join("/", ...migrationDestPath);
|
|
18
|
+
|
|
19
|
+
// create destination folder
|
|
20
|
+
let { stdout, stderr } = await execPromise(`mkdir -p ${migrationDestPath}`);
|
|
21
|
+
if (stderr) return;
|
|
22
|
+
|
|
23
|
+
// copy files
|
|
24
|
+
({ stdout, stderr } = await execPromise(
|
|
25
|
+
`cp -R "${migrationSrcPath}/." "${migrationDestPath}/"`,
|
|
26
|
+
));
|
|
27
|
+
if (stderr) return;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
module.exports = moveMigrationScripts;
|