UNPKG

@directus/api

Version:

Directus is a real-time API and App dashboard for managing SQL database content

1,530 lines (1,528 loc) 27.6 kB
import { merge, uniq } from "lodash-es"; //#region src/database/migrations/20201029C-remove-system-fields.ts const defaults = { collection: null, field: null, special: null, interface: null, options: null, display: null, display_options: null, locked: false, readonly: false, hidden: false, sort: null, width: "full", group: null, translations: null, note: null }; const systemFields = [ { collection: "directus_collections", field: "collection_divider", special: "alias", interface: "divider", options: { icon: "box", title: "Collection Setup", color: "#2F80ED" }, locked: true, sort: 1, width: "full" }, { collection: "directus_collections", field: "collection", interface: "text-input", options: { font: "monospace" }, locked: true, readonly: true, sort: 2, width: "half" }, { collection: "directus_collections", field: "icon", interface: "icon", options: null, locked: true, sort: 3, width: "half" }, { collection: "directus_collections", field: "note", interface: "text-input", options: { placeholder: "A description of this collection..." }, locked: true, sort: 4, width: "full" }, { collection: "directus_collections", field: "display_template", interface: "display-template", options: { collectionField: "collection" }, locked: true, sort: 5, width: "full" }, { collection: "directus_collections", field: "hidden", special: "boolean", interface: "toggle", options: { label: "Hide within the App" }, locked: true, sort: 6, width: "half" }, { collection: "directus_collections", field: "singleton", special: "boolean", interface: "toggle", options: { label: "Treat as single object" }, locked: true, sort: 7, width: "half" }, { collection: "directus_collections", field: "translations", special: "json", interface: "repeater", options: { template: "{{ translation }} ({{ language }})", fields: [{ field: "language", name: "Language", type: "string", schema: { default_value: "en-US" }, meta: { interface: "system-language", width: "half" } }, { field: "translation", name: "translation", type: "string", meta: { interface: "text-input", width: "half", options: { placeholder: "Enter a translation..." } } }] }, locked: true, sort: 8, width: "full" }, { collection: "directus_collections", field: "archive_divider", special: "alias", interface: "divider", options: { icon: "archive", title: "Archive", color: "#2F80ED" }, locked: true, sort: 9, width: "full" }, { collection: "directus_collections", field: "archive_field", interface: "field", options: { collectionField: "collection", allowNone: true, placeholder: "Choose a field..." }, locked: true, sort: 10, width: "half" }, { collection: "directus_collections", field: "archive_app_filter", interface: "toggle", special: "boolean", options: { label: "Enable App Archive Filter" }, locked: true, sort: 11, width: "half" }, { collection: "directus_collections", field: "archive_value", interface: "text-input", options: { font: "monospace", iconRight: "archive", placeholder: "Value set when archiving..." }, locked: true, sort: 12, width: "half" }, { collection: "directus_collections", field: "unarchive_value", interface: "text-input", options: { font: "monospace", iconRight: "unarchive", placeholder: "Value set when unarchiving..." }, locked: true, sort: 13, width: "half" }, { collection: "directus_collections", field: "sort_divider", special: "alias", interface: "divider", options: { icon: "sort", title: "Sort", color: "#2F80ED" }, locked: true, sort: 14, width: "full" }, { collection: "directus_collections", field: "sort_field", interface: "field", options: { collectionField: "collection", placeholder: "Choose a field...", typeAllowList: [ "float", "decimal", "integer" ], allowNone: true }, locked: true, sort: 15, width: "half" }, { collection: "directus_roles", field: "id", hidden: true, interface: "text-input", locked: true, special: "uuid" }, { collection: "directus_roles", field: "name", interface: "text-input", options: { placeholder: "The unique name for this role..." }, locked: true, sort: 1, width: "half" }, { collection: "directus_roles", field: "icon", interface: "icon", display: "icon", locked: true, sort: 2, width: "half" }, { collection: "directus_roles", field: "description", interface: "text-input", options: { placeholder: "A description of this role..." }, locked: true, sort: 3, width: "full" }, { collection: "directus_roles", field: "app_access", interface: "toggle", locked: true, special: "boolean", sort: 4, width: "half" }, { collection: "directus_roles", field: "admin_access", interface: "toggle", locked: true, special: "boolean", sort: 5, width: "half" }, { collection: "directus_roles", field: "ip_access", interface: "tags", options: { placeholder: "Add allowed IP addresses, leave empty to allow all..." }, locked: true, special: "csv", sort: 6, width: "full" }, { collection: "directus_roles", field: "enforce_tfa", interface: "toggle", locked: true, sort: 7, special: "boolean", width: "half" }, { collection: "directus_roles", field: "users", interface: "one-to-many", locked: true, special: "o2m", sort: 8, options: { fields: ["first_name", "last_name"] }, width: "full" }, { collection: "directus_roles", field: "module_list", interface: "repeater", locked: true, options: { template: "{{ name }}", addLabel: "Add New Module...", fields: [ { name: "Icon", field: "icon", type: "string", meta: { interface: "icon", width: "half" } }, { name: "Name", field: "name", type: "string", meta: { interface: "text-input", width: "half", options: { iconRight: "title", placeholder: "Enter a title..." } } }, { name: "Link", field: "link", type: "string", meta: { interface: "text-input", width: "full", options: { iconRight: "link", placeholder: "Relative or absolute URL..." } } } ] }, special: "json", sort: 9, width: "full" }, { collection: "directus_roles", field: "collection_list", interface: "repeater", locked: true, options: { template: "{{ group_name }}", addLabel: "Add New Group...", fields: [ { name: "Group Name", field: "group_name", type: "string", meta: { width: "half", interface: "text-input", options: { iconRight: "title", placeholder: "Label this group..." } }, schema: { is_nullable: false } }, { name: "Type", field: "accordion", type: "string", schema: { default_value: "always_open" }, meta: { width: "half", interface: "dropdown", options: { choices: [ { value: "always_open", text: "Always Open" }, { value: "start_open", text: "Start Open" }, { value: "start_collapsed", text: "Start Collapsed" } ] } } }, { name: "Collections", field: "collections", type: "JSON", meta: { interface: "repeater", options: { addLabel: "Add New Collection...", template: "{{ collection }}", fields: [{ name: "Collection", field: "collection", type: "string", meta: { interface: "collection", width: "full" }, schema: { is_nullable: false } }] } } } ] }, special: "json", sort: 10, width: "full" }, { collection: "directus_fields", field: "options", hidden: true, locked: true, special: "json" }, { collection: "directus_fields", field: "display_options", hidden: true, locked: true, special: "json" }, { collection: "directus_fields", field: "locked", hidden: true, locked: true, special: "boolean" }, { collection: "directus_fields", field: "readonly", hidden: true, locked: true, special: "boolean" }, { collection: "directus_fields", field: "hidden", hidden: true, locked: true, special: "boolean" }, { collection: "directus_fields", field: "special", hidden: true, locked: true, special: "csv" }, { collection: "directus_fields", field: "translations", hidden: true, locked: true, special: "json" }, { collection: "directus_users", field: "first_name", interface: "text-input", locked: true, options: { iconRight: "account_circle" }, sort: 1, width: "half" }, { collection: "directus_users", field: "last_name", interface: "text-input", locked: true, options: { iconRight: "account_circle" }, sort: 2, width: "half" }, { collection: "directus_users", field: "email", interface: "text-input", locked: true, options: { iconRight: "email" }, sort: 3, width: "half" }, { collection: "directus_users", field: "password", special: "hash, conceal", interface: "hash", locked: true, options: { iconRight: "lock", masked: true }, sort: 4, width: "half" }, { collection: "directus_users", field: "avatar", interface: "file", locked: true, sort: 5, width: "full" }, { collection: "directus_users", field: "location", interface: "text-input", options: { iconRight: "place" }, sort: 6, width: "half" }, { collection: "directus_users", field: "title", interface: "text-input", options: { iconRight: "work" }, sort: 7, width: "half" }, { collection: "directus_users", field: "description", interface: "textarea", sort: 8, width: "full" }, { collection: "directus_users", field: "tags", interface: "tags", special: "json", sort: 9, width: "full", options: { iconRight: "local_offer" } }, { collection: "directus_users", field: "preferences_divider", interface: "divider", options: { icon: "face", title: "User Preferences", color: "#2F80ED" }, special: "alias", sort: 10, width: "full" }, { collection: "directus_users", field: "language", interface: "dropdown", locked: true, options: { choices: [ { text: "Afrikaans (South Africa)", value: "af-ZA" }, { text: "Arabic (Saudi Arabia)", value: "ar-SA" }, { text: "Catalan (Spain)", value: "ca-ES" }, { text: "Chinese (Simplified)", value: "zh-CN" }, { text: "Czech (Czech Republic)", value: "cs-CZ" }, { text: "Danish (Denmark)", value: "da-DK" }, { text: "Dutch (Netherlands)", value: "nl-NL" }, { text: "English (United States)", value: "en-US" }, { text: "Finnish (Finland)", value: "fi-FI" }, { text: "French (France)", value: "fr-FR" }, { text: "German (Germany)", value: "de-DE" }, { text: "Greek (Greece)", value: "el-GR" }, { text: "Hebrew (Israel)", value: "he-IL" }, { text: "Hungarian (Hungary)", value: "hu-HU" }, { text: "Icelandic (Iceland)", value: "is-IS" }, { text: "Indonesian (Indonesia)", value: "id-ID" }, { text: "Italian (Italy)", value: "it-IT" }, { text: "Japanese (Japan)", value: "ja-JP" }, { text: "Korean (Korea)", value: "ko-KR" }, { text: "Malay (Malaysia)", value: "ms-MY" }, { text: "Norwegian (Norway)", value: "no-NO" }, { text: "Polish (Poland)", value: "pl-PL" }, { text: "Portuguese (Brazil)", value: "pt-BR" }, { text: "Portuguese (Portugal)", value: "pt-PT" }, { text: "Russian (Russian Federation)", value: "ru-RU" }, { text: "Spanish (Spain)", value: "es-ES" }, { text: "Spanish (Latin America)", value: "es-419" }, { text: "Taiwanese Mandarin (Taiwan)", value: "zh-TW" }, { text: "Turkish (Turkey)", value: "tr-TR" }, { text: "Ukrainian (Ukraine)", value: "uk-UA" }, { text: "Vietnamese (Vietnam)", value: "vi-VN" } ] }, sort: 11, width: "half" }, { collection: "directus_users", field: "theme", interface: "dropdown", locked: true, options: { choices: [ { value: "auto", text: "Automatic (Based on System)" }, { value: "light", text: "Light Mode" }, { value: "dark", text: "Dark Mode" } ] }, sort: 12, width: "half" }, { collection: "directus_users", field: "tfa_secret", interface: "tfa-setup", locked: true, special: "conceal", sort: 13, width: "half" }, { collection: "directus_users", field: "admin_divider", interface: "divider", locked: true, options: { icon: "verified_user", title: "Admin Options", color: "#F2994A" }, special: "alias", sort: 14, width: "full" }, { collection: "directus_users", field: "status", interface: "dropdown", locked: true, options: { choices: [ { text: "Draft", value: "draft" }, { text: "Invited", value: "invited" }, { text: "Active", value: "active" }, { text: "Suspended", value: "suspended" }, { text: "Archived", value: "archived" } ] }, sort: 15, width: "half" }, { collection: "directus_users", field: "role", interface: "many-to-one", locked: true, options: { template: "{{ name }}" }, special: "m2o", sort: 16, width: "half" }, { collection: "directus_users", field: "token", interface: "token", locked: true, options: { iconRight: "vpn_key", placeholder: "Enter a secure access token..." }, sort: 17, width: "full" }, { collection: "directus_users", field: "id", special: "uuid", interface: "text-input", locked: true, options: { iconRight: "vpn_key" }, sort: 18, width: "full" }, { collection: "directus_folders", field: "id", interface: "text-input", locked: true, special: "uuid" }, { collection: "directus_files", field: "id", hidden: true, interface: "text-input", locked: true, special: "uuid" }, { collection: "directus_files", field: "title", interface: "text-input", locked: true, options: { iconRight: "title", placeholder: "A unique title..." }, sort: 1, width: "full" }, { collection: "directus_files", field: "description", interface: "textarea", locked: true, sort: 2, width: "full", options: { placeholder: "An optional description..." } }, { collection: "directus_files", field: "tags", interface: "tags", locked: true, options: { iconRight: "local_offer" }, special: "json", sort: 3, width: "full", display: "tags" }, { collection: "directus_files", field: "location", interface: "text-input", locked: true, options: { iconRight: "place", placeholder: "An optional location..." }, sort: 4, width: "half" }, { collection: "directus_files", field: "storage", interface: "text-input", locked: true, options: { iconRight: "storage" }, sort: 5, width: "half", readonly: true }, { collection: "directus_files", field: "storage_divider", interface: "divider", locked: true, options: { icon: "insert_drive_file", title: "File Naming", color: "#2F80ED" }, special: "alias", sort: 6, width: "full" }, { collection: "directus_files", field: "filename_disk", interface: "text-input", locked: true, options: { iconRight: "publish", placeholder: "Name on disk storage..." }, sort: 7, width: "half" }, { collection: "directus_files", field: "filename_download", interface: "text-input", locked: true, options: { iconRight: "get_app", placeholder: "Name when downloading..." }, sort: 8, width: "half" }, { collection: "directus_files", field: "metadata", hidden: true, locked: true, special: "json" }, { collection: "directus_files", field: "type", display: "mime-type" }, { collection: "directus_files", field: "filesize", display: "filesize" }, { collection: "directus_files", field: "modified_by", interface: "user", locked: true, special: "user-updated", width: "half", display: "user" }, { collection: "directus_files", field: "modified_on", interface: "datetime", locked: true, special: "date-updated", width: "half", display: "datetime" }, { collection: "directus_files", field: "created_on", display: "datetime" }, { collection: "directus_files", field: "created_by", display: "user" }, { collection: "directus_permissions", field: "permissions", hidden: true, locked: true, special: "json" }, { collection: "directus_permissions", field: "presets", hidden: true, locked: true, special: "json" }, { collection: "directus_presets", field: "filters", hidden: true, locked: true, special: "json" }, { collection: "directus_presets", field: "layout_query", hidden: true, locked: true, special: "json" }, { collection: "directus_presets", field: "layout_options", hidden: true, locked: true, special: "json" }, { collection: "directus_revisions", field: "data", hidden: true, locked: true, special: "json" }, { collection: "directus_revisions", field: "delta", hidden: true, locked: true, special: "json" }, { collection: "directus_settings", field: "project_name", interface: "text-input", locked: true, options: { iconRight: "title", placeholder: "My project..." }, sort: 1, translations: { language: "en-US", translations: "Name" }, width: "half" }, { collection: "directus_settings", field: "project_url", interface: "text-input", locked: true, options: { iconRight: "link", placeholder: "https://example.com" }, sort: 2, translations: { language: "en-US", translations: "Website" }, width: "half" }, { collection: "directus_settings", field: "project_color", interface: "color", locked: true, note: "Login & Logo Background", sort: 3, translations: { language: "en-US", translations: "Brand Color" }, width: "half" }, { collection: "directus_settings", field: "project_logo", interface: "file", locked: true, note: "White 40x40 SVG/PNG", sort: 4, translations: { language: "en-US", translations: "Brand Logo" }, width: "half" }, { collection: "directus_settings", field: "public_divider", interface: "divider", locked: true, options: { icon: "public", title: "Public Pages", color: "#2F80ED" }, special: "alias", sort: 5, width: "full" }, { collection: "directus_settings", field: "public_foreground", interface: "file", locked: true, sort: 6, translations: { language: "en-US", translations: "Login Foreground" }, width: "half" }, { collection: "directus_settings", field: "public_background", interface: "file", locked: true, sort: 7, translations: { language: "en-US", translations: "Login Background" }, width: "half" }, { collection: "directus_settings", field: "public_note", interface: "textarea", locked: true, options: { placeholder: "A short, public message that supports markdown formatting..." }, sort: 8, width: "full" }, { collection: "directus_settings", field: "security_divider", interface: "divider", locked: true, options: { icon: "security", title: "Security", color: "#2F80ED" }, special: "alias", sort: 9, width: "full" }, { collection: "directus_settings", field: "auth_password_policy", interface: "dropdown", locked: true, options: { choices: [ { value: null, text: "None – Not Recommended" }, { value: "/^.{8,}$/", text: "Weak – Minimum 8 Characters" }, { value: "/(?=^.{8,}$)(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()_+}{';'?>.<,])(?!.*\\s).*$/", text: "Strong – Upper / Lowercase / Numbers / Special" } ] }, sort: 10, width: "half" }, { collection: "directus_settings", field: "auth_login_attempts", interface: "numeric", locked: true, options: { iconRight: "lock" }, sort: 11, width: "half" }, { collection: "directus_settings", field: "files_divider", interface: "divider", locked: true, options: { icon: "storage", title: "Files & Thumbnails", color: "#2F80ED" }, special: "alias", sort: 12, width: "full" }, { collection: "directus_settings", field: "storage_asset_presets", interface: "repeater", locked: true, options: { fields: [ { field: "key", name: "Key", type: "string", schema: { is_nullable: false }, meta: { interface: "slug", options: { onlyOnCreate: false }, width: "half" } }, { field: "fit", name: "Fit", type: "string", schema: { is_nullable: false }, meta: { interface: "dropdown", options: { choices: [{ value: "contain", text: "Contain (preserve aspect ratio)" }, { value: "cover", text: "Cover (forces exact size)" }] }, width: "half" } }, { field: "width", name: "Width", type: "integer", schema: { is_nullable: false }, meta: { interface: "numeric", width: "half" } }, { field: "height", name: "Height", type: "integer", schema: { is_nullable: false }, meta: { interface: "numeric", width: "half" } }, { field: "quality", type: "integer", name: "Quality", schema: { default_value: 80, is_nullable: false }, meta: { interface: "slider", options: { max: 100, min: 0, step: 1 }, width: "full" } } ], template: "{{key}}" }, special: "json", sort: 13, width: "full" }, { collection: "directus_settings", field: "storage_asset_transform", interface: "dropdown", locked: true, options: { choices: [ { value: "all", text: "All" }, { value: "none", text: "None" }, { value: "presets", text: "Presets Only" } ] }, sort: 14, width: "half" }, { collection: "directus_settings", field: "id", hidden: true, locked: true }, { collection: "directus_settings", field: "overrides_divider", interface: "divider", locked: true, options: { icon: "brush", title: "App Overrides", color: "#2F80ED" }, special: "alias", sort: 15, width: "full" }, { collection: "directus_settings", field: "custom_css", interface: "code", locked: true, options: { language: "css", lineNumber: true }, sort: 16, width: "full" }, { collection: "directus_webhooks", field: "id", hidden: true, locked: true }, { collection: "directus_webhooks", field: "name", interface: "text-input", locked: true, options: { iconRight: "title" }, sort: 1, width: "full" }, { collection: "directus_webhooks", field: "method", interface: "dropdown", display: "labels", display_options: { defaultBackground: "#ECEFF1", choices: null, format: false }, locked: true, options: { choices: ["GET", "POST"] }, sort: 2, width: "half" }, { collection: "directus_webhooks", field: "url", interface: "text-input", locked: true, options: { iconRight: "link" }, sort: 3, width: "half" }, { collection: "directus_webhooks", field: "status", interface: "dropdown", display: "labels", display_options: { defaultColor: "#B0BEC5", defaultBackground: "#ECEFF1", showAsDot: true, choices: [{ text: "Active", value: "active", foreground: "#607D8B", background: "#2F80ED" }, { text: "Inactive", value: "inactive", foreground: "#607D8B", background: "#ECEFF1" }] }, locked: true, options: { choices: [{ text: "Active", value: "active" }, { text: "Inactive", value: "inactive" }] }, sort: 4, width: "half" }, { collection: "directus_webhooks", field: "data", interface: "toggle", locked: true, options: { label: "Send Event Data" }, special: "boolean", sort: 5, width: "half" }, { collection: "directus_webhooks", field: "triggers_divider", interface: "divider", options: { icon: "api", title: "Triggers", color: "#2F80ED" }, special: "alias", sort: 6, width: "full" }, { collection: "directus_webhooks", field: "actions", interface: "checkboxes", options: { choices: [ { text: "Create", value: "create" }, { text: "Update", value: "update" }, { text: "Delete", value: "delete" } ] }, special: "csv", sort: 7, width: "full" }, { collection: "directus_webhooks", field: "collections", interface: "collections", special: "csv", sort: 8, width: "full" }, { collection: "directus_activity", field: "action", display: "labels", display_options: { defaultForeground: "#263238", defaultBackground: "#eceff1", choices: [ { text: "Create", value: "create", foreground: "#27ae60", background: "#c9ebd7" }, { text: "Update", value: "update", foreground: "#2f80ed", background: "#cbdffb" }, { text: "Delete", value: "delete", foreground: "#eb5757", background: "#fad5d5" }, { text: "Login", value: "authenticate", foreground: "#9b51e0", background: "#e6d3f7" } ] } }, { collection: "directus_activity", field: "collection", display: "collection", display_options: { icon: true } }, { collection: "directus_activity", field: "timestamp", display: "datetime", options: { relative: true } }, { collection: "directus_activity", field: "user", display: "user" }, { collection: "directus_activity", field: "comment", display: "formatted-text", display_options: { subdued: true } }, { collection: "directus_activity", field: "user_agent", display: "formatted-text", display_options: { font: "monospace" } }, { collection: "directus_activity", field: "ip", display: "formatted-text", display_options: { font: "monospace" } }, { collection: "directus_activity", field: "revisions", interface: "one-to-many", locked: true, special: "o2m", options: { fields: ["collection", "item"] }, width: "full" }, { collection: "directus_relations", field: "one_allowed_collections", locked: true, special: "csv" } ].map((row) => { for (const [key, value] of Object.entries(row)) if (value !== null && (typeof value === "object" || Array.isArray(value))) row[key] = JSON.stringify(value); return merge({}, defaults, row); }); async function up(knex) { const fieldKeys = uniq(systemFields.map((field) => field.field)); await knex("directus_fields").delete().where("collection", "like", "directus_%").whereIn("field", fieldKeys); } async function down(knex) { await knex.insert(systemFields).into("directus_fields"); } //#endregion export { down, up };