plugin-git-manager 1.2.2 → 1.2.3
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/client/228.7588a0707cb3694a.js +9 -0
- package/dist/client/597.1698c0124e2f95ce.js +10 -0
- package/dist/client/906.bea20db91f34f5e6.js +10 -0
- package/dist/client/index.js +10 -1
- package/dist/externalVersion.js +15 -5
- package/dist/index.js +9 -0
- package/dist/locale/en-US.json +8 -1
- package/dist/locale/vi-VN.json +8 -1
- package/dist/server/actions/git-actions.js +43 -6
- package/dist/server/actions/gitlab-api.js +9 -0
- package/dist/server/actions/poller.js +9 -0
- package/dist/server/actions/review.js +9 -0
- package/dist/server/actions/role-permissions.js +145 -0
- package/dist/server/ai-tools.js +9 -0
- package/dist/server/collections/gitCodeReviews.js +9 -0
- package/dist/server/collections/gitRepositories.js +9 -0
- package/dist/server/collections/gitReviewFlows.js +9 -0
- package/dist/server/index.js +9 -0
- package/dist/server/migrations/20260508000000-add-auto-review-flow-id.js +9 -0
- package/dist/server/plugin.js +27 -1
- package/dist/server/poller.js +9 -0
- package/dist/server/utils/gitlab-url.js +9 -0
- package/dist/server/utils/redact.js +9 -0
- package/package.json +36 -36
- package/src/client/components/GitManagerSettings.tsx +1 -11
- package/src/client/components/RepositoryPermissions.tsx +130 -0
- package/src/client/index.tsx +36 -2
- package/src/locale/en-US.json +8 -1
- package/src/locale/vi-VN.json +8 -1
- package/src/server/__tests__/smoke.test.ts +17 -0
- package/src/server/actions/git-actions.ts +430 -430
- package/src/server/actions/role-permissions.ts +128 -0
- package/src/server/plugin.ts +46 -25
- package/dist/client/187.d5545b7cc8b90bfc.js +0 -1
- package/dist/client/ai-context.d.ts +0 -8
- package/dist/client/components/AIEmployeeSelect.d.ts +0 -13
- package/dist/client/components/CommitHistory.d.ts +0 -2
- package/dist/client/components/FileExplorer.d.ts +0 -2
- package/dist/client/components/GitManagerSettings.d.ts +0 -2
- package/dist/client/components/GitOperations.d.ts +0 -2
- package/dist/client/components/LLMModelSelect.d.ts +0 -10
- package/dist/client/components/LLMServiceSelect.d.ts +0 -9
- package/dist/client/components/MarkdownView.d.ts +0 -10
- package/dist/client/components/MergeRequests.d.ts +0 -2
- package/dist/client/components/PollingStatus.d.ts +0 -2
- package/dist/client/components/RepositoryConfig.d.ts +0 -2
- package/dist/client/components/ReviewFlows.d.ts +0 -2
- package/dist/client/components/ReviewHistory.d.ts +0 -4
- package/dist/client/components/RunReviewButton.d.ts +0 -31
- package/dist/client/context/GitManagerContext.d.ts +0 -26
- package/dist/client/index.d.ts +0 -5
- package/dist/client/locale.d.ts +0 -2
- package/dist/index.d.ts +0 -2
- package/dist/server/actions/git-actions.d.ts +0 -13
- package/dist/server/actions/gitlab-api.d.ts +0 -4
- package/dist/server/actions/poller.d.ts +0 -8
- package/dist/server/actions/review.d.ts +0 -40
- package/dist/server/ai-tools.d.ts +0 -10
- package/dist/server/collections/gitCodeReviews.d.ts +0 -2
- package/dist/server/collections/gitRepositories.d.ts +0 -2
- package/dist/server/collections/gitReviewFlows.d.ts +0 -2
- package/dist/server/index.d.ts +0 -2
- package/dist/server/migrations/20260508000000-add-auto-review-flow-id.d.ts +0 -6
- package/dist/server/plugin.d.ts +0 -12
- package/dist/server/poller.d.ts +0 -30
- package/dist/server/utils/gitlab-url.d.ts +0 -21
- package/dist/server/utils/redact.d.ts +0 -13
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __defProp = Object.defineProperty;
|
|
2
11
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
12
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __defProp = Object.defineProperty;
|
|
2
11
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
12
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var role_permissions_exports = {};
|
|
28
|
+
__export(role_permissions_exports, {
|
|
29
|
+
rolePermissions: () => rolePermissions,
|
|
30
|
+
updateRolePermissions: () => updateRolePermissions
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(role_permissions_exports);
|
|
33
|
+
function getRecordValue(record, key) {
|
|
34
|
+
return (record == null ? void 0 : record.get) ? record.get(key) : record == null ? void 0 : record[key];
|
|
35
|
+
}
|
|
36
|
+
async function rolePermissions(ctx, _next) {
|
|
37
|
+
var _a;
|
|
38
|
+
const currentRoles = Array.isArray((_a = ctx.state) == null ? void 0 : _a.currentRoles) ? ctx.state.currentRoles : [];
|
|
39
|
+
if (!currentRoles.includes("root")) {
|
|
40
|
+
const canAccessRoles = await ctx.app.acl.can({ roles: currentRoles, resource: "roles", action: "update" });
|
|
41
|
+
if (!canAccessRoles) return ctx.throw(403, "Permission denied");
|
|
42
|
+
}
|
|
43
|
+
const roleName = ctx.action.params.roleName;
|
|
44
|
+
if (!roleName) return ctx.throw(400, "roleName is required");
|
|
45
|
+
const resource = await ctx.db.getRepository("rolesResources").findOne({
|
|
46
|
+
filter: { roleName, name: "gitRepositories" }
|
|
47
|
+
});
|
|
48
|
+
if (!resource) {
|
|
49
|
+
ctx.body = { data: { read: [], write: [] } };
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const actions = await ctx.db.getRepository("rolesResourcesActions").find({
|
|
53
|
+
filter: { rolesResourceId: getRecordValue(resource, "id") },
|
|
54
|
+
appends: ["scope"]
|
|
55
|
+
});
|
|
56
|
+
const result = { read: [], write: [] };
|
|
57
|
+
for (const action of actions) {
|
|
58
|
+
const actionData = action.toJSON ? action.toJSON() : action;
|
|
59
|
+
const actionName = actionData.name;
|
|
60
|
+
if (result[actionName]) {
|
|
61
|
+
const scopeRow = actionData.scope;
|
|
62
|
+
const scope = (scopeRow == null ? void 0 : scopeRow.scope) || scopeRow;
|
|
63
|
+
try {
|
|
64
|
+
if (scope && scope.$and && scope.$and[0] && scope.$and[0].id) {
|
|
65
|
+
if (scope.$and[0].id.$in) {
|
|
66
|
+
result[actionName] = scope.$and[0].id.$in;
|
|
67
|
+
} else if (typeof scope.$and[0].id === "number" || typeof scope.$and[0].id === "string") {
|
|
68
|
+
result[actionName] = [scope.$and[0].id];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
} catch (e) {
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
ctx.body = result;
|
|
76
|
+
}
|
|
77
|
+
async function updateRolePermissions(ctx, _next) {
|
|
78
|
+
var _a, _b, _c;
|
|
79
|
+
const currentRoles = Array.isArray((_a = ctx.state) == null ? void 0 : _a.currentRoles) ? ctx.state.currentRoles : [];
|
|
80
|
+
if (!currentRoles.includes("root")) {
|
|
81
|
+
const canAccessRoles = await ctx.app.acl.can({ roles: currentRoles, resource: "roles", action: "update" });
|
|
82
|
+
if (!canAccessRoles) return ctx.throw(403, "Permission denied");
|
|
83
|
+
}
|
|
84
|
+
const payload = ctx.action.params.values || ctx.request.body || {};
|
|
85
|
+
const roleName = payload.roleName || ctx.action.params.roleName;
|
|
86
|
+
const permissions = payload.values || {};
|
|
87
|
+
if (!roleName) return ctx.throw(400, "roleName is required");
|
|
88
|
+
const resourceRepo = ctx.db.getRepository("rolesResources");
|
|
89
|
+
let resource = await resourceRepo.findOne({ filter: { roleName, name: "gitRepositories" } });
|
|
90
|
+
if (!resource) {
|
|
91
|
+
resource = await resourceRepo.create({
|
|
92
|
+
values: { roleName, name: "gitRepositories", usingActionsConfig: true }
|
|
93
|
+
});
|
|
94
|
+
} else if (!getRecordValue(resource, "usingActionsConfig")) {
|
|
95
|
+
await resource.update({ usingActionsConfig: true });
|
|
96
|
+
}
|
|
97
|
+
const rolesResourceId = getRecordValue(resource, "id");
|
|
98
|
+
const actionsRepo = ctx.db.getRepository("rolesResourcesActions");
|
|
99
|
+
for (const actionName of ["read", "write"]) {
|
|
100
|
+
const ids = permissions[actionName] || [];
|
|
101
|
+
const action = await actionsRepo.findOne({
|
|
102
|
+
filter: { rolesResourceId, name: actionName },
|
|
103
|
+
appends: ["scope"]
|
|
104
|
+
});
|
|
105
|
+
if (ids.length === 0) {
|
|
106
|
+
if (action) await action.destroy();
|
|
107
|
+
} else {
|
|
108
|
+
const scopeJson = { $and: [{ id: { $in: ids } }] };
|
|
109
|
+
if (action) {
|
|
110
|
+
const actionData = action.toJSON ? action.toJSON() : action;
|
|
111
|
+
const actionScope = actionData.scope;
|
|
112
|
+
const actionScopeId = getRecordValue(actionScope, "id") || actionData.scopeId || getRecordValue(action, "scopeId");
|
|
113
|
+
if (actionScopeId) {
|
|
114
|
+
await ctx.db.getRepository("rolesResourcesScopes").update({
|
|
115
|
+
filterByTk: actionScopeId,
|
|
116
|
+
values: { scope: scopeJson }
|
|
117
|
+
});
|
|
118
|
+
} else {
|
|
119
|
+
const newScope = await ctx.db.getRepository("rolesResourcesScopes").create({
|
|
120
|
+
values: { scope: scopeJson }
|
|
121
|
+
});
|
|
122
|
+
await action.update({ scopeId: getRecordValue(newScope, "id") });
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
const newScope = await ctx.db.getRepository("rolesResourcesScopes").create({
|
|
126
|
+
values: { scope: scopeJson }
|
|
127
|
+
});
|
|
128
|
+
await actionsRepo.create({
|
|
129
|
+
values: { rolesResourceId, name: actionName, scopeId: getRecordValue(newScope, "id") }
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
await resource.writeToACL({ acl: ctx.app.acl });
|
|
136
|
+
} catch (e) {
|
|
137
|
+
(_c = (_b = ctx.logger) == null ? void 0 : _b.warn) == null ? void 0 : _c.call(_b, "[git-manager] Failed to write resource to ACL memory cache:", e);
|
|
138
|
+
}
|
|
139
|
+
ctx.body = { data: "ok" };
|
|
140
|
+
}
|
|
141
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
142
|
+
0 && (module.exports = {
|
|
143
|
+
rolePermissions,
|
|
144
|
+
updateRolePermissions
|
|
145
|
+
});
|
package/dist/server/ai-tools.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __create = Object.create;
|
|
2
11
|
var __defProp = Object.defineProperty;
|
|
3
12
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __defProp = Object.defineProperty;
|
|
2
11
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
12
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __defProp = Object.defineProperty;
|
|
2
11
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
12
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __defProp = Object.defineProperty;
|
|
2
11
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
12
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
package/dist/server/index.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __create = Object.create;
|
|
2
11
|
var __defProp = Object.defineProperty;
|
|
3
12
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __defProp = Object.defineProperty;
|
|
2
11
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
12
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
package/dist/server/plugin.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __create = Object.create;
|
|
2
11
|
var __defProp = Object.defineProperty;
|
|
3
12
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -39,6 +48,7 @@ var gitActions = __toESM(require("./actions/git-actions"));
|
|
|
39
48
|
var gitlabApi = __toESM(require("./actions/gitlab-api"));
|
|
40
49
|
var reviewActions = __toESM(require("./actions/review"));
|
|
41
50
|
var pollerActions = __toESM(require("./actions/poller"));
|
|
51
|
+
var rolePermissionsActions = __toESM(require("./actions/role-permissions"));
|
|
42
52
|
var import_review = require("./actions/review");
|
|
43
53
|
var import_ai_tools = require("./ai-tools");
|
|
44
54
|
var import_poller = require("./poller");
|
|
@@ -81,7 +91,9 @@ class PluginGitManagerServer extends import_server.Plugin {
|
|
|
81
91
|
reviewApprovePost: reviewActions.reviewApprovePost,
|
|
82
92
|
reviewReject: reviewActions.reviewReject,
|
|
83
93
|
pollNow: pollerActions.pollNow,
|
|
84
|
-
pollerStatus: pollerActions.pollerStatus
|
|
94
|
+
pollerStatus: pollerActions.pollerStatus,
|
|
95
|
+
rolePermissions: rolePermissionsActions.rolePermissions,
|
|
96
|
+
updateRolePermissions: rolePermissionsActions.updateRolePermissions
|
|
85
97
|
}
|
|
86
98
|
});
|
|
87
99
|
this.app.use(async (ctx, next) => {
|
|
@@ -166,6 +178,20 @@ class PluginGitManagerServer extends import_server.Plugin {
|
|
|
166
178
|
"gitManager:pollNow"
|
|
167
179
|
]
|
|
168
180
|
});
|
|
181
|
+
this.app.acl.registerSnippet({
|
|
182
|
+
name: `pm.${this.name}.repositories`,
|
|
183
|
+
actions: [
|
|
184
|
+
"gitRepositories:*"
|
|
185
|
+
]
|
|
186
|
+
});
|
|
187
|
+
this.app.acl.registerSnippet({
|
|
188
|
+
name: `pm.${this.name}.manage`,
|
|
189
|
+
actions: [
|
|
190
|
+
`pm.${this.name}.repositories`,
|
|
191
|
+
`pm.${this.name}.read`,
|
|
192
|
+
`pm.${this.name}.write`
|
|
193
|
+
]
|
|
194
|
+
});
|
|
169
195
|
this.app.resourceManager.use(async (ctx, next) => {
|
|
170
196
|
var _a, _b, _c, _d, _e;
|
|
171
197
|
if (((_a = ctx.action) == null ? void 0 : _a.resourceName) === "gitRepositories" && ["create", "update"].includes((_b = ctx.action) == null ? void 0 : _b.actionName)) {
|
package/dist/server/poller.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __defProp = Object.defineProperty;
|
|
2
11
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
12
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __defProp = Object.defineProperty;
|
|
2
11
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
12
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __defProp = Object.defineProperty;
|
|
2
11
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
12
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
package/package.json
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "plugin-git-manager",
|
|
3
|
-
"displayName": "Git Manager",
|
|
4
|
-
"displayName.zh-CN": "Git 管理器",
|
|
5
|
-
"description": "Manage Git repositories with PAT authentication - pull, push, fetch, diff, file browsing",
|
|
6
|
-
"version": "1.2.
|
|
7
|
-
"license": "Apache-2.0",
|
|
8
|
-
"main": "dist/server/index.js",
|
|
9
|
-
"files": [
|
|
10
|
-
"dist",
|
|
11
|
-
"src",
|
|
12
|
-
"client.js",
|
|
13
|
-
"server.js",
|
|
14
|
-
"client.d.ts",
|
|
15
|
-
"server.d.ts"
|
|
16
|
-
],
|
|
17
|
-
"nocobase": {
|
|
18
|
-
"supportedVersions": [
|
|
19
|
-
"2.x"
|
|
20
|
-
],
|
|
21
|
-
"editionLevel": 0
|
|
22
|
-
},
|
|
23
|
-
"peerDependencies": {
|
|
24
|
-
"@nocobase/client": "2.x",
|
|
25
|
-
"@nocobase/server": "2.x",
|
|
26
|
-
"@nocobase/database": "2.x",
|
|
27
|
-
"@nocobase/test": "2.x"
|
|
28
|
-
},
|
|
29
|
-
"optionalPeerDependencies": {
|
|
30
|
-
"@nocobase/ai": "2.x",
|
|
31
|
-
"@nocobase/plugin-ai": "2.x",
|
|
32
|
-
"@nocobase/plugin-field-markdown-vditor": "2.x"
|
|
33
|
-
},
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"simple-git": "^3.27.0"
|
|
36
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "plugin-git-manager",
|
|
3
|
+
"displayName": "Git Manager",
|
|
4
|
+
"displayName.zh-CN": "Git 管理器",
|
|
5
|
+
"description": "Manage Git repositories with PAT authentication - pull, push, fetch, diff, file browsing",
|
|
6
|
+
"version": "1.2.3",
|
|
7
|
+
"license": "Apache-2.0",
|
|
8
|
+
"main": "dist/server/index.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"src",
|
|
12
|
+
"client.js",
|
|
13
|
+
"server.js",
|
|
14
|
+
"client.d.ts",
|
|
15
|
+
"server.d.ts"
|
|
16
|
+
],
|
|
17
|
+
"nocobase": {
|
|
18
|
+
"supportedVersions": [
|
|
19
|
+
"2.x"
|
|
20
|
+
],
|
|
21
|
+
"editionLevel": 0
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"@nocobase/client": "2.x",
|
|
25
|
+
"@nocobase/server": "2.x",
|
|
26
|
+
"@nocobase/database": "2.x",
|
|
27
|
+
"@nocobase/test": "2.x"
|
|
28
|
+
},
|
|
29
|
+
"optionalPeerDependencies": {
|
|
30
|
+
"@nocobase/ai": "2.x",
|
|
31
|
+
"@nocobase/plugin-ai": "2.x",
|
|
32
|
+
"@nocobase/plugin-field-markdown-vditor": "2.x"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"simple-git": "^3.27.0"
|
|
36
|
+
}
|
|
37
37
|
}
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
RobotOutlined, AuditOutlined, ClockCircleOutlined,
|
|
6
6
|
} from '@ant-design/icons';
|
|
7
7
|
import { GitManagerProvider, useGitManager } from '../context/GitManagerContext';
|
|
8
|
-
import { RepositoryConfig } from './RepositoryConfig';
|
|
9
8
|
import { FileExplorer } from './FileExplorer';
|
|
10
9
|
import { CommitHistory } from './CommitHistory';
|
|
11
10
|
import { MergeRequests } from './MergeRequests';
|
|
@@ -76,18 +75,9 @@ const GitManagerContent: React.FC = () => {
|
|
|
76
75
|
|
|
77
76
|
<Tabs
|
|
78
77
|
type="card"
|
|
79
|
-
defaultActiveKey="
|
|
78
|
+
defaultActiveKey="explorer"
|
|
80
79
|
destroyInactiveTabPane
|
|
81
80
|
items={[
|
|
82
|
-
{
|
|
83
|
-
key: 'repos',
|
|
84
|
-
label: (
|
|
85
|
-
<span>
|
|
86
|
-
<DatabaseOutlined /> {t('Repositories')}
|
|
87
|
-
</span>
|
|
88
|
-
),
|
|
89
|
-
children: <RepositoryConfig />,
|
|
90
|
-
},
|
|
91
81
|
{
|
|
92
82
|
key: 'explorer',
|
|
93
83
|
label: (
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { useAPIClient } from '@nocobase/client';
|
|
3
|
+
import { Table, Checkbox, Spin, Typography, message } from 'antd';
|
|
4
|
+
|
|
5
|
+
export const RepositoryPermissions = ({ activeRole }) => {
|
|
6
|
+
const api = useAPIClient();
|
|
7
|
+
const [loading, setLoading] = useState(false);
|
|
8
|
+
const [repositories, setRepositories] = useState([]);
|
|
9
|
+
const [permissions, setPermissions] = useState({ read: [], write: [] });
|
|
10
|
+
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (activeRole?.name) {
|
|
13
|
+
loadData();
|
|
14
|
+
}
|
|
15
|
+
}, [activeRole?.name]);
|
|
16
|
+
|
|
17
|
+
const loadData = async () => {
|
|
18
|
+
setLoading(true);
|
|
19
|
+
try {
|
|
20
|
+
const [repoRes, permRes] = await Promise.all([
|
|
21
|
+
api.request({
|
|
22
|
+
resource: 'gitRepositories',
|
|
23
|
+
action: 'list',
|
|
24
|
+
params: { paginate: false, sort: ['name'] },
|
|
25
|
+
}),
|
|
26
|
+
api.request({
|
|
27
|
+
url: 'gitManager:rolePermissions',
|
|
28
|
+
method: 'get',
|
|
29
|
+
params: { roleName: activeRole.name },
|
|
30
|
+
}),
|
|
31
|
+
]);
|
|
32
|
+
const fetchedPerms = permRes?.data?.data || permRes?.data || { read: [], write: [] };
|
|
33
|
+
setRepositories(repoRes?.data?.data || []);
|
|
34
|
+
setPermissions({
|
|
35
|
+
read: fetchedPerms.read || [],
|
|
36
|
+
write: fetchedPerms.write || [],
|
|
37
|
+
});
|
|
38
|
+
} catch (e) {
|
|
39
|
+
console.error(e);
|
|
40
|
+
message.error('Failed to load repository permissions');
|
|
41
|
+
}
|
|
42
|
+
setLoading(false);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const handleToggle = async (repositoryId: number, actionName: string, checked: boolean) => {
|
|
46
|
+
const currentList = permissions[actionName] || [];
|
|
47
|
+
const newList = checked
|
|
48
|
+
? [...new Set([...currentList, repositoryId])]
|
|
49
|
+
: currentList.filter((id: number) => id !== repositoryId);
|
|
50
|
+
|
|
51
|
+
const newPermissions = { ...permissions, [actionName]: newList };
|
|
52
|
+
const prevPermissions = permissions;
|
|
53
|
+
setPermissions(newPermissions);
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
await api.request({
|
|
57
|
+
url: 'gitManager:updateRolePermissions',
|
|
58
|
+
method: 'post',
|
|
59
|
+
data: {
|
|
60
|
+
roleName: activeRole.name,
|
|
61
|
+
values: newPermissions,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
} catch {
|
|
65
|
+
message.error('Failed to update permissions');
|
|
66
|
+
setPermissions(prevPermissions);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const columns = [
|
|
71
|
+
{
|
|
72
|
+
title: 'Repository Name',
|
|
73
|
+
dataIndex: 'name',
|
|
74
|
+
key: 'name',
|
|
75
|
+
render: (text: string) => <Typography.Text strong>{text}</Typography.Text>,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
title: 'Repository URL',
|
|
79
|
+
dataIndex: 'repoUrl',
|
|
80
|
+
key: 'repoUrl',
|
|
81
|
+
ellipsis: true,
|
|
82
|
+
render: (text: string) => <Typography.Text type="secondary">{text}</Typography.Text>,
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
title: 'Read (List, Browse Files, View History)',
|
|
86
|
+
key: 'read',
|
|
87
|
+
width: 100,
|
|
88
|
+
render: (_: any, record: any) => (
|
|
89
|
+
<Checkbox
|
|
90
|
+
checked={(permissions.read || []).includes(record.id)}
|
|
91
|
+
onChange={(e) => handleToggle(record.id, 'read', e.target.checked)}
|
|
92
|
+
/>
|
|
93
|
+
),
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
title: 'Write (Clone, Pull, Push, Review)',
|
|
97
|
+
key: 'write',
|
|
98
|
+
width: 100,
|
|
99
|
+
render: (_: any, record: any) => (
|
|
100
|
+
<Checkbox
|
|
101
|
+
checked={(permissions.write || []).includes(record.id)}
|
|
102
|
+
onChange={(e) => handleToggle(record.id, 'write', e.target.checked)}
|
|
103
|
+
/>
|
|
104
|
+
),
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
if (loading && !repositories.length) {
|
|
109
|
+
return <Spin style={{ display: 'block', margin: '40px auto' }} />;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<div style={{ padding: 16 }}>
|
|
114
|
+
<div style={{ marginBottom: 16 }}>
|
|
115
|
+
<Typography.Text type="secondary">
|
|
116
|
+
Configure access permissions for each repository for the role{' '}
|
|
117
|
+
<Typography.Text strong>{activeRole?.title || activeRole?.name}</Typography.Text>.
|
|
118
|
+
</Typography.Text>
|
|
119
|
+
</div>
|
|
120
|
+
<Table
|
|
121
|
+
dataSource={repositories}
|
|
122
|
+
columns={columns}
|
|
123
|
+
rowKey="id"
|
|
124
|
+
pagination={false}
|
|
125
|
+
size="small"
|
|
126
|
+
bordered
|
|
127
|
+
/>
|
|
128
|
+
</div>
|
|
129
|
+
);
|
|
130
|
+
};
|
package/src/client/index.tsx
CHANGED
|
@@ -10,13 +10,33 @@ const GitManagerSettings = React.lazy(() =>
|
|
|
10
10
|
import('./components/GitManagerSettings').then((m) => ({ default: m.GitManagerSettings })),
|
|
11
11
|
);
|
|
12
12
|
|
|
13
|
+
const RepositoryConfig = React.lazy(() =>
|
|
14
|
+
import('./components/RepositoryConfig').then((m) => ({ default: m.RepositoryConfig })),
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
import PluginACLClient from '@nocobase/plugin-acl/client';
|
|
18
|
+
import { RepositoryPermissions } from './components/RepositoryPermissions';
|
|
19
|
+
|
|
13
20
|
export class PluginGitManagerClient extends Plugin {
|
|
14
21
|
async load() {
|
|
15
|
-
|
|
22
|
+
// Parent group with no direct component — acts as a category in settings
|
|
23
|
+
this.app.pluginSettingsManager.add('git-manager', {
|
|
16
24
|
title: (this as any).t('Git Manager'),
|
|
17
25
|
icon: 'BranchesOutlined',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Repositories config — separate group for ACL-granular access
|
|
29
|
+
this.app.pluginSettingsManager.add('git-manager.repositories', {
|
|
30
|
+
title: (this as any).t('Repositories'),
|
|
31
|
+
Component: RepositoryConfig,
|
|
32
|
+
aclSnippet: `pm.plugin-git-manager.repositories`,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Full management — requires full plugin permission
|
|
36
|
+
this.app.pluginSettingsManager.add('git-manager.manage', {
|
|
37
|
+
title: (this as any).t('Manage'),
|
|
18
38
|
Component: GitManagerSettings,
|
|
19
|
-
aclSnippet:
|
|
39
|
+
aclSnippet: `pm.plugin-git-manager.manage`,
|
|
20
40
|
});
|
|
21
41
|
|
|
22
42
|
const aiManager = ((this as any).app as any).aiManager;
|
|
@@ -25,6 +45,20 @@ export class PluginGitManagerClient extends Plugin {
|
|
|
25
45
|
aiManager.registerWorkContext('git-merge-request', GitMergeRequestWorkContext);
|
|
26
46
|
aiManager.registerWorkContext('git-commit', GitCommitWorkContext);
|
|
27
47
|
}
|
|
48
|
+
|
|
49
|
+
const aclPlugin = this.app.pm.get(PluginACLClient);
|
|
50
|
+
if (aclPlugin) {
|
|
51
|
+
aclPlugin.settingsUI.addPermissionsTab(({ t, TabLayout, activeRole }) => ({
|
|
52
|
+
key: 'git-manager',
|
|
53
|
+
label: 'Git Manager',
|
|
54
|
+
sort: 25,
|
|
55
|
+
children: (
|
|
56
|
+
<TabLayout>
|
|
57
|
+
<RepositoryPermissions activeRole={activeRole} />
|
|
58
|
+
</TabLayout>
|
|
59
|
+
),
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
28
62
|
}
|
|
29
63
|
}
|
|
30
64
|
|
package/src/locale/en-US.json
CHANGED
|
@@ -186,5 +186,12 @@
|
|
|
186
186
|
"Only flows with automatic trigger modes are shown": "Only flows with automatic trigger modes are shown",
|
|
187
187
|
"Fallback": "Fallback",
|
|
188
188
|
"AI employee not found": "AI employee not found",
|
|
189
|
-
"Failed to open AI chat": "Failed to open AI chat"
|
|
189
|
+
"Failed to open AI chat": "Failed to open AI chat",
|
|
190
|
+
"Manage": "Manage",
|
|
191
|
+
"Repository Permissions": "Repository Permissions",
|
|
192
|
+
"Read (List, Browse Files, View History)": "Read (List, Browse Files, View History)",
|
|
193
|
+
"Write (Clone, Pull, Push, Review)": "Write (Clone, Pull, Push, Review)",
|
|
194
|
+
"Configure access permissions for each repository for the role {{roleName}}": "Configure access permissions for each repository for the role {{roleName}}",
|
|
195
|
+
"Failed to load repository permissions": "Failed to load repository permissions",
|
|
196
|
+
"Failed to update permissions": "Failed to update permissions"
|
|
190
197
|
}
|
package/src/locale/vi-VN.json
CHANGED
|
@@ -179,5 +179,12 @@
|
|
|
179
179
|
"new": "mới",
|
|
180
180
|
"Reviewed SHA": "SHA đã đánh giá",
|
|
181
181
|
"Latest SHA": "SHA mới nhất",
|
|
182
|
-
"All triggers": "Tất cả nguồn"
|
|
182
|
+
"All triggers": "Tất cả nguồn",
|
|
183
|
+
"Manage": "Quản lý",
|
|
184
|
+
"Repository Permissions": "Phân quyền kho mã nguồn",
|
|
185
|
+
"Read (List, Browse Files, View History)": "Đọc (Xem danh sách, Duyệt tệp, Xem lịch sử)",
|
|
186
|
+
"Write (Clone, Pull, Push, Review)": "Ghi (Sao chép, Kéo về, Đẩy lên, Đánh giá)",
|
|
187
|
+
"Configure access permissions for each repository for the role {{roleName}}": "Cấu hình quyền truy cập cho từng kho mã nguồn đối với vai trò {{roleName}}",
|
|
188
|
+
"Failed to load repository permissions": "Không thể tải phân quyền kho mã nguồn",
|
|
189
|
+
"Failed to update permissions": "Cập nhật phân quyền thất bại"
|
|
183
190
|
}
|