@intranefr/superbackend 1.6.7 → 1.7.8
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/.beads/.br_history/issues.20260314_212352_900045509.jsonl +0 -0
- package/.beads/.br_history/issues.20260314_212352_900045509.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_087140743.jsonl +1 -0
- package/.beads/.br_history/issues.20260314_212353_087140743.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_285881504.jsonl +2 -0
- package/.beads/.br_history/issues.20260314_212353_285881504.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_473915419.jsonl +3 -0
- package/.beads/.br_history/issues.20260314_212353_473915419.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_659476307.jsonl +4 -0
- package/.beads/.br_history/issues.20260314_212353_659476307.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_869998925.jsonl +5 -0
- package/.beads/.br_history/issues.20260314_212353_869998925.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212354_054785029.jsonl +6 -0
- package/.beads/.br_history/issues.20260314_212354_054785029.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_175893691.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_175893691.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_338509797.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_338509797.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_515443192.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_515443192.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_676417592.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_676417592.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_839182422.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_839182422.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213337_004349113.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213337_004349113.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213337_179824080.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213337_179824080.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213701_705075332.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213701_705075332.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213706_783128702.jsonl +8 -0
- package/.beads/.br_history/issues.20260314_213706_783128702.jsonl.meta.json +1 -0
- package/.beads/config.yaml +4 -0
- package/.beads/issues.jsonl +8 -0
- package/.beads/metadata.json +4 -0
- package/.env.example +8 -0
- package/autochangelog/.env.example +36 -0
- package/autochangelog/README.md +412 -0
- package/autochangelog/config/database.js +27 -0
- package/autochangelog/package.json +47 -0
- package/autochangelog/public/landing.html +581 -0
- package/autochangelog/server.js +104 -0
- package/autochangelog/src/app.js +181 -0
- package/autochangelog/src/config/database.js +26 -0
- package/autochangelog/src/controllers/auth.js +488 -0
- package/autochangelog/src/controllers/changelog.js +682 -0
- package/autochangelog/src/controllers/project.js +580 -0
- package/autochangelog/src/controllers/repository.js +780 -0
- package/autochangelog/src/middleware/auth.js +386 -0
- package/autochangelog/src/models/Changelog.js +443 -0
- package/autochangelog/src/models/Project.js +226 -0
- package/autochangelog/src/models/Repository.js +366 -0
- package/autochangelog/src/models/User.js +223 -0
- package/autochangelog/src/routes/auth.routes.js +32 -0
- package/autochangelog/src/routes/changelog.routes.js +42 -0
- package/autochangelog/src/routes/github-auth.routes.js +102 -0
- package/autochangelog/src/routes/project.routes.js +50 -0
- package/autochangelog/src/routes/repository.routes.js +54 -0
- package/autochangelog/src/services/changelog.js +722 -0
- package/autochangelog/src/services/github.js +243 -0
- package/autochangelog/utils/logger.js +77 -0
- package/autochangelog/views/404.ejs +18 -0
- package/autochangelog/views/dashboard.ejs +596 -0
- package/autochangelog/views/index.ejs +231 -0
- package/autochangelog/views/layouts/main.ejs +44 -0
- package/autochangelog/views/login.ejs +104 -0
- package/autochangelog/views/partials/footer.ejs +20 -0
- package/autochangelog/views/partials/navbar.ejs +51 -0
- package/autochangelog/views/register.ejs +109 -0
- package/autochangelog-cli/README.md +266 -0
- package/autochangelog-cli/bin/autochangelog +120 -0
- package/autochangelog-cli/package.json +46 -0
- package/autochangelog-cli/src/cli/commands/auth.js +291 -0
- package/autochangelog-cli/src/cli/commands/changelog.js +619 -0
- package/autochangelog-cli/src/cli/commands/project.js +427 -0
- package/autochangelog-cli/src/cli/commands/repo.js +557 -0
- package/autochangelog-cli/src/cli/commands/stats.js +706 -0
- package/autochangelog-cli/src/cli/utils/config.js +277 -0
- package/autochangelog-cli/src/cli/utils/errors.js +307 -0
- package/autochangelog-cli/src/cli/utils/logger.js +75 -0
- package/autochangelog-cli/src/cli/utils/output.js +357 -0
- package/package.json +9 -3
- package/plugins/supercli/README.md +108 -0
- package/plugins/supercli/plugin.json +123 -0
- package/server.js +1 -1
- package/src/cli/api.js +380 -0
- package/src/cli/direct/agent-utils.js +61 -0
- package/src/cli/direct/cli-utils.js +112 -0
- package/src/cli/direct/data-seeding.js +307 -0
- package/src/cli/direct/db-admin.js +84 -0
- package/src/cli/direct/db-advanced.js +372 -0
- package/src/cli/direct/db-utils.js +558 -0
- package/src/cli/direct/help.js +195 -0
- package/src/cli/direct/migration.js +107 -0
- package/src/cli/direct/rbac-advanced.js +132 -0
- package/src/cli/direct/resources-additional.js +400 -0
- package/src/cli/direct/resources-cms-advanced.js +173 -0
- package/src/cli/direct/resources-cms.js +247 -0
- package/src/cli/direct/resources-core.js +253 -0
- package/src/cli/direct/resources-execution.js +367 -0
- package/src/cli/direct/resources-health.js +152 -0
- package/src/cli/direct/resources-integrations.js +182 -0
- package/src/cli/direct/resources-logs.js +204 -0
- package/src/cli/direct/resources-org-rbac.js +187 -0
- package/src/cli/direct/resources-system.js +236 -0
- package/src/cli/direct.js +556 -0
- package/src/controllers/admin.controller.js +4 -0
- package/src/controllers/auth.controller.js +148 -1
- package/src/controllers/waitingList.controller.js +130 -1
- package/src/models/RbacRole.js +1 -1
- package/src/models/User.js +39 -5
- package/src/routes/auth.routes.js +6 -0
- package/src/routes/waitingList.routes.js +12 -2
- package/src/routes/waitingListAdmin.routes.js +3 -0
- package/src/services/email.service.js +1 -0
- package/src/services/github.service.js +255 -0
- package/src/services/rateLimiter.service.js +29 -1
- package/src/services/waitingListJson.service.js +32 -3
- package/views/admin-waiting-list.ejs +386 -3
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Log resources: notifications, cache, audit-logs, console-logs, activity-logs, email-logs
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const mongoose = require('mongoose');
|
|
8
|
+
|
|
9
|
+
const notifications = {
|
|
10
|
+
async execute(options) {
|
|
11
|
+
const Notification = mongoose.model('Notification');
|
|
12
|
+
switch (options.command) {
|
|
13
|
+
case 'list': {
|
|
14
|
+
const limit = parseInt(options.value) || 50;
|
|
15
|
+
const notifications = await Notification.find().sort({ createdAt: -1 }).limit(limit).lean();
|
|
16
|
+
return { items: notifications, count: notifications.length };
|
|
17
|
+
}
|
|
18
|
+
case 'get': {
|
|
19
|
+
if (!options.id) throw new Error('Notification ID is required');
|
|
20
|
+
const notification = await Notification.findById(options.id).lean();
|
|
21
|
+
if (!notification) throw new Error('Notification not found');
|
|
22
|
+
return notification;
|
|
23
|
+
}
|
|
24
|
+
case 'delete': {
|
|
25
|
+
if (!options.id) throw new Error('Notification ID is required');
|
|
26
|
+
const notification = await Notification.findByIdAndDelete(options.id);
|
|
27
|
+
if (!notification) throw new Error('Notification not found');
|
|
28
|
+
return { success: true, id: options.id };
|
|
29
|
+
}
|
|
30
|
+
case 'clear': {
|
|
31
|
+
await Notification.deleteMany({});
|
|
32
|
+
return { success: true, message: 'All notifications cleared' };
|
|
33
|
+
}
|
|
34
|
+
default:
|
|
35
|
+
throw new Error(`Unknown notifications command: ${options.command}`);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const cache = {
|
|
41
|
+
async execute(options) {
|
|
42
|
+
const CacheEntry = mongoose.model('CacheEntry');
|
|
43
|
+
switch (options.command) {
|
|
44
|
+
case 'list': {
|
|
45
|
+
const limit = parseInt(options.value) || 50;
|
|
46
|
+
const entries = await CacheEntry.find().sort({ createdAt: -1 }).limit(limit).lean();
|
|
47
|
+
return { items: entries, count: entries.length };
|
|
48
|
+
}
|
|
49
|
+
case 'get': {
|
|
50
|
+
if (!options.key) throw new Error('--key is required');
|
|
51
|
+
const entry = await CacheEntry.findOne({ key: options.key }).lean();
|
|
52
|
+
if (!entry) throw new Error('Cache entry not found');
|
|
53
|
+
return entry;
|
|
54
|
+
}
|
|
55
|
+
case 'delete': {
|
|
56
|
+
if (!options.key) throw new Error('--key is required');
|
|
57
|
+
const entry = await CacheEntry.findOneAndDelete({ key: options.key });
|
|
58
|
+
if (!entry) throw new Error('Cache entry not found');
|
|
59
|
+
return { success: true, key: options.key };
|
|
60
|
+
}
|
|
61
|
+
case 'clear': {
|
|
62
|
+
const result = await CacheEntry.deleteMany({});
|
|
63
|
+
return { success: true, deletedCount: result.deletedCount };
|
|
64
|
+
}
|
|
65
|
+
default:
|
|
66
|
+
throw new Error(`Unknown cache command: ${options.command}`);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const auditLogs = {
|
|
72
|
+
async execute(options) {
|
|
73
|
+
const AuditEvent = mongoose.model('AuditEvent');
|
|
74
|
+
switch (options.command) {
|
|
75
|
+
case 'list': {
|
|
76
|
+
const limit = parseInt(options.value) || 50;
|
|
77
|
+
const events = await AuditEvent.find().sort({ createdAt: -1 }).limit(limit).lean();
|
|
78
|
+
return { items: events, count: events.length };
|
|
79
|
+
}
|
|
80
|
+
case 'get': {
|
|
81
|
+
if (!options.id) throw new Error('Audit event ID is required');
|
|
82
|
+
const event = await AuditEvent.findById(options.id).lean();
|
|
83
|
+
if (!event) throw new Error('Audit event not found');
|
|
84
|
+
return event;
|
|
85
|
+
}
|
|
86
|
+
case 'clear': {
|
|
87
|
+
const days = parseInt(options.value) || 90;
|
|
88
|
+
const cutoffDate = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
|
|
89
|
+
const result = await AuditEvent.deleteMany({ createdAt: { $lt: cutoffDate } });
|
|
90
|
+
return { success: true, deletedCount: result.deletedCount, olderThan: cutoffDate.toISOString() };
|
|
91
|
+
}
|
|
92
|
+
default:
|
|
93
|
+
throw new Error(`Unknown audit-logs command: ${options.command}`);
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const consoleLogs = {
|
|
99
|
+
async execute(options) {
|
|
100
|
+
const ConsoleLog = mongoose.model('ConsoleLog');
|
|
101
|
+
switch (options.command) {
|
|
102
|
+
case 'list': {
|
|
103
|
+
const limit = parseInt(options.value) || 50;
|
|
104
|
+
const logs = await ConsoleLog.find().sort({ createdAt: -1 }).limit(limit).lean();
|
|
105
|
+
return { items: logs, count: logs.length };
|
|
106
|
+
}
|
|
107
|
+
case 'get': {
|
|
108
|
+
if (!options.id) throw new Error('Log ID is required');
|
|
109
|
+
const log = await ConsoleLog.findById(options.id).lean();
|
|
110
|
+
if (!log) throw new Error('Log not found');
|
|
111
|
+
return log;
|
|
112
|
+
}
|
|
113
|
+
case 'clear': {
|
|
114
|
+
const days = parseInt(options.value) || 7;
|
|
115
|
+
const cutoffDate = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
|
|
116
|
+
const result = await ConsoleLog.deleteMany({ createdAt: { $lt: cutoffDate } });
|
|
117
|
+
return { success: true, deletedCount: result.deletedCount, olderThan: cutoffDate.toISOString() };
|
|
118
|
+
}
|
|
119
|
+
default:
|
|
120
|
+
throw new Error(`Unknown console-logs command: ${options.command}`);
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const activityLogs = {
|
|
126
|
+
async execute(options) {
|
|
127
|
+
const ActivityLog = mongoose.model('ActivityLog');
|
|
128
|
+
switch (options.command) {
|
|
129
|
+
case 'list': {
|
|
130
|
+
const limit = parseInt(options.value) || 50;
|
|
131
|
+
const logs = await ActivityLog.find().sort({ createdAt: -1 }).limit(limit).lean();
|
|
132
|
+
return { items: logs, count: logs.length };
|
|
133
|
+
}
|
|
134
|
+
case 'get': {
|
|
135
|
+
if (!options.id) throw new Error('Activity log ID is required');
|
|
136
|
+
const log = await ActivityLog.findById(options.id).lean();
|
|
137
|
+
if (!log) throw new Error('Activity log not found');
|
|
138
|
+
return log;
|
|
139
|
+
}
|
|
140
|
+
case 'clear': {
|
|
141
|
+
const days = parseInt(options.value) || 30;
|
|
142
|
+
const cutoffDate = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
|
|
143
|
+
const result = await ActivityLog.deleteMany({ createdAt: { $lt: cutoffDate } });
|
|
144
|
+
return { success: true, deletedCount: result.deletedCount, olderThan: cutoffDate.toISOString() };
|
|
145
|
+
}
|
|
146
|
+
default:
|
|
147
|
+
throw new Error(`Unknown activity-logs command: ${options.command}`);
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const emailLogs = {
|
|
153
|
+
async execute(options) {
|
|
154
|
+
const EmailLog = mongoose.model('EmailLog');
|
|
155
|
+
switch (options.command) {
|
|
156
|
+
case 'list': {
|
|
157
|
+
const limit = parseInt(options.value) || 50;
|
|
158
|
+
const logs = await EmailLog.find().sort({ createdAt: -1 }).limit(limit).lean();
|
|
159
|
+
return { items: logs, count: logs.length };
|
|
160
|
+
}
|
|
161
|
+
case 'get': {
|
|
162
|
+
if (!options.id) throw new Error('Email log ID is required');
|
|
163
|
+
const log = await EmailLog.findById(options.id).lean();
|
|
164
|
+
if (!log) throw new Error('Email log not found');
|
|
165
|
+
return log;
|
|
166
|
+
}
|
|
167
|
+
case 'clear': {
|
|
168
|
+
const days = parseInt(options.value) || 30;
|
|
169
|
+
const cutoffDate = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
|
|
170
|
+
const result = await EmailLog.deleteMany({ createdAt: { $lt: cutoffDate } });
|
|
171
|
+
return { success: true, deletedCount: result.deletedCount, olderThan: cutoffDate.toISOString() };
|
|
172
|
+
}
|
|
173
|
+
default:
|
|
174
|
+
throw new Error(`Unknown email-logs command: ${options.command}`);
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const waitingList = {
|
|
180
|
+
async execute(options) {
|
|
181
|
+
const WaitingList = mongoose.model('WaitingList');
|
|
182
|
+
switch (options.command) {
|
|
183
|
+
case 'list': {
|
|
184
|
+
const limit = parseInt(options.value) || 50;
|
|
185
|
+
const entries = await WaitingList.find().sort({ createdAt: -1 }).limit(limit).lean();
|
|
186
|
+
return { items: entries, count: entries.length };
|
|
187
|
+
}
|
|
188
|
+
case 'delete': {
|
|
189
|
+
if (!options.id) throw new Error('Waiting list entry ID is required');
|
|
190
|
+
const entry = await WaitingList.findByIdAndDelete(options.id);
|
|
191
|
+
if (!entry) throw new Error('Waiting list entry not found');
|
|
192
|
+
return { success: true, id: options.id };
|
|
193
|
+
}
|
|
194
|
+
case 'clear': {
|
|
195
|
+
await WaitingList.deleteMany({});
|
|
196
|
+
return { success: true, message: 'All waiting list entries cleared' };
|
|
197
|
+
}
|
|
198
|
+
default:
|
|
199
|
+
throw new Error(`Unknown waiting-list command: ${options.command}`);
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
module.exports = { notifications, cache, auditLogs, consoleLogs, activityLogs, emailLogs, waitingList };
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Organization & RBAC handlers: orgs, rbac-roles, rbac-groups, invites, org-members
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const mongoose = require("mongoose");
|
|
8
|
+
|
|
9
|
+
const orgs = {
|
|
10
|
+
async execute(options) {
|
|
11
|
+
const Organization = mongoose.model("Organization");
|
|
12
|
+
switch (options.command) {
|
|
13
|
+
case "list": {
|
|
14
|
+
const orgs = await Organization.find().lean();
|
|
15
|
+
return { items: orgs, count: orgs.length };
|
|
16
|
+
}
|
|
17
|
+
case "get": {
|
|
18
|
+
if (!options.id) throw new Error("Org ID is required");
|
|
19
|
+
const org = await Organization.findById(options.id).lean();
|
|
20
|
+
if (!org) throw new Error("Org not found");
|
|
21
|
+
return org;
|
|
22
|
+
}
|
|
23
|
+
case "create": {
|
|
24
|
+
if (!options.name) throw new Error("--name is required");
|
|
25
|
+
const org = await Organization.create({
|
|
26
|
+
name: options.name,
|
|
27
|
+
description: options.description || "",
|
|
28
|
+
});
|
|
29
|
+
return org;
|
|
30
|
+
}
|
|
31
|
+
case "update": {
|
|
32
|
+
if (!options.id) throw new Error("Org ID is required");
|
|
33
|
+
const updateData = {};
|
|
34
|
+
if (options.name) updateData.name = options.name;
|
|
35
|
+
if (options.description) updateData.description = options.description;
|
|
36
|
+
const org = await Org.findByIdAndUpdate(options.id, updateData, {
|
|
37
|
+
new: true,
|
|
38
|
+
});
|
|
39
|
+
if (!org) throw new Error("Org not found");
|
|
40
|
+
return org;
|
|
41
|
+
}
|
|
42
|
+
case "delete": {
|
|
43
|
+
if (!options.id) throw new Error("Org ID is required");
|
|
44
|
+
const org = await Org.findByIdAndDelete(options.id);
|
|
45
|
+
if (!org) throw new Error("Org not found");
|
|
46
|
+
return { success: true, id: options.id };
|
|
47
|
+
}
|
|
48
|
+
default:
|
|
49
|
+
throw new Error(`Unknown orgs command: ${options.command}`);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const rbacRoles = {
|
|
55
|
+
async execute(options) {
|
|
56
|
+
const RbacRole = mongoose.model("RbacRole");
|
|
57
|
+
switch (options.command) {
|
|
58
|
+
case "list": {
|
|
59
|
+
const roles = await RbacRole.find().lean();
|
|
60
|
+
return { items: roles, count: roles.length };
|
|
61
|
+
}
|
|
62
|
+
case "get": {
|
|
63
|
+
if (!options.id) throw new Error("Role ID is required");
|
|
64
|
+
const role = await RbacRole.findById(options.id).lean();
|
|
65
|
+
if (!role) throw new Error("Role not found");
|
|
66
|
+
return role;
|
|
67
|
+
}
|
|
68
|
+
case "create": {
|
|
69
|
+
if (!options.name) throw new Error("--name is required");
|
|
70
|
+
const role = await RbacRole.create({
|
|
71
|
+
name: options.name,
|
|
72
|
+
description: options.description || "",
|
|
73
|
+
});
|
|
74
|
+
return role;
|
|
75
|
+
}
|
|
76
|
+
case "delete": {
|
|
77
|
+
if (!options.id) throw new Error("Role ID is required");
|
|
78
|
+
const role = await RbacRole.findByIdAndDelete(options.id);
|
|
79
|
+
if (!role) throw new Error("Role not found");
|
|
80
|
+
return { success: true, id: options.id };
|
|
81
|
+
}
|
|
82
|
+
default:
|
|
83
|
+
throw new Error(`Unknown rbac-roles command: ${options.command}`);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const rbacGroups = {
|
|
89
|
+
async execute(options) {
|
|
90
|
+
const RbacGroup = mongoose.model("RbacGroup");
|
|
91
|
+
switch (options.command) {
|
|
92
|
+
case "list": {
|
|
93
|
+
const groups = await RbacGroup.find().lean();
|
|
94
|
+
return { items: groups, count: groups.length };
|
|
95
|
+
}
|
|
96
|
+
case "get": {
|
|
97
|
+
if (!options.id) throw new Error("Group ID is required");
|
|
98
|
+
const group = await RbacGroup.findById(options.id).lean();
|
|
99
|
+
if (!group) throw new Error("Group not found");
|
|
100
|
+
return group;
|
|
101
|
+
}
|
|
102
|
+
case "create": {
|
|
103
|
+
if (!options.name) throw new Error("--name is required");
|
|
104
|
+
const group = await RbacGroup.create({
|
|
105
|
+
name: options.name,
|
|
106
|
+
description: options.description || "",
|
|
107
|
+
});
|
|
108
|
+
return group;
|
|
109
|
+
}
|
|
110
|
+
case "delete": {
|
|
111
|
+
if (!options.id) throw new Error("Group ID is required");
|
|
112
|
+
const group = await RbacGroup.findByIdAndDelete(options.id);
|
|
113
|
+
if (!group) throw new Error("Group not found");
|
|
114
|
+
return { success: true, id: options.id };
|
|
115
|
+
}
|
|
116
|
+
default:
|
|
117
|
+
throw new Error(`Unknown rbac-groups command: ${options.command}`);
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const invites = {
|
|
123
|
+
async execute(options) {
|
|
124
|
+
const Invite = mongoose.model("Invite");
|
|
125
|
+
switch (options.command) {
|
|
126
|
+
case "list": {
|
|
127
|
+
const limit = parseInt(options.value) || 50;
|
|
128
|
+
const invites = await Invite.find()
|
|
129
|
+
.sort({ createdAt: -1 })
|
|
130
|
+
.limit(limit)
|
|
131
|
+
.lean();
|
|
132
|
+
return { items: invites, count: invites.length };
|
|
133
|
+
}
|
|
134
|
+
case "get": {
|
|
135
|
+
if (!options.id) throw new Error("Invite ID is required");
|
|
136
|
+
const invite = await Invite.findById(options.id).lean();
|
|
137
|
+
if (!invite) throw new Error("Invite not found");
|
|
138
|
+
return invite;
|
|
139
|
+
}
|
|
140
|
+
case "create": {
|
|
141
|
+
if (!options.email) throw new Error("--email is required");
|
|
142
|
+
const invite = await Invite.create({
|
|
143
|
+
email: options.email,
|
|
144
|
+
role: options.role || "user",
|
|
145
|
+
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
|
146
|
+
});
|
|
147
|
+
return invite;
|
|
148
|
+
}
|
|
149
|
+
case "delete": {
|
|
150
|
+
if (!options.id) throw new Error("Invite ID is required");
|
|
151
|
+
const invite = await Invite.findByIdAndDelete(options.id);
|
|
152
|
+
if (!invite) throw new Error("Invite not found");
|
|
153
|
+
return { success: true, id: options.id };
|
|
154
|
+
}
|
|
155
|
+
case "clear": {
|
|
156
|
+
await Invite.deleteMany({ used: true });
|
|
157
|
+
return { success: true, message: "Cleared used invites" };
|
|
158
|
+
}
|
|
159
|
+
default:
|
|
160
|
+
throw new Error(`Unknown invites command: ${options.command}`);
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const orgMembers = {
|
|
166
|
+
async execute(options) {
|
|
167
|
+
const OrganizationMember = mongoose.model("OrganizationMember");
|
|
168
|
+
switch (options.command) {
|
|
169
|
+
case "list": {
|
|
170
|
+
const members = await OrganizationMember.find()
|
|
171
|
+
.populate("userId")
|
|
172
|
+
.lean();
|
|
173
|
+
return { items: members, count: members.length };
|
|
174
|
+
}
|
|
175
|
+
case "delete": {
|
|
176
|
+
if (!options.id) throw new Error("Member ID is required");
|
|
177
|
+
const member = await OrganizationMember.findByIdAndDelete(options.id);
|
|
178
|
+
if (!member) throw new Error("Member not found");
|
|
179
|
+
return { success: true, id: options.id };
|
|
180
|
+
}
|
|
181
|
+
default:
|
|
182
|
+
throw new Error(`Unknown org-members command: ${options.command}`);
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
module.exports = { orgs, rbacRoles, rbacGroups, invites, orgMembers };
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* System resources: crons, errors, scripts, workflows, health-checks
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const mongoose = require("mongoose");
|
|
8
|
+
|
|
9
|
+
const crons = {
|
|
10
|
+
async execute(options) {
|
|
11
|
+
const CronJob = mongoose.model("CronJob");
|
|
12
|
+
switch (options.command) {
|
|
13
|
+
case "list": {
|
|
14
|
+
const crons = await CronJob.find().lean();
|
|
15
|
+
return { items: crons, count: crons.length };
|
|
16
|
+
}
|
|
17
|
+
case "get": {
|
|
18
|
+
if (!options.id) throw new Error("Cron ID is required");
|
|
19
|
+
const cron = await CronJob.findById(options.id).lean();
|
|
20
|
+
if (!cron) throw new Error("Cron not found");
|
|
21
|
+
return cron;
|
|
22
|
+
}
|
|
23
|
+
case "create": {
|
|
24
|
+
if (!options.name) throw new Error("--name is required");
|
|
25
|
+
if (!options.description)
|
|
26
|
+
throw new Error("--description (cron expression) is required");
|
|
27
|
+
const cron = await CronJob.create({
|
|
28
|
+
name: options.name,
|
|
29
|
+
description: options.description,
|
|
30
|
+
enabled: true,
|
|
31
|
+
});
|
|
32
|
+
return cron;
|
|
33
|
+
}
|
|
34
|
+
case "delete": {
|
|
35
|
+
if (!options.id) throw new Error("Cron ID is required");
|
|
36
|
+
const cron = await CronJob.findByIdAndDelete(options.id);
|
|
37
|
+
if (!cron) throw new Error("Cron not found");
|
|
38
|
+
return { success: true, id: options.id };
|
|
39
|
+
}
|
|
40
|
+
case "enable": {
|
|
41
|
+
if (!options.id) throw new Error("Cron ID is required");
|
|
42
|
+
const cron = await CronJob.findByIdAndUpdate(
|
|
43
|
+
options.id,
|
|
44
|
+
{ enabled: true },
|
|
45
|
+
{ new: true },
|
|
46
|
+
);
|
|
47
|
+
if (!cron) throw new Error("Cron not found");
|
|
48
|
+
return cron;
|
|
49
|
+
}
|
|
50
|
+
case "disable": {
|
|
51
|
+
if (!options.id) throw new Error("Cron ID is required");
|
|
52
|
+
const cron = await CronJob.findByIdAndUpdate(
|
|
53
|
+
options.id,
|
|
54
|
+
{ enabled: false },
|
|
55
|
+
{ new: true },
|
|
56
|
+
);
|
|
57
|
+
if (!cron) throw new Error("Cron not found");
|
|
58
|
+
return cron;
|
|
59
|
+
}
|
|
60
|
+
default:
|
|
61
|
+
throw new Error(`Unknown crons command: ${options.command}`);
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const errors = {
|
|
67
|
+
async execute(options) {
|
|
68
|
+
const ErrorAggregate = mongoose.model("ErrorAggregate");
|
|
69
|
+
switch (options.command) {
|
|
70
|
+
case "list": {
|
|
71
|
+
const limit = parseInt(options.value) || 50;
|
|
72
|
+
const errors = await ErrorAggregate.find()
|
|
73
|
+
.sort({ count: -1 })
|
|
74
|
+
.limit(limit)
|
|
75
|
+
.lean();
|
|
76
|
+
return { items: errors, count: errors.length };
|
|
77
|
+
}
|
|
78
|
+
case "get": {
|
|
79
|
+
if (!options.id) throw new Error("Error ID is required");
|
|
80
|
+
const error = await ErrorAggregate.findById(options.id).lean();
|
|
81
|
+
if (!error) throw new Error("Error not found");
|
|
82
|
+
return error;
|
|
83
|
+
}
|
|
84
|
+
case "delete": {
|
|
85
|
+
if (!options.id) throw new Error("Error ID is required");
|
|
86
|
+
const error = await ErrorAggregate.findByIdAndDelete(options.id);
|
|
87
|
+
if (!error) throw new Error("Error not found");
|
|
88
|
+
return { success: true, id: options.id };
|
|
89
|
+
}
|
|
90
|
+
case "clear": {
|
|
91
|
+
await ErrorAggregate.deleteMany({});
|
|
92
|
+
return { success: true, message: "All errors cleared" };
|
|
93
|
+
}
|
|
94
|
+
default:
|
|
95
|
+
throw new Error(`Unknown errors command: ${options.command}`);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const scripts = {
|
|
101
|
+
async execute(options) {
|
|
102
|
+
const ScriptDefinition = mongoose.model("ScriptDefinition");
|
|
103
|
+
switch (options.command) {
|
|
104
|
+
case "list": {
|
|
105
|
+
const scripts = await ScriptDefinition.find().lean();
|
|
106
|
+
return { items: scripts, count: scripts.length };
|
|
107
|
+
}
|
|
108
|
+
case "get": {
|
|
109
|
+
if (!options.id) throw new Error("Script ID is required");
|
|
110
|
+
const script = await ScriptDefinition.findById(options.id).lean();
|
|
111
|
+
if (!script) throw new Error("Script not found");
|
|
112
|
+
return script;
|
|
113
|
+
}
|
|
114
|
+
case "create": {
|
|
115
|
+
if (!options.name) throw new Error("--name is required");
|
|
116
|
+
if (!options.description)
|
|
117
|
+
throw new Error("--description (script code) is required");
|
|
118
|
+
const script = await ScriptDefinition.create({
|
|
119
|
+
name: options.name,
|
|
120
|
+
description: options.description,
|
|
121
|
+
enabled: true,
|
|
122
|
+
});
|
|
123
|
+
return script;
|
|
124
|
+
}
|
|
125
|
+
case "delete": {
|
|
126
|
+
if (!options.id) throw new Error("Script ID is required");
|
|
127
|
+
const script = await ScriptDefinition.findByIdAndDelete(options.id);
|
|
128
|
+
if (!script) throw new Error("Script not found");
|
|
129
|
+
return { success: true, id: options.id };
|
|
130
|
+
}
|
|
131
|
+
default:
|
|
132
|
+
throw new Error(`Unknown scripts command: ${options.command}`);
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const workflows = {
|
|
138
|
+
async execute(options) {
|
|
139
|
+
const Workflow = mongoose.model("Workflow");
|
|
140
|
+
switch (options.command) {
|
|
141
|
+
case "list": {
|
|
142
|
+
const workflows = await Workflow.find().lean();
|
|
143
|
+
return { items: workflows, count: workflows.length };
|
|
144
|
+
}
|
|
145
|
+
case "get": {
|
|
146
|
+
if (!options.id) throw new Error("Workflow ID is required");
|
|
147
|
+
const workflow = await Workflow.findById(options.id).lean();
|
|
148
|
+
if (!workflow) throw new Error("Workflow not found");
|
|
149
|
+
return workflow;
|
|
150
|
+
}
|
|
151
|
+
case "create": {
|
|
152
|
+
if (!options.name) throw new Error("--name is required");
|
|
153
|
+
const workflow = await Workflow.create({
|
|
154
|
+
name: options.name,
|
|
155
|
+
description: options.description || "",
|
|
156
|
+
enabled: true,
|
|
157
|
+
});
|
|
158
|
+
return workflow;
|
|
159
|
+
}
|
|
160
|
+
case "delete": {
|
|
161
|
+
if (!options.id) throw new Error("Workflow ID is required");
|
|
162
|
+
const workflow = await Workflow.findByIdAndDelete(options.id);
|
|
163
|
+
if (!workflow) throw new Error("Workflow not found");
|
|
164
|
+
return { success: true, id: options.id };
|
|
165
|
+
}
|
|
166
|
+
case "enable": {
|
|
167
|
+
if (!options.id) throw new Error("Workflow ID is required");
|
|
168
|
+
const workflow = await Workflow.findByIdAndUpdate(
|
|
169
|
+
options.id,
|
|
170
|
+
{ enabled: true },
|
|
171
|
+
{ new: true },
|
|
172
|
+
);
|
|
173
|
+
if (!workflow) throw new Error("Workflow not found");
|
|
174
|
+
return workflow;
|
|
175
|
+
}
|
|
176
|
+
case "disable": {
|
|
177
|
+
if (!options.id) throw new Error("Workflow ID is required");
|
|
178
|
+
const workflow = await Workflow.findByIdAndUpdate(
|
|
179
|
+
options.id,
|
|
180
|
+
{ enabled: false },
|
|
181
|
+
{ new: true },
|
|
182
|
+
);
|
|
183
|
+
if (!workflow) throw new Error("Workflow not found");
|
|
184
|
+
return workflow;
|
|
185
|
+
}
|
|
186
|
+
default:
|
|
187
|
+
throw new Error(`Unknown workflows command: ${options.command}`);
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const healthChecks = {
|
|
193
|
+
async execute(options) {
|
|
194
|
+
const HealthCheck = mongoose.model("HealthCheck");
|
|
195
|
+
switch (options.command) {
|
|
196
|
+
case "list": {
|
|
197
|
+
const checks = await HealthCheck.find().lean();
|
|
198
|
+
return { items: checks, count: checks.length };
|
|
199
|
+
}
|
|
200
|
+
case "get": {
|
|
201
|
+
if (!options.id) throw new Error("Health check ID is required");
|
|
202
|
+
const check = await HealthCheck.findById(options.id).lean();
|
|
203
|
+
if (!check) throw new Error("Health check not found");
|
|
204
|
+
return check;
|
|
205
|
+
}
|
|
206
|
+
case "create": {
|
|
207
|
+
if (!options.name) throw new Error("--name is required");
|
|
208
|
+
if (!options.value)
|
|
209
|
+
throw new Error("--value (cron expression) is required");
|
|
210
|
+
if (!options.key)
|
|
211
|
+
throw new Error(
|
|
212
|
+
"--key (checkType: http/script/internal) is required",
|
|
213
|
+
);
|
|
214
|
+
const check = await HealthCheck.create({
|
|
215
|
+
name: options.name,
|
|
216
|
+
description: options.description || "",
|
|
217
|
+
cronExpression: options.value,
|
|
218
|
+
checkType: options.key,
|
|
219
|
+
createdBy: "cli",
|
|
220
|
+
enabled: true,
|
|
221
|
+
});
|
|
222
|
+
return check;
|
|
223
|
+
}
|
|
224
|
+
case "delete": {
|
|
225
|
+
if (!options.id) throw new Error("Health check ID is required");
|
|
226
|
+
const check = await HealthCheck.findByIdAndDelete(options.id);
|
|
227
|
+
if (!check) throw new Error("Health check not found");
|
|
228
|
+
return { success: true, id: options.id };
|
|
229
|
+
}
|
|
230
|
+
default:
|
|
231
|
+
throw new Error(`Unknown health-checks command: ${options.command}`);
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
module.exports = { crons, errors, scripts, workflows, healthChecks };
|