@sonicjs-cms/core 2.0.0-alpha.2 → 2.0.0-alpha.4
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/dist/chunk-3MNMOLSA.js +133 -0
- package/dist/chunk-3MNMOLSA.js.map +1 -0
- package/dist/chunk-5XKH6PBR.js +7026 -0
- package/dist/chunk-5XKH6PBR.js.map +1 -0
- package/dist/chunk-AGOE25LF.cjs +137 -0
- package/dist/chunk-AGOE25LF.cjs.map +1 -0
- package/dist/chunk-B5DU2UAN.cjs +7035 -0
- package/dist/chunk-B5DU2UAN.cjs.map +1 -0
- package/dist/index.cjs +13 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +10 -3
- package/dist/index.js.map +1 -1
- package/dist/routes.cjs +34 -2
- package/dist/routes.js +5 -1
- package/dist/services.cjs +13 -1
- package/dist/services.js +1 -1
- package/migrations/001_initial_schema.sql +198 -0
- package/migrations/002_faq_plugin.sql +86 -0
- package/migrations/003_stage5_enhancements.sql +121 -0
- package/migrations/004_stage6_user_management.sql +183 -0
- package/migrations/005_stage7_workflow_automation.sql +294 -0
- package/migrations/006_plugin_system.sql +155 -0
- package/migrations/007_demo_login_plugin.sql +23 -0
- package/migrations/008_fix_slug_validation.sql +22 -0
- package/migrations/009_system_logging.sql +57 -0
- package/migrations/011_config_managed_collections.sql +14 -0
- package/migrations/012_testimonials_plugin.sql +80 -0
- package/migrations/013_code_examples_plugin.sql +177 -0
- package/migrations/014_fix_plugin_registry.sql +88 -0
- package/migrations/015_add_remaining_plugins.sql +89 -0
- package/migrations/016_remove_duplicate_cache_plugin.sql +17 -0
- package/migrations/017_auth_configurable_fields.sql +49 -0
- package/package.json +1 -1
- package/dist/chunk-4URGXJP7.js +0 -3
- package/dist/chunk-4URGXJP7.js.map +0 -1
- package/dist/chunk-ALTMI5Y2.cjs +0 -4
- package/dist/chunk-ALTMI5Y2.cjs.map +0 -1
- package/dist/chunk-BOLQHE4J.cjs +0 -11
- package/dist/chunk-BOLQHE4J.cjs.map +0 -1
- package/dist/chunk-HD7R6T6I.js +0 -9
- package/dist/chunk-HD7R6T6I.js.map +0 -1
- package/dist/collection-config-FLlGtsh9.d.cts +0 -107
- package/dist/collection-config-FLlGtsh9.d.ts +0 -107
- package/dist/index-BlsY5XNH.d.ts +0 -8333
- package/dist/index-D45jaIlr.d.cts +0 -8333
- package/dist/index.d.cts +0 -136
- package/dist/index.d.ts +0 -136
- package/dist/middleware.d.cts +0 -206
- package/dist/middleware.d.ts +0 -206
- package/dist/plugin-UzmDImQc.d.cts +0 -357
- package/dist/plugin-UzmDImQc.d.ts +0 -357
- package/dist/plugins.d.cts +0 -330
- package/dist/plugins.d.ts +0 -330
- package/dist/routes.d.cts +0 -17
- package/dist/routes.d.ts +0 -17
- package/dist/services.d.cts +0 -5
- package/dist/services.d.ts +0 -5
- package/dist/templates.d.cts +0 -140
- package/dist/templates.d.ts +0 -140
- package/dist/types.d.cts +0 -41
- package/dist/types.d.ts +0 -41
- package/dist/utils.d.cts +0 -184
- package/dist/utils.d.ts +0 -184
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
-- Stage 5: Advanced Content Management enhancements
|
|
2
|
+
-- Add scheduling and workflow features to content table
|
|
3
|
+
|
|
4
|
+
-- Add content scheduling columns
|
|
5
|
+
ALTER TABLE content ADD COLUMN scheduled_publish_at INTEGER;
|
|
6
|
+
ALTER TABLE content ADD COLUMN scheduled_unpublish_at INTEGER;
|
|
7
|
+
|
|
8
|
+
-- Add workflow and review columns
|
|
9
|
+
ALTER TABLE content ADD COLUMN review_status TEXT DEFAULT 'none'; -- none, pending, approved, rejected
|
|
10
|
+
ALTER TABLE content ADD COLUMN reviewer_id TEXT REFERENCES users(id);
|
|
11
|
+
ALTER TABLE content ADD COLUMN reviewed_at INTEGER;
|
|
12
|
+
ALTER TABLE content ADD COLUMN review_notes TEXT;
|
|
13
|
+
|
|
14
|
+
-- Add content metadata
|
|
15
|
+
ALTER TABLE content ADD COLUMN meta_title TEXT;
|
|
16
|
+
ALTER TABLE content ADD COLUMN meta_description TEXT;
|
|
17
|
+
ALTER TABLE content ADD COLUMN featured_image_id TEXT REFERENCES media(id);
|
|
18
|
+
ALTER TABLE content ADD COLUMN content_type TEXT DEFAULT 'standard'; -- standard, template, component
|
|
19
|
+
|
|
20
|
+
-- Create content_fields table for dynamic field definitions
|
|
21
|
+
CREATE TABLE IF NOT EXISTS content_fields (
|
|
22
|
+
id TEXT PRIMARY KEY,
|
|
23
|
+
collection_id TEXT NOT NULL REFERENCES collections(id),
|
|
24
|
+
field_name TEXT NOT NULL,
|
|
25
|
+
field_type TEXT NOT NULL, -- text, richtext, number, boolean, date, select, media, relationship
|
|
26
|
+
field_label TEXT NOT NULL,
|
|
27
|
+
field_options TEXT, -- JSON for select options, validation rules, etc.
|
|
28
|
+
field_order INTEGER NOT NULL DEFAULT 0,
|
|
29
|
+
is_required INTEGER NOT NULL DEFAULT 0,
|
|
30
|
+
is_searchable INTEGER NOT NULL DEFAULT 0,
|
|
31
|
+
created_at INTEGER NOT NULL,
|
|
32
|
+
updated_at INTEGER NOT NULL,
|
|
33
|
+
UNIQUE(collection_id, field_name)
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
-- Create content_relationships table for content relationships
|
|
37
|
+
CREATE TABLE IF NOT EXISTS content_relationships (
|
|
38
|
+
id TEXT PRIMARY KEY,
|
|
39
|
+
source_content_id TEXT NOT NULL REFERENCES content(id),
|
|
40
|
+
target_content_id TEXT NOT NULL REFERENCES content(id),
|
|
41
|
+
relationship_type TEXT NOT NULL, -- references, tags, categories
|
|
42
|
+
created_at INTEGER NOT NULL,
|
|
43
|
+
UNIQUE(source_content_id, target_content_id, relationship_type)
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
-- Create workflow_templates table for reusable workflows
|
|
47
|
+
CREATE TABLE IF NOT EXISTS workflow_templates (
|
|
48
|
+
id TEXT PRIMARY KEY,
|
|
49
|
+
name TEXT NOT NULL,
|
|
50
|
+
description TEXT,
|
|
51
|
+
collection_id TEXT REFERENCES collections(id), -- null means applies to all collections
|
|
52
|
+
workflow_steps TEXT NOT NULL, -- JSON array of workflow steps
|
|
53
|
+
is_active INTEGER NOT NULL DEFAULT 1,
|
|
54
|
+
created_at INTEGER NOT NULL,
|
|
55
|
+
updated_at INTEGER NOT NULL
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
-- Add indexes for new columns
|
|
59
|
+
CREATE INDEX IF NOT EXISTS idx_content_scheduled_publish ON content(scheduled_publish_at);
|
|
60
|
+
CREATE INDEX IF NOT EXISTS idx_content_scheduled_unpublish ON content(scheduled_unpublish_at);
|
|
61
|
+
CREATE INDEX IF NOT EXISTS idx_content_review_status ON content(review_status);
|
|
62
|
+
CREATE INDEX IF NOT EXISTS idx_content_reviewer ON content(reviewer_id);
|
|
63
|
+
CREATE INDEX IF NOT EXISTS idx_content_content_type ON content(content_type);
|
|
64
|
+
|
|
65
|
+
CREATE INDEX IF NOT EXISTS idx_content_fields_collection ON content_fields(collection_id);
|
|
66
|
+
CREATE INDEX IF NOT EXISTS idx_content_fields_name ON content_fields(field_name);
|
|
67
|
+
CREATE INDEX IF NOT EXISTS idx_content_fields_type ON content_fields(field_type);
|
|
68
|
+
CREATE INDEX IF NOT EXISTS idx_content_fields_order ON content_fields(field_order);
|
|
69
|
+
|
|
70
|
+
CREATE INDEX IF NOT EXISTS idx_content_relationships_source ON content_relationships(source_content_id);
|
|
71
|
+
CREATE INDEX IF NOT EXISTS idx_content_relationships_target ON content_relationships(target_content_id);
|
|
72
|
+
CREATE INDEX IF NOT EXISTS idx_content_relationships_type ON content_relationships(relationship_type);
|
|
73
|
+
|
|
74
|
+
CREATE INDEX IF NOT EXISTS idx_workflow_templates_collection ON workflow_templates(collection_id);
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_workflow_templates_active ON workflow_templates(is_active);
|
|
76
|
+
|
|
77
|
+
-- Insert default workflow template
|
|
78
|
+
INSERT OR IGNORE INTO workflow_templates (
|
|
79
|
+
id, name, description, workflow_steps, is_active, created_at, updated_at
|
|
80
|
+
) VALUES (
|
|
81
|
+
'default-content-workflow',
|
|
82
|
+
'Default Content Workflow',
|
|
83
|
+
'Standard content workflow: Draft → Review → Published',
|
|
84
|
+
'[
|
|
85
|
+
{"step": "draft", "name": "Draft", "description": "Content is being created", "permissions": ["author", "editor", "admin"]},
|
|
86
|
+
{"step": "review", "name": "Under Review", "description": "Content is pending review", "permissions": ["editor", "admin"]},
|
|
87
|
+
{"step": "published", "name": "Published", "description": "Content is live", "permissions": ["editor", "admin"]},
|
|
88
|
+
{"step": "archived", "name": "Archived", "description": "Content is archived", "permissions": ["admin"]}
|
|
89
|
+
]',
|
|
90
|
+
1,
|
|
91
|
+
strftime('%s', 'now') * 1000,
|
|
92
|
+
strftime('%s', 'now') * 1000
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
-- Insert enhanced field definitions for existing collections
|
|
96
|
+
INSERT OR IGNORE INTO content_fields (
|
|
97
|
+
id, collection_id, field_name, field_type, field_label, field_options, field_order, is_required, is_searchable, created_at, updated_at
|
|
98
|
+
) VALUES
|
|
99
|
+
-- Blog Posts fields
|
|
100
|
+
('blog-title-field', 'blog-posts-collection', 'title', 'text', 'Title', '{"maxLength": 200, "placeholder": "Enter blog post title"}', 1, 1, 1, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
101
|
+
('blog-content-field', 'blog-posts-collection', 'content', 'richtext', 'Content', '{"toolbar": "full", "height": 400}', 2, 1, 1, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
102
|
+
('blog-excerpt-field', 'blog-posts-collection', 'excerpt', 'text', 'Excerpt', '{"maxLength": 500, "rows": 3, "placeholder": "Brief description of the post"}', 3, 0, 1, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
103
|
+
('blog-tags-field', 'blog-posts-collection', 'tags', 'select', 'Tags', '{"multiple": true, "options": ["technology", "business", "tutorial", "news", "update"], "allowCustom": true}', 4, 0, 1, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
104
|
+
('blog-featured-image-field', 'blog-posts-collection', 'featured_image', 'media', 'Featured Image', '{"accept": "image/*", "maxSize": "5MB"}', 5, 0, 0, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
105
|
+
('blog-publish-date-field', 'blog-posts-collection', 'publish_date', 'date', 'Publish Date', '{"format": "YYYY-MM-DD", "defaultToday": true}', 6, 0, 0, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
106
|
+
('blog-featured-field', 'blog-posts-collection', 'is_featured', 'boolean', 'Featured Post', '{"default": false}', 7, 0, 0, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
107
|
+
|
|
108
|
+
-- Pages fields
|
|
109
|
+
('pages-title-field', 'pages-collection', 'title', 'text', 'Title', '{"maxLength": 200, "placeholder": "Enter page title"}', 1, 1, 1, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
110
|
+
('pages-content-field', 'pages-collection', 'content', 'richtext', 'Content', '{"toolbar": "full", "height": 500}', 2, 1, 1, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
111
|
+
('pages-slug-field', 'pages-collection', 'slug', 'text', 'URL Slug', '{"pattern": "^[a-z0-9-]+$", "placeholder": "url-friendly-slug"}', 3, 1, 0, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
112
|
+
('pages-meta-desc-field', 'pages-collection', 'meta_description', 'text', 'Meta Description', '{"maxLength": 160, "rows": 2, "placeholder": "SEO description for search engines"}', 4, 0, 0, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
113
|
+
('pages-template-field', 'pages-collection', 'template', 'select', 'Page Template', '{"options": ["default", "landing", "contact", "about"], "default": "default"}', 5, 0, 0, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
114
|
+
|
|
115
|
+
-- News fields
|
|
116
|
+
('news-title-field', 'news-collection', 'title', 'text', 'Title', '{"maxLength": 200, "placeholder": "Enter news title"}', 1, 1, 1, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
117
|
+
('news-content-field', 'news-collection', 'content', 'richtext', 'Content', '{"toolbar": "news", "height": 400}', 2, 1, 1, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
118
|
+
('news-category-field', 'news-collection', 'category', 'select', 'Category', '{"options": ["technology", "business", "politics", "sports", "entertainment", "health"], "required": true}', 3, 1, 1, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
119
|
+
('news-author-field', 'news-collection', 'author', 'text', 'Author', '{"placeholder": "Author name"}', 4, 1, 1, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
120
|
+
('news-source-field', 'news-collection', 'source', 'text', 'Source', '{"placeholder": "News source"}', 5, 0, 1, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000),
|
|
121
|
+
('news-priority-field', 'news-collection', 'priority', 'select', 'Priority', '{"options": ["low", "normal", "high", "breaking"], "default": "normal"}', 6, 0, 0, strftime('%s', 'now') * 1000, strftime('%s', 'now') * 1000);
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
-- Stage 6: User Management & Permissions enhancements
|
|
2
|
+
-- Enhanced user system with profiles, teams, permissions, and activity logging
|
|
3
|
+
|
|
4
|
+
-- Add user profile and preferences columns
|
|
5
|
+
ALTER TABLE users ADD COLUMN phone TEXT;
|
|
6
|
+
ALTER TABLE users ADD COLUMN bio TEXT;
|
|
7
|
+
ALTER TABLE users ADD COLUMN avatar_url TEXT;
|
|
8
|
+
ALTER TABLE users ADD COLUMN timezone TEXT DEFAULT 'UTC';
|
|
9
|
+
ALTER TABLE users ADD COLUMN language TEXT DEFAULT 'en';
|
|
10
|
+
ALTER TABLE users ADD COLUMN email_notifications INTEGER DEFAULT 1;
|
|
11
|
+
ALTER TABLE users ADD COLUMN theme TEXT DEFAULT 'dark';
|
|
12
|
+
ALTER TABLE users ADD COLUMN two_factor_enabled INTEGER DEFAULT 0;
|
|
13
|
+
ALTER TABLE users ADD COLUMN two_factor_secret TEXT;
|
|
14
|
+
ALTER TABLE users ADD COLUMN password_reset_token TEXT;
|
|
15
|
+
ALTER TABLE users ADD COLUMN password_reset_expires INTEGER;
|
|
16
|
+
ALTER TABLE users ADD COLUMN email_verified INTEGER DEFAULT 0;
|
|
17
|
+
ALTER TABLE users ADD COLUMN email_verification_token TEXT;
|
|
18
|
+
ALTER TABLE users ADD COLUMN invitation_token TEXT;
|
|
19
|
+
ALTER TABLE users ADD COLUMN invited_by TEXT REFERENCES users(id);
|
|
20
|
+
ALTER TABLE users ADD COLUMN invited_at INTEGER;
|
|
21
|
+
ALTER TABLE users ADD COLUMN accepted_invitation_at INTEGER;
|
|
22
|
+
|
|
23
|
+
-- Create teams table for team-based collaboration
|
|
24
|
+
CREATE TABLE IF NOT EXISTS teams (
|
|
25
|
+
id TEXT PRIMARY KEY,
|
|
26
|
+
name TEXT NOT NULL,
|
|
27
|
+
description TEXT,
|
|
28
|
+
slug TEXT NOT NULL UNIQUE,
|
|
29
|
+
owner_id TEXT NOT NULL REFERENCES users(id),
|
|
30
|
+
settings TEXT, -- JSON for team settings
|
|
31
|
+
is_active INTEGER NOT NULL DEFAULT 1,
|
|
32
|
+
created_at INTEGER NOT NULL,
|
|
33
|
+
updated_at INTEGER NOT NULL
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
-- Create team memberships table
|
|
37
|
+
CREATE TABLE IF NOT EXISTS team_memberships (
|
|
38
|
+
id TEXT PRIMARY KEY,
|
|
39
|
+
team_id TEXT NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
|
|
40
|
+
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
41
|
+
role TEXT NOT NULL DEFAULT 'member', -- owner, admin, editor, member, viewer
|
|
42
|
+
permissions TEXT, -- JSON for specific permissions
|
|
43
|
+
joined_at INTEGER NOT NULL,
|
|
44
|
+
updated_at INTEGER NOT NULL,
|
|
45
|
+
UNIQUE(team_id, user_id)
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
-- Create permissions table for granular access control
|
|
49
|
+
CREATE TABLE IF NOT EXISTS permissions (
|
|
50
|
+
id TEXT PRIMARY KEY,
|
|
51
|
+
name TEXT NOT NULL UNIQUE,
|
|
52
|
+
description TEXT,
|
|
53
|
+
category TEXT NOT NULL, -- content, users, collections, media, settings
|
|
54
|
+
created_at INTEGER NOT NULL
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
-- Create role permissions mapping
|
|
58
|
+
CREATE TABLE IF NOT EXISTS role_permissions (
|
|
59
|
+
id TEXT PRIMARY KEY,
|
|
60
|
+
role TEXT NOT NULL,
|
|
61
|
+
permission_id TEXT NOT NULL REFERENCES permissions(id),
|
|
62
|
+
created_at INTEGER NOT NULL,
|
|
63
|
+
UNIQUE(role, permission_id)
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
-- Create user sessions table for better session management
|
|
67
|
+
CREATE TABLE IF NOT EXISTS user_sessions (
|
|
68
|
+
id TEXT PRIMARY KEY,
|
|
69
|
+
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
70
|
+
token_hash TEXT NOT NULL,
|
|
71
|
+
ip_address TEXT,
|
|
72
|
+
user_agent TEXT,
|
|
73
|
+
is_active INTEGER NOT NULL DEFAULT 1,
|
|
74
|
+
expires_at INTEGER NOT NULL,
|
|
75
|
+
created_at INTEGER NOT NULL,
|
|
76
|
+
last_used_at INTEGER
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
-- Create activity log table for audit trails
|
|
80
|
+
CREATE TABLE IF NOT EXISTS activity_logs (
|
|
81
|
+
id TEXT PRIMARY KEY,
|
|
82
|
+
user_id TEXT REFERENCES users(id),
|
|
83
|
+
action TEXT NOT NULL,
|
|
84
|
+
resource_type TEXT, -- users, content, collections, media, etc.
|
|
85
|
+
resource_id TEXT,
|
|
86
|
+
details TEXT, -- JSON with additional details
|
|
87
|
+
ip_address TEXT,
|
|
88
|
+
user_agent TEXT,
|
|
89
|
+
created_at INTEGER NOT NULL
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
-- Create password history table for security
|
|
93
|
+
CREATE TABLE IF NOT EXISTS password_history (
|
|
94
|
+
id TEXT PRIMARY KEY,
|
|
95
|
+
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
96
|
+
password_hash TEXT NOT NULL,
|
|
97
|
+
created_at INTEGER NOT NULL
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
-- Insert default permissions
|
|
101
|
+
INSERT OR IGNORE INTO permissions (id, name, description, category, created_at) VALUES
|
|
102
|
+
('perm_content_create', 'content.create', 'Create new content', 'content', strftime('%s', 'now') * 1000),
|
|
103
|
+
('perm_content_read', 'content.read', 'View content', 'content', strftime('%s', 'now') * 1000),
|
|
104
|
+
('perm_content_update', 'content.update', 'Edit existing content', 'content', strftime('%s', 'now') * 1000),
|
|
105
|
+
('perm_content_delete', 'content.delete', 'Delete content', 'content', strftime('%s', 'now') * 1000),
|
|
106
|
+
('perm_content_publish', 'content.publish', 'Publish/unpublish content', 'content', strftime('%s', 'now') * 1000),
|
|
107
|
+
|
|
108
|
+
('perm_collections_create', 'collections.create', 'Create new collections', 'collections', strftime('%s', 'now') * 1000),
|
|
109
|
+
('perm_collections_read', 'collections.read', 'View collections', 'collections', strftime('%s', 'now') * 1000),
|
|
110
|
+
('perm_collections_update', 'collections.update', 'Edit collections', 'collections', strftime('%s', 'now') * 1000),
|
|
111
|
+
('perm_collections_delete', 'collections.delete', 'Delete collections', 'collections', strftime('%s', 'now') * 1000),
|
|
112
|
+
('perm_collections_fields', 'collections.fields', 'Manage collection fields', 'collections', strftime('%s', 'now') * 1000),
|
|
113
|
+
|
|
114
|
+
('perm_media_upload', 'media.upload', 'Upload media files', 'media', strftime('%s', 'now') * 1000),
|
|
115
|
+
('perm_media_read', 'media.read', 'View media files', 'media', strftime('%s', 'now') * 1000),
|
|
116
|
+
('perm_media_update', 'media.update', 'Edit media metadata', 'media', strftime('%s', 'now') * 1000),
|
|
117
|
+
('perm_media_delete', 'media.delete', 'Delete media files', 'media', strftime('%s', 'now') * 1000),
|
|
118
|
+
|
|
119
|
+
('perm_users_create', 'users.create', 'Invite new users', 'users', strftime('%s', 'now') * 1000),
|
|
120
|
+
('perm_users_read', 'users.read', 'View user profiles', 'users', strftime('%s', 'now') * 1000),
|
|
121
|
+
('perm_users_update', 'users.update', 'Edit user profiles', 'users', strftime('%s', 'now') * 1000),
|
|
122
|
+
('perm_users_delete', 'users.delete', 'Deactivate users', 'users', strftime('%s', 'now') * 1000),
|
|
123
|
+
('perm_users_roles', 'users.roles', 'Manage user roles', 'users', strftime('%s', 'now') * 1000),
|
|
124
|
+
|
|
125
|
+
('perm_settings_read', 'settings.read', 'View system settings', 'settings', strftime('%s', 'now') * 1000),
|
|
126
|
+
('perm_settings_update', 'settings.update', 'Modify system settings', 'settings', strftime('%s', 'now') * 1000),
|
|
127
|
+
('perm_activity_read', 'activity.read', 'View activity logs', 'settings', strftime('%s', 'now') * 1000);
|
|
128
|
+
|
|
129
|
+
-- Assign permissions to default roles
|
|
130
|
+
INSERT OR IGNORE INTO role_permissions (id, role, permission_id, created_at) VALUES
|
|
131
|
+
-- Admin has all permissions
|
|
132
|
+
('rp_admin_content_create', 'admin', 'perm_content_create', strftime('%s', 'now') * 1000),
|
|
133
|
+
('rp_admin_content_read', 'admin', 'perm_content_read', strftime('%s', 'now') * 1000),
|
|
134
|
+
('rp_admin_content_update', 'admin', 'perm_content_update', strftime('%s', 'now') * 1000),
|
|
135
|
+
('rp_admin_content_delete', 'admin', 'perm_content_delete', strftime('%s', 'now') * 1000),
|
|
136
|
+
('rp_admin_content_publish', 'admin', 'perm_content_publish', strftime('%s', 'now') * 1000),
|
|
137
|
+
('rp_admin_collections_create', 'admin', 'perm_collections_create', strftime('%s', 'now') * 1000),
|
|
138
|
+
('rp_admin_collections_read', 'admin', 'perm_collections_read', strftime('%s', 'now') * 1000),
|
|
139
|
+
('rp_admin_collections_update', 'admin', 'perm_collections_update', strftime('%s', 'now') * 1000),
|
|
140
|
+
('rp_admin_collections_delete', 'admin', 'perm_collections_delete', strftime('%s', 'now') * 1000),
|
|
141
|
+
('rp_admin_collections_fields', 'admin', 'perm_collections_fields', strftime('%s', 'now') * 1000),
|
|
142
|
+
('rp_admin_media_upload', 'admin', 'perm_media_upload', strftime('%s', 'now') * 1000),
|
|
143
|
+
('rp_admin_media_read', 'admin', 'perm_media_read', strftime('%s', 'now') * 1000),
|
|
144
|
+
('rp_admin_media_update', 'admin', 'perm_media_update', strftime('%s', 'now') * 1000),
|
|
145
|
+
('rp_admin_media_delete', 'admin', 'perm_media_delete', strftime('%s', 'now') * 1000),
|
|
146
|
+
('rp_admin_users_create', 'admin', 'perm_users_create', strftime('%s', 'now') * 1000),
|
|
147
|
+
('rp_admin_users_read', 'admin', 'perm_users_read', strftime('%s', 'now') * 1000),
|
|
148
|
+
('rp_admin_users_update', 'admin', 'perm_users_update', strftime('%s', 'now') * 1000),
|
|
149
|
+
('rp_admin_users_delete', 'admin', 'perm_users_delete', strftime('%s', 'now') * 1000),
|
|
150
|
+
('rp_admin_users_roles', 'admin', 'perm_users_roles', strftime('%s', 'now') * 1000),
|
|
151
|
+
('rp_admin_settings_read', 'admin', 'perm_settings_read', strftime('%s', 'now') * 1000),
|
|
152
|
+
('rp_admin_settings_update', 'admin', 'perm_settings_update', strftime('%s', 'now') * 1000),
|
|
153
|
+
('rp_admin_activity_read', 'admin', 'perm_activity_read', strftime('%s', 'now') * 1000),
|
|
154
|
+
|
|
155
|
+
-- Editor permissions
|
|
156
|
+
('rp_editor_content_create', 'editor', 'perm_content_create', strftime('%s', 'now') * 1000),
|
|
157
|
+
('rp_editor_content_read', 'editor', 'perm_content_read', strftime('%s', 'now') * 1000),
|
|
158
|
+
('rp_editor_content_update', 'editor', 'perm_content_update', strftime('%s', 'now') * 1000),
|
|
159
|
+
('rp_editor_content_publish', 'editor', 'perm_content_publish', strftime('%s', 'now') * 1000),
|
|
160
|
+
('rp_editor_collections_read', 'editor', 'perm_collections_read', strftime('%s', 'now') * 1000),
|
|
161
|
+
('rp_editor_media_upload', 'editor', 'perm_media_upload', strftime('%s', 'now') * 1000),
|
|
162
|
+
('rp_editor_media_read', 'editor', 'perm_media_read', strftime('%s', 'now') * 1000),
|
|
163
|
+
('rp_editor_media_update', 'editor', 'perm_media_update', strftime('%s', 'now') * 1000),
|
|
164
|
+
('rp_editor_users_read', 'editor', 'perm_users_read', strftime('%s', 'now') * 1000),
|
|
165
|
+
|
|
166
|
+
-- Viewer permissions
|
|
167
|
+
('rp_viewer_content_read', 'viewer', 'perm_content_read', strftime('%s', 'now') * 1000),
|
|
168
|
+
('rp_viewer_collections_read', 'viewer', 'perm_collections_read', strftime('%s', 'now') * 1000),
|
|
169
|
+
('rp_viewer_media_read', 'viewer', 'perm_media_read', strftime('%s', 'now') * 1000),
|
|
170
|
+
('rp_viewer_users_read', 'viewer', 'perm_users_read', strftime('%s', 'now') * 1000);
|
|
171
|
+
|
|
172
|
+
-- Create indexes for performance
|
|
173
|
+
CREATE INDEX IF NOT EXISTS idx_team_memberships_team_id ON team_memberships(team_id);
|
|
174
|
+
CREATE INDEX IF NOT EXISTS idx_team_memberships_user_id ON team_memberships(user_id);
|
|
175
|
+
CREATE INDEX IF NOT EXISTS idx_user_sessions_user_id ON user_sessions(user_id);
|
|
176
|
+
CREATE INDEX IF NOT EXISTS idx_user_sessions_token_hash ON user_sessions(token_hash);
|
|
177
|
+
CREATE INDEX IF NOT EXISTS idx_activity_logs_user_id ON activity_logs(user_id);
|
|
178
|
+
CREATE INDEX IF NOT EXISTS idx_activity_logs_created_at ON activity_logs(created_at);
|
|
179
|
+
CREATE INDEX IF NOT EXISTS idx_activity_logs_resource ON activity_logs(resource_type, resource_id);
|
|
180
|
+
CREATE INDEX IF NOT EXISTS idx_password_history_user_id ON password_history(user_id);
|
|
181
|
+
CREATE INDEX IF NOT EXISTS idx_users_email_verification_token ON users(email_verification_token);
|
|
182
|
+
CREATE INDEX IF NOT EXISTS idx_users_password_reset_token ON users(password_reset_token);
|
|
183
|
+
CREATE INDEX IF NOT EXISTS idx_users_invitation_token ON users(invitation_token);
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
-- Stage 7: Workflow & Automation Migration
|
|
2
|
+
-- This migration adds workflow and automation capabilities to SonicJS
|
|
3
|
+
|
|
4
|
+
-- Workflow States Table
|
|
5
|
+
CREATE TABLE IF NOT EXISTS workflow_states (
|
|
6
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
7
|
+
name TEXT NOT NULL,
|
|
8
|
+
description TEXT,
|
|
9
|
+
color TEXT DEFAULT '#6B7280',
|
|
10
|
+
is_initial INTEGER DEFAULT 0,
|
|
11
|
+
is_final INTEGER DEFAULT 0,
|
|
12
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
-- Insert default workflow states
|
|
16
|
+
INSERT OR IGNORE INTO workflow_states (id, name, description, color, is_initial, is_final) VALUES
|
|
17
|
+
('draft', 'Draft', 'Content is being worked on', '#F59E0B', 1, 0),
|
|
18
|
+
('pending-review', 'Pending Review', 'Content is waiting for review', '#3B82F6', 0, 0),
|
|
19
|
+
('approved', 'Approved', 'Content has been approved', '#10B981', 0, 0),
|
|
20
|
+
('published', 'Published', 'Content is live', '#059669', 0, 1),
|
|
21
|
+
('rejected', 'Rejected', 'Content was rejected', '#EF4444', 0, 1),
|
|
22
|
+
('archived', 'Archived', 'Content has been archived', '#6B7280', 0, 1);
|
|
23
|
+
|
|
24
|
+
-- Workflows Table
|
|
25
|
+
CREATE TABLE IF NOT EXISTS workflows (
|
|
26
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
27
|
+
name TEXT NOT NULL,
|
|
28
|
+
description TEXT,
|
|
29
|
+
collection_id TEXT,
|
|
30
|
+
is_active INTEGER DEFAULT 1,
|
|
31
|
+
auto_publish INTEGER DEFAULT 0,
|
|
32
|
+
require_approval INTEGER DEFAULT 1,
|
|
33
|
+
approval_levels INTEGER DEFAULT 1,
|
|
34
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
35
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
36
|
+
FOREIGN KEY (collection_id) REFERENCES collections(id) ON DELETE CASCADE
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
-- Workflow Transitions Table
|
|
40
|
+
CREATE TABLE IF NOT EXISTS workflow_transitions (
|
|
41
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
42
|
+
workflow_id TEXT NOT NULL,
|
|
43
|
+
from_state_id TEXT NOT NULL,
|
|
44
|
+
to_state_id TEXT NOT NULL,
|
|
45
|
+
required_permission TEXT,
|
|
46
|
+
auto_transition INTEGER DEFAULT 0,
|
|
47
|
+
transition_conditions TEXT, -- JSON
|
|
48
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
49
|
+
FOREIGN KEY (workflow_id) REFERENCES workflows(id) ON DELETE CASCADE,
|
|
50
|
+
FOREIGN KEY (from_state_id) REFERENCES workflow_states(id),
|
|
51
|
+
FOREIGN KEY (to_state_id) REFERENCES workflow_states(id)
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
-- Content Workflow Status Table
|
|
55
|
+
CREATE TABLE IF NOT EXISTS content_workflow_status (
|
|
56
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
57
|
+
content_id TEXT NOT NULL,
|
|
58
|
+
workflow_id TEXT NOT NULL,
|
|
59
|
+
current_state_id TEXT NOT NULL,
|
|
60
|
+
assigned_to TEXT,
|
|
61
|
+
due_date DATETIME,
|
|
62
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
63
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
64
|
+
FOREIGN KEY (content_id) REFERENCES content(id) ON DELETE CASCADE,
|
|
65
|
+
FOREIGN KEY (workflow_id) REFERENCES workflows(id),
|
|
66
|
+
FOREIGN KEY (current_state_id) REFERENCES workflow_states(id),
|
|
67
|
+
FOREIGN KEY (assigned_to) REFERENCES users(id),
|
|
68
|
+
UNIQUE(content_id, workflow_id)
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
-- Workflow History Table
|
|
72
|
+
CREATE TABLE IF NOT EXISTS workflow_history (
|
|
73
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
74
|
+
content_id TEXT NOT NULL,
|
|
75
|
+
workflow_id TEXT NOT NULL,
|
|
76
|
+
from_state_id TEXT,
|
|
77
|
+
to_state_id TEXT NOT NULL,
|
|
78
|
+
user_id TEXT NOT NULL,
|
|
79
|
+
comment TEXT,
|
|
80
|
+
metadata TEXT, -- JSON
|
|
81
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
82
|
+
FOREIGN KEY (content_id) REFERENCES content(id) ON DELETE CASCADE,
|
|
83
|
+
FOREIGN KEY (workflow_id) REFERENCES workflows(id),
|
|
84
|
+
FOREIGN KEY (from_state_id) REFERENCES workflow_states(id),
|
|
85
|
+
FOREIGN KEY (to_state_id) REFERENCES workflow_states(id),
|
|
86
|
+
FOREIGN KEY (user_id) REFERENCES users(id)
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
-- Scheduled Content Table
|
|
90
|
+
CREATE TABLE IF NOT EXISTS scheduled_content (
|
|
91
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
92
|
+
content_id TEXT NOT NULL,
|
|
93
|
+
action TEXT NOT NULL, -- 'publish', 'unpublish', 'archive'
|
|
94
|
+
scheduled_at DATETIME NOT NULL,
|
|
95
|
+
timezone TEXT DEFAULT 'UTC',
|
|
96
|
+
user_id TEXT NOT NULL,
|
|
97
|
+
status TEXT DEFAULT 'pending', -- 'pending', 'completed', 'failed', 'cancelled'
|
|
98
|
+
executed_at DATETIME,
|
|
99
|
+
error_message TEXT,
|
|
100
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
101
|
+
FOREIGN KEY (content_id) REFERENCES content(id) ON DELETE CASCADE,
|
|
102
|
+
FOREIGN KEY (user_id) REFERENCES users(id)
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
-- Notifications Table
|
|
106
|
+
CREATE TABLE IF NOT EXISTS notifications (
|
|
107
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
108
|
+
user_id TEXT NOT NULL,
|
|
109
|
+
type TEXT NOT NULL, -- 'workflow', 'schedule', 'system'
|
|
110
|
+
title TEXT NOT NULL,
|
|
111
|
+
message TEXT NOT NULL,
|
|
112
|
+
data TEXT, -- JSON
|
|
113
|
+
is_read INTEGER DEFAULT 0,
|
|
114
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
115
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
-- Notification Preferences Table
|
|
119
|
+
CREATE TABLE IF NOT EXISTS notification_preferences (
|
|
120
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
121
|
+
user_id TEXT NOT NULL,
|
|
122
|
+
notification_type TEXT NOT NULL,
|
|
123
|
+
email_enabled INTEGER DEFAULT 1,
|
|
124
|
+
in_app_enabled INTEGER DEFAULT 1,
|
|
125
|
+
digest_frequency TEXT DEFAULT 'daily', -- 'immediate', 'hourly', 'daily', 'weekly'
|
|
126
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
127
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
128
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
129
|
+
UNIQUE(user_id, notification_type)
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
-- Webhooks Table
|
|
133
|
+
CREATE TABLE IF NOT EXISTS webhooks (
|
|
134
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
135
|
+
name TEXT NOT NULL,
|
|
136
|
+
url TEXT NOT NULL,
|
|
137
|
+
secret TEXT,
|
|
138
|
+
events TEXT NOT NULL, -- JSON array of event types
|
|
139
|
+
is_active INTEGER DEFAULT 1,
|
|
140
|
+
retry_count INTEGER DEFAULT 3,
|
|
141
|
+
timeout_seconds INTEGER DEFAULT 30,
|
|
142
|
+
last_success_at DATETIME,
|
|
143
|
+
last_failure_at DATETIME,
|
|
144
|
+
failure_count INTEGER DEFAULT 0,
|
|
145
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
146
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
-- Webhook Deliveries Table
|
|
150
|
+
CREATE TABLE IF NOT EXISTS webhook_deliveries (
|
|
151
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
152
|
+
webhook_id TEXT NOT NULL,
|
|
153
|
+
event_type TEXT NOT NULL,
|
|
154
|
+
payload TEXT NOT NULL, -- JSON
|
|
155
|
+
response_status INTEGER,
|
|
156
|
+
response_body TEXT,
|
|
157
|
+
attempt_count INTEGER DEFAULT 1,
|
|
158
|
+
delivered_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
159
|
+
FOREIGN KEY (webhook_id) REFERENCES webhooks(id) ON DELETE CASCADE
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
-- Content Versions Table (for rollback functionality)
|
|
163
|
+
CREATE TABLE IF NOT EXISTS content_versions (
|
|
164
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
165
|
+
content_id TEXT NOT NULL,
|
|
166
|
+
version_number INTEGER NOT NULL,
|
|
167
|
+
title TEXT NOT NULL,
|
|
168
|
+
content TEXT NOT NULL,
|
|
169
|
+
fields TEXT, -- JSON
|
|
170
|
+
user_id TEXT NOT NULL,
|
|
171
|
+
change_summary TEXT,
|
|
172
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
173
|
+
FOREIGN KEY (content_id) REFERENCES content(id) ON DELETE CASCADE,
|
|
174
|
+
FOREIGN KEY (user_id) REFERENCES users(id),
|
|
175
|
+
UNIQUE(content_id, version_number)
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
-- Automation Rules Table
|
|
179
|
+
CREATE TABLE IF NOT EXISTS automation_rules (
|
|
180
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
181
|
+
name TEXT NOT NULL,
|
|
182
|
+
description TEXT,
|
|
183
|
+
trigger_type TEXT NOT NULL, -- 'content_created', 'content_updated', 'workflow_transition', 'schedule'
|
|
184
|
+
trigger_conditions TEXT, -- JSON
|
|
185
|
+
action_type TEXT NOT NULL, -- 'workflow_transition', 'send_notification', 'webhook_call', 'auto_save'
|
|
186
|
+
action_config TEXT, -- JSON
|
|
187
|
+
is_active INTEGER DEFAULT 1,
|
|
188
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
189
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
-- Auto-save Drafts Table
|
|
193
|
+
CREATE TABLE IF NOT EXISTS auto_save_drafts (
|
|
194
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
195
|
+
content_id TEXT,
|
|
196
|
+
user_id TEXT NOT NULL,
|
|
197
|
+
title TEXT,
|
|
198
|
+
content TEXT,
|
|
199
|
+
fields TEXT, -- JSON
|
|
200
|
+
last_saved_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
201
|
+
FOREIGN KEY (content_id) REFERENCES content(id) ON DELETE CASCADE,
|
|
202
|
+
FOREIGN KEY (user_id) REFERENCES users(id),
|
|
203
|
+
UNIQUE(content_id, user_id)
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
-- Add workflow-related columns to existing content table (skip existing columns)
|
|
207
|
+
ALTER TABLE content ADD COLUMN workflow_state_id TEXT DEFAULT 'draft';
|
|
208
|
+
ALTER TABLE content ADD COLUMN embargo_until DATETIME;
|
|
209
|
+
ALTER TABLE content ADD COLUMN expires_at DATETIME;
|
|
210
|
+
ALTER TABLE content ADD COLUMN version_number INTEGER DEFAULT 1;
|
|
211
|
+
ALTER TABLE content ADD COLUMN is_auto_saved INTEGER DEFAULT 0;
|
|
212
|
+
|
|
213
|
+
-- Create indexes for performance
|
|
214
|
+
CREATE INDEX IF NOT EXISTS idx_content_workflow_status_content_id ON content_workflow_status(content_id);
|
|
215
|
+
CREATE INDEX IF NOT EXISTS idx_content_workflow_status_workflow_id ON content_workflow_status(workflow_id);
|
|
216
|
+
CREATE INDEX IF NOT EXISTS idx_workflow_history_content_id ON workflow_history(content_id);
|
|
217
|
+
CREATE INDEX IF NOT EXISTS idx_scheduled_content_scheduled_at ON scheduled_content(scheduled_at);
|
|
218
|
+
CREATE INDEX IF NOT EXISTS idx_scheduled_content_status ON scheduled_content(status);
|
|
219
|
+
CREATE INDEX IF NOT EXISTS idx_notifications_user_id ON notifications(user_id);
|
|
220
|
+
CREATE INDEX IF NOT EXISTS idx_notifications_is_read ON notifications(is_read);
|
|
221
|
+
CREATE INDEX IF NOT EXISTS idx_content_versions_content_id ON content_versions(content_id);
|
|
222
|
+
CREATE INDEX IF NOT EXISTS idx_auto_save_drafts_user_id ON auto_save_drafts(user_id);
|
|
223
|
+
CREATE INDEX IF NOT EXISTS idx_content_workflow_state ON content(workflow_state_id);
|
|
224
|
+
CREATE INDEX IF NOT EXISTS idx_content_scheduled_publish ON content(scheduled_publish_at);
|
|
225
|
+
|
|
226
|
+
-- Insert default workflow for collections
|
|
227
|
+
INSERT OR IGNORE INTO workflows (id, name, description, collection_id, is_active, require_approval, approval_levels)
|
|
228
|
+
SELECT
|
|
229
|
+
'default-' || id,
|
|
230
|
+
'Default Workflow for ' || name,
|
|
231
|
+
'Standard content approval workflow',
|
|
232
|
+
id,
|
|
233
|
+
1,
|
|
234
|
+
1,
|
|
235
|
+
1
|
|
236
|
+
FROM collections;
|
|
237
|
+
|
|
238
|
+
-- Insert default workflow transitions
|
|
239
|
+
INSERT OR IGNORE INTO workflow_transitions (workflow_id, from_state_id, to_state_id, required_permission)
|
|
240
|
+
SELECT
|
|
241
|
+
w.id,
|
|
242
|
+
'draft',
|
|
243
|
+
'pending-review',
|
|
244
|
+
'content:submit'
|
|
245
|
+
FROM workflows w;
|
|
246
|
+
|
|
247
|
+
INSERT OR IGNORE INTO workflow_transitions (workflow_id, from_state_id, to_state_id, required_permission)
|
|
248
|
+
SELECT
|
|
249
|
+
w.id,
|
|
250
|
+
'pending-review',
|
|
251
|
+
'approved',
|
|
252
|
+
'content:approve'
|
|
253
|
+
FROM workflows w;
|
|
254
|
+
|
|
255
|
+
INSERT OR IGNORE INTO workflow_transitions (workflow_id, from_state_id, to_state_id, required_permission)
|
|
256
|
+
SELECT
|
|
257
|
+
w.id,
|
|
258
|
+
'approved',
|
|
259
|
+
'published',
|
|
260
|
+
'content:publish'
|
|
261
|
+
FROM workflows w;
|
|
262
|
+
|
|
263
|
+
INSERT OR IGNORE INTO workflow_transitions (workflow_id, from_state_id, to_state_id, required_permission)
|
|
264
|
+
SELECT
|
|
265
|
+
w.id,
|
|
266
|
+
'pending-review',
|
|
267
|
+
'rejected',
|
|
268
|
+
'content:approve'
|
|
269
|
+
FROM workflows w;
|
|
270
|
+
|
|
271
|
+
-- Insert default notification preferences for all users
|
|
272
|
+
INSERT OR IGNORE INTO notification_preferences (user_id, notification_type, email_enabled, in_app_enabled)
|
|
273
|
+
SELECT
|
|
274
|
+
id,
|
|
275
|
+
'workflow_assigned',
|
|
276
|
+
1,
|
|
277
|
+
1
|
|
278
|
+
FROM users;
|
|
279
|
+
|
|
280
|
+
INSERT OR IGNORE INTO notification_preferences (user_id, notification_type, email_enabled, in_app_enabled)
|
|
281
|
+
SELECT
|
|
282
|
+
id,
|
|
283
|
+
'workflow_status_change',
|
|
284
|
+
1,
|
|
285
|
+
1
|
|
286
|
+
FROM users;
|
|
287
|
+
|
|
288
|
+
INSERT OR IGNORE INTO notification_preferences (user_id, notification_type, email_enabled, in_app_enabled)
|
|
289
|
+
SELECT
|
|
290
|
+
id,
|
|
291
|
+
'content_scheduled',
|
|
292
|
+
1,
|
|
293
|
+
1
|
|
294
|
+
FROM users;
|