@nocobase/plugin-api-keys 0.10.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/README.zh-CN.md +9 -0
- package/client.d.ts +4 -0
- package/client.js +30 -0
- package/docs/en-US/changelog.md +1 -0
- package/docs/en-US/index.md +9 -0
- package/docs/en-US/tabs.json +14 -0
- package/docs/en-US/usage.md +19 -0
- package/docs/zh-CN/changelog.md +1 -0
- package/docs/zh-CN/index.md +10 -0
- package/docs/zh-CN/tabs.json +14 -0
- package/docs/zh-CN/usage.md +19 -0
- package/lib/client/Configuration/ExpiresSelect.d.ts +3 -0
- package/lib/client/Configuration/ExpiresSelect.js +131 -0
- package/lib/client/Configuration/index.d.ts +2 -0
- package/lib/client/Configuration/index.js +47 -0
- package/lib/client/Configuration/roles.d.ts +3 -0
- package/lib/client/Configuration/roles.js +20 -0
- package/lib/client/Configuration/schema.d.ts +2 -0
- package/lib/client/Configuration/schema.js +319 -0
- package/lib/client/index.d.ts +3 -0
- package/lib/client/index.js +46 -0
- package/lib/client/locale/en-US.d.ts +2 -0
- package/lib/client/locale/en-US.js +9 -0
- package/lib/client/locale/index.d.ts +2 -0
- package/lib/client/locale/index.js +32 -0
- package/lib/client/locale/zh-CN.d.ts +19 -0
- package/lib/client/locale/zh-CN.js +26 -0
- package/lib/collections/api-keys.d.ts +3 -0
- package/lib/collections/api-keys.js +87 -0
- package/lib/collections/index.d.ts +1 -0
- package/lib/collections/index.js +13 -0
- package/lib/constants.d.ts +1 -0
- package/lib/constants.js +8 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +13 -0
- package/lib/locale.d.ts +1 -0
- package/lib/locale.js +10 -0
- package/lib/server/actions/api-keys.d.ts +3 -0
- package/lib/server/actions/api-keys.js +71 -0
- package/lib/server/index.d.ts +1 -0
- package/lib/server/index.js +13 -0
- package/lib/server/locale/en-US.d.ts +2 -0
- package/lib/server/locale/en-US.js +8 -0
- package/lib/server/locale/index.d.ts +2 -0
- package/lib/server/locale/index.js +20 -0
- package/lib/server/locale/zh-CN.d.ts +4 -0
- package/lib/server/locale/zh-CN.js +10 -0
- package/lib/server/plugin.d.ts +10 -0
- package/lib/server/plugin.js +77 -0
- package/package.json +24 -0
- package/server.d.ts +4 -0
- package/server.js +30 -0
- package/src/client/Configuration/ExpiresSelect.tsx +80 -0
- package/src/client/Configuration/index.tsx +18 -0
- package/src/client/Configuration/roles.ts +9 -0
- package/src/client/Configuration/schema.tsx +264 -0
- package/src/client/index.tsx +29 -0
- package/src/client/locale/en-US.ts +3 -0
- package/src/client/locale/index.ts +13 -0
- package/src/client/locale/zh-CN.ts +21 -0
- package/src/collections/api-keys.ts +95 -0
- package/src/collections/index.ts +1 -0
- package/src/constants.ts +1 -0
- package/src/index.ts +1 -0
- package/src/locale.ts +5 -0
- package/src/server/__tests__/actions.test.ts +181 -0
- package/src/server/actions/api-keys.ts +49 -0
- package/src/server/index.ts +1 -0
- package/src/server/locale/en-US.ts +1 -0
- package/src/server/locale/index.ts +2 -0
- package/src/server/locale/zh-CN.ts +3 -0
- package/src/server/plugin.ts +53 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.create = create;
|
|
7
|
+
exports.destroy = destroy;
|
|
8
|
+
function _actions() {
|
|
9
|
+
const data = _interopRequireDefault(require("@nocobase/actions"));
|
|
10
|
+
_actions = function _actions() {
|
|
11
|
+
return data;
|
|
12
|
+
};
|
|
13
|
+
return data;
|
|
14
|
+
}
|
|
15
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
16
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
17
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
18
|
+
function create(_x, _x2) {
|
|
19
|
+
return _create.apply(this, arguments);
|
|
20
|
+
}
|
|
21
|
+
function _create() {
|
|
22
|
+
_create = _asyncToGenerator(function* (ctx, next) {
|
|
23
|
+
const values = ctx.action.params.values;
|
|
24
|
+
if (!values.role) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const repository = ctx.db.getRepository('users.roles', ctx.auth.user.id);
|
|
28
|
+
const role = yield repository.findOne({
|
|
29
|
+
filter: {
|
|
30
|
+
name: values.role.name
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
if (!role) {
|
|
34
|
+
throw ctx.throw(400, ctx.t('Role not found'));
|
|
35
|
+
}
|
|
36
|
+
const token = ctx.app.authManager.jwt.sign({
|
|
37
|
+
userId: ctx.auth.user.id,
|
|
38
|
+
roleName: role.name
|
|
39
|
+
}, {
|
|
40
|
+
expiresIn: values.expiresIn
|
|
41
|
+
});
|
|
42
|
+
ctx.action.mergeParams({
|
|
43
|
+
values: {
|
|
44
|
+
token
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return _actions().default.create(ctx, /*#__PURE__*/_asyncToGenerator(function* () {
|
|
48
|
+
ctx.body = {
|
|
49
|
+
token
|
|
50
|
+
};
|
|
51
|
+
yield next();
|
|
52
|
+
}));
|
|
53
|
+
});
|
|
54
|
+
return _create.apply(this, arguments);
|
|
55
|
+
}
|
|
56
|
+
function destroy(_x3, _x4) {
|
|
57
|
+
return _destroy.apply(this, arguments);
|
|
58
|
+
}
|
|
59
|
+
function _destroy() {
|
|
60
|
+
_destroy = _asyncToGenerator(function* (ctx, next) {
|
|
61
|
+
const repo = ctx.db.getRepository(ctx.action.resourceName);
|
|
62
|
+
const filterByTk = ctx.action.params.filterByTk;
|
|
63
|
+
const data = yield repo.findById(filterByTk);
|
|
64
|
+
const token = data === null || data === void 0 ? void 0 : data.get('token');
|
|
65
|
+
if (token) {
|
|
66
|
+
yield ctx.app.authManager.jwt.block(token);
|
|
67
|
+
}
|
|
68
|
+
return _actions().default.destroy(ctx, next);
|
|
69
|
+
});
|
|
70
|
+
return _destroy.apply(this, arguments);
|
|
71
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './plugin';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "default", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function get() {
|
|
9
|
+
return _plugin.default;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
var _plugin = _interopRequireDefault(require("./plugin"));
|
|
13
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "enUS", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function get() {
|
|
9
|
+
return _enUS.default;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "zhCN", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function get() {
|
|
15
|
+
return _zhCN.default;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
var _enUS = _interopRequireDefault(require("./en-US"));
|
|
19
|
+
var _zhCN = _interopRequireDefault(require("./zh-CN"));
|
|
20
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Plugin } from '@nocobase/server';
|
|
2
|
+
export interface ApiKeysPluginConfig {
|
|
3
|
+
name?: string;
|
|
4
|
+
}
|
|
5
|
+
export default class ApiKeysPlugin extends Plugin<ApiKeysPluginConfig> {
|
|
6
|
+
resourceName: string;
|
|
7
|
+
constructor(app: any, options: any);
|
|
8
|
+
beforeLoad(): Promise<void>;
|
|
9
|
+
load(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
function _server() {
|
|
8
|
+
const data = require("@nocobase/server");
|
|
9
|
+
_server = function _server() {
|
|
10
|
+
return data;
|
|
11
|
+
};
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
function _path() {
|
|
15
|
+
const data = require("path");
|
|
16
|
+
_path = function _path() {
|
|
17
|
+
return data;
|
|
18
|
+
};
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
21
|
+
var _constants = require("../constants");
|
|
22
|
+
var _apiKeys = require("./actions/api-keys");
|
|
23
|
+
var _locale = require("./locale");
|
|
24
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
25
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
26
|
+
class ApiKeysPlugin extends _server().Plugin {
|
|
27
|
+
constructor(app, options) {
|
|
28
|
+
super(app, options);
|
|
29
|
+
this.resourceName = 'apiKeys';
|
|
30
|
+
}
|
|
31
|
+
beforeLoad() {
|
|
32
|
+
var _this = this;
|
|
33
|
+
return _asyncToGenerator(function* () {
|
|
34
|
+
_this.app.i18n.addResources('zh-CN', _constants.NAMESPACE, _locale.zhCN);
|
|
35
|
+
_this.app.i18n.addResources('en-US', _constants.NAMESPACE, _locale.enUS);
|
|
36
|
+
yield _this.app.resourcer.define({
|
|
37
|
+
name: _this.resourceName,
|
|
38
|
+
actions: {
|
|
39
|
+
create: _apiKeys.create,
|
|
40
|
+
destroy: _apiKeys.destroy
|
|
41
|
+
},
|
|
42
|
+
only: ['list', 'create', 'destroy']
|
|
43
|
+
});
|
|
44
|
+
_this.app.acl.registerSnippet({
|
|
45
|
+
name: ['pm', _this.name, 'configuration'].join('.'),
|
|
46
|
+
actions: ['apiKeys:list', 'apiKeys:create', 'apiKeys:destroy']
|
|
47
|
+
});
|
|
48
|
+
})();
|
|
49
|
+
}
|
|
50
|
+
load() {
|
|
51
|
+
var _this2 = this;
|
|
52
|
+
return _asyncToGenerator(function* () {
|
|
53
|
+
yield _this2.db.import({
|
|
54
|
+
directory: (0, _path().resolve)(__dirname, '../collections')
|
|
55
|
+
});
|
|
56
|
+
_this2.app.resourcer.use( /*#__PURE__*/function () {
|
|
57
|
+
var _ref = _asyncToGenerator(function* (ctx, next) {
|
|
58
|
+
const _ctx$action$params = ctx.action.params,
|
|
59
|
+
resourceName = _ctx$action$params.resourceName,
|
|
60
|
+
actionName = _ctx$action$params.actionName;
|
|
61
|
+
if (resourceName == _this2.resourceName && ['list', 'destroy'].includes(actionName)) {
|
|
62
|
+
ctx.action.mergeParams({
|
|
63
|
+
filter: {
|
|
64
|
+
createdById: ctx.auth.user.id
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
yield next();
|
|
69
|
+
});
|
|
70
|
+
return function (_x, _x2) {
|
|
71
|
+
return _ref.apply(this, arguments);
|
|
72
|
+
};
|
|
73
|
+
}());
|
|
74
|
+
})();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.default = ApiKeysPlugin;
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nocobase/plugin-api-keys",
|
|
3
|
+
"displayName": "API keys",
|
|
4
|
+
"displayName.zh-CN": "API keys",
|
|
5
|
+
"description": "Allow users to use API key to access NocoBase's api",
|
|
6
|
+
"description.zh-CN": "允许用户使用 API key 访问 NocoBase 的 api",
|
|
7
|
+
"version": "0.10.1-alpha.1",
|
|
8
|
+
"license": "AGPL-3.0",
|
|
9
|
+
"main": "./lib/index.js",
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@nocobase/actions": "0.10.1-alpha.1",
|
|
13
|
+
"@nocobase/database": "0.10.1-alpha.1",
|
|
14
|
+
"@nocobase/resourcer": "0.10.1-alpha.1",
|
|
15
|
+
"@nocobase/server": "0.10.1-alpha.1",
|
|
16
|
+
"@nocobase/utils": "0.10.1-alpha.1",
|
|
17
|
+
"jsonwebtoken": "^8.5.1"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@nocobase/test": "0.10.1-alpha.1",
|
|
21
|
+
"@types/jsonwebtoken": "^8.5.8"
|
|
22
|
+
},
|
|
23
|
+
"gitHead": "8f415f5e0ee2e72d681f9ab16af5911b52c374a9"
|
|
24
|
+
}
|
package/server.d.ts
ADDED
package/server.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
4
|
+
|
|
5
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
6
|
+
|
|
7
|
+
var _index = _interopRequireWildcard(require("./lib/server"));
|
|
8
|
+
|
|
9
|
+
Object.defineProperty(exports, "__esModule", {
|
|
10
|
+
value: true
|
|
11
|
+
});
|
|
12
|
+
var _exportNames = {};
|
|
13
|
+
Object.defineProperty(exports, "default", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function get() {
|
|
16
|
+
return _index.default;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
Object.keys(_index).forEach(function (key) {
|
|
21
|
+
if (key === "default" || key === "__esModule") return;
|
|
22
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
23
|
+
if (key in exports && exports[key] === _index[key]) return;
|
|
24
|
+
Object.defineProperty(exports, key, {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function get() {
|
|
27
|
+
return _index[key];
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { css } from '@emotion/css';
|
|
2
|
+
import { connect, mapProps, mapReadPretty } from '@formily/react';
|
|
3
|
+
import { useRecord } from '@nocobase/client';
|
|
4
|
+
import { useBoolean } from 'ahooks';
|
|
5
|
+
import { DatePicker, Select, Space, Typography } from 'antd';
|
|
6
|
+
import moment from 'moment';
|
|
7
|
+
import React, { useMemo } from 'react';
|
|
8
|
+
import { useTranslation } from '../locale';
|
|
9
|
+
|
|
10
|
+
const TOMORROW = moment().add(1, 'days');
|
|
11
|
+
|
|
12
|
+
const spaceCSS = css`
|
|
13
|
+
width: 100%;
|
|
14
|
+
& > .ant-space-item {
|
|
15
|
+
flex: 1;
|
|
16
|
+
}
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
const InternalExpiresSelect = (props) => {
|
|
20
|
+
const { onChange } = props;
|
|
21
|
+
const [isCustom, { toggle: toggleShowDatePicker, setFalse }] = useBoolean();
|
|
22
|
+
|
|
23
|
+
const onSelectChange = (v) => {
|
|
24
|
+
if (v === 'custom') {
|
|
25
|
+
onChange('1d');
|
|
26
|
+
return toggleShowDatePicker();
|
|
27
|
+
} else {
|
|
28
|
+
setFalse();
|
|
29
|
+
onChange(v);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const onDatePickerChange = (v: moment.Moment) => {
|
|
34
|
+
v = v.milliseconds(0).second(0);
|
|
35
|
+
const NOW = moment().milliseconds(0).seconds(0);
|
|
36
|
+
const value = `${v.diff(NOW, 'd')}d`;
|
|
37
|
+
onChange(value);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Space className={spaceCSS}>
|
|
42
|
+
<Select {...props} value={isCustom ? 'custom' : props.value} onChange={onSelectChange}></Select>
|
|
43
|
+
{isCustom ? (
|
|
44
|
+
<DatePicker
|
|
45
|
+
disabledDate={(time) => {
|
|
46
|
+
return time.isSameOrBefore();
|
|
47
|
+
}}
|
|
48
|
+
defaultValue={TOMORROW}
|
|
49
|
+
onChange={onDatePickerChange}
|
|
50
|
+
showToday={false}
|
|
51
|
+
allowClear={false}
|
|
52
|
+
/>
|
|
53
|
+
) : null}
|
|
54
|
+
</Space>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const ReadPretty = () => {
|
|
59
|
+
const { expiresIn, createdAt } = useRecord();
|
|
60
|
+
const { t } = useTranslation();
|
|
61
|
+
const expiresDate = useMemo(() => {
|
|
62
|
+
if (expiresIn === 'never') return t('Never expires');
|
|
63
|
+
|
|
64
|
+
return moment(createdAt)
|
|
65
|
+
.add(expiresIn?.replace('d', '') || 0, 'days')
|
|
66
|
+
.format('YYYY-MM-DD HH:mm:ss');
|
|
67
|
+
}, [createdAt, expiresIn]);
|
|
68
|
+
|
|
69
|
+
return <Typography.Text>{expiresDate}</Typography.Text>;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const ExpiresSelect = connect(
|
|
73
|
+
InternalExpiresSelect,
|
|
74
|
+
mapProps({
|
|
75
|
+
dataSource: 'options',
|
|
76
|
+
}),
|
|
77
|
+
mapReadPretty(ReadPretty),
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
export { ExpiresSelect };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { RecursionField } from '@formily/react';
|
|
2
|
+
import { CollectionManagerProvider, SchemaComponentOptions, useCurrentRoles } from '@nocobase/client';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { apiKeysCollection } from '../../collections';
|
|
5
|
+
import { ExpiresSelect } from './ExpiresSelect';
|
|
6
|
+
import { configurationSchema } from './schema';
|
|
7
|
+
|
|
8
|
+
export const Configuration = () => {
|
|
9
|
+
const currentRoles = useCurrentRoles();
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<CollectionManagerProvider collections={[apiKeysCollection]}>
|
|
13
|
+
<SchemaComponentOptions scope={{ currentRoles }} components={{ ExpiresSelect }}>
|
|
14
|
+
<RecursionField schema={configurationSchema} />
|
|
15
|
+
</SchemaComponentOptions>
|
|
16
|
+
</CollectionManagerProvider>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { ISchema, useForm } from '@formily/react';
|
|
2
|
+
import { uid } from '@formily/shared';
|
|
3
|
+
import { useActionContext, useBlockRequestContext, useRecord } from '@nocobase/client';
|
|
4
|
+
import { Alert, Modal, Space, Typography } from 'antd';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { generateNTemplate } from '../../locale';
|
|
7
|
+
import { useTranslation } from '../locale';
|
|
8
|
+
const { useModal } = Modal;
|
|
9
|
+
|
|
10
|
+
const useCreateAction = () => {
|
|
11
|
+
const form = useForm();
|
|
12
|
+
const { setVisible } = useActionContext();
|
|
13
|
+
const { resource, service } = useBlockRequestContext();
|
|
14
|
+
const { t } = useTranslation();
|
|
15
|
+
const [modalIns, element] = useModal();
|
|
16
|
+
return {
|
|
17
|
+
async run() {
|
|
18
|
+
await form.submit();
|
|
19
|
+
const response = await resource.create({
|
|
20
|
+
values: form.values,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
modalIns.success({
|
|
24
|
+
title: t('API key created successfully'),
|
|
25
|
+
onOk: () => {
|
|
26
|
+
form.reset();
|
|
27
|
+
setVisible(false);
|
|
28
|
+
},
|
|
29
|
+
content: (
|
|
30
|
+
<Space direction="vertical">
|
|
31
|
+
<Alert
|
|
32
|
+
message={t('Make sure to copy your personal access key now as you will not be able to see this again.')}
|
|
33
|
+
type="warning"
|
|
34
|
+
></Alert>
|
|
35
|
+
<Typography.Text copyable>{response.data?.data?.token}</Typography.Text>
|
|
36
|
+
</Space>
|
|
37
|
+
),
|
|
38
|
+
});
|
|
39
|
+
service?.refresh();
|
|
40
|
+
},
|
|
41
|
+
element,
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const useDestroyAction = () => {
|
|
46
|
+
const record = useRecord();
|
|
47
|
+
const { resource, service } = useBlockRequestContext();
|
|
48
|
+
return {
|
|
49
|
+
async run() {
|
|
50
|
+
await resource.destroy({
|
|
51
|
+
filterByTk: record.id,
|
|
52
|
+
});
|
|
53
|
+
service.refresh();
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const configurationSchema: ISchema = {
|
|
59
|
+
type: 'object',
|
|
60
|
+
properties: {
|
|
61
|
+
configuration: {
|
|
62
|
+
type: 'void',
|
|
63
|
+
'x-decorator': 'TableBlockProvider',
|
|
64
|
+
'x-decorator-props': {
|
|
65
|
+
collection: 'apiKeys',
|
|
66
|
+
resource: 'apiKeys',
|
|
67
|
+
action: 'list',
|
|
68
|
+
params: {
|
|
69
|
+
pageSize: 20,
|
|
70
|
+
appends: ['role'],
|
|
71
|
+
sort: ['-createdAt'],
|
|
72
|
+
},
|
|
73
|
+
rowKey: 'name',
|
|
74
|
+
showIndex: true,
|
|
75
|
+
},
|
|
76
|
+
'x-component': 'CardItem',
|
|
77
|
+
properties: {
|
|
78
|
+
actions: {
|
|
79
|
+
type: 'void',
|
|
80
|
+
'x-component': 'ActionBar',
|
|
81
|
+
'x-component-props': {
|
|
82
|
+
style: {
|
|
83
|
+
marginBottom: 'var(--nb-spacing)',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
properties: {
|
|
87
|
+
create: {
|
|
88
|
+
type: 'void',
|
|
89
|
+
'x-action': 'create',
|
|
90
|
+
title: generateNTemplate('Add API key'),
|
|
91
|
+
'x-component': 'Action',
|
|
92
|
+
'x-component-props': {
|
|
93
|
+
openMode: 'drawer',
|
|
94
|
+
type: 'primary',
|
|
95
|
+
},
|
|
96
|
+
properties: {
|
|
97
|
+
drawer: {
|
|
98
|
+
type: 'void',
|
|
99
|
+
title: generateNTemplate('Add API key'),
|
|
100
|
+
'x-decorator': 'Form',
|
|
101
|
+
'x-component': 'Action.Modal',
|
|
102
|
+
'x-component-props': {
|
|
103
|
+
maskClosable: false,
|
|
104
|
+
style: {
|
|
105
|
+
maxWidth: '520px',
|
|
106
|
+
width: '100%',
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
properties: {
|
|
110
|
+
name: {
|
|
111
|
+
type: 'string',
|
|
112
|
+
title: generateNTemplate('Key name'),
|
|
113
|
+
required: true,
|
|
114
|
+
'x-component': 'CollectionField',
|
|
115
|
+
'x-decorator': 'FormItem',
|
|
116
|
+
},
|
|
117
|
+
role: {
|
|
118
|
+
type: 'string',
|
|
119
|
+
title: generateNTemplate('Role'),
|
|
120
|
+
required: true,
|
|
121
|
+
'x-collection-field': 'apiKeys.role',
|
|
122
|
+
'x-component': 'CollectionField',
|
|
123
|
+
'x-decorator': 'FormItem',
|
|
124
|
+
},
|
|
125
|
+
expiresIn: {
|
|
126
|
+
type: 'string',
|
|
127
|
+
title: generateNTemplate('Expiration'),
|
|
128
|
+
required: true,
|
|
129
|
+
'x-component': 'CollectionField',
|
|
130
|
+
'x-decorator': 'FormItem',
|
|
131
|
+
default: '30d',
|
|
132
|
+
},
|
|
133
|
+
footer: {
|
|
134
|
+
type: 'void',
|
|
135
|
+
'x-component': 'Action.Modal.Footer',
|
|
136
|
+
properties: {
|
|
137
|
+
cancel: {
|
|
138
|
+
title: '{{t("Cancel")}}',
|
|
139
|
+
'x-component': 'Action',
|
|
140
|
+
'x-component-props': {
|
|
141
|
+
useAction: '{{ cm.useCancelAction }}',
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
submit: {
|
|
145
|
+
title: '{{t("Submit")}}',
|
|
146
|
+
'x-component': 'Action',
|
|
147
|
+
'x-component-props': {
|
|
148
|
+
type: 'primary',
|
|
149
|
+
useAction: useCreateAction,
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
'x-align': 'right',
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
[uid()]: {
|
|
162
|
+
type: 'array',
|
|
163
|
+
'x-component': 'TableV2',
|
|
164
|
+
'x-component-props': {
|
|
165
|
+
rowKey: 'id',
|
|
166
|
+
useProps: '{{ useTableBlockProps }}',
|
|
167
|
+
},
|
|
168
|
+
properties: {
|
|
169
|
+
column1: {
|
|
170
|
+
type: 'void',
|
|
171
|
+
'x-decorator': 'TableV2.Column.Decorator',
|
|
172
|
+
'x-component': 'TableV2.Column',
|
|
173
|
+
title: generateNTemplate('Key name'),
|
|
174
|
+
properties: {
|
|
175
|
+
name: {
|
|
176
|
+
type: 'string',
|
|
177
|
+
'x-component': 'CollectionField',
|
|
178
|
+
'x-read-pretty': true,
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
column2: {
|
|
183
|
+
type: 'void',
|
|
184
|
+
'x-decorator': 'TableV2.Column.Decorator',
|
|
185
|
+
'x-component': 'TableV2.Column',
|
|
186
|
+
title: generateNTemplate('Role'),
|
|
187
|
+
properties: {
|
|
188
|
+
role: {
|
|
189
|
+
type: 'object',
|
|
190
|
+
'x-collection-field': 'apiKeys.role',
|
|
191
|
+
'x-component': 'CollectionField',
|
|
192
|
+
'x-component-props': {
|
|
193
|
+
enableLink: false,
|
|
194
|
+
},
|
|
195
|
+
'x-read-pretty': true,
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
column3: {
|
|
200
|
+
type: 'void',
|
|
201
|
+
'x-decorator': 'TableV2.Column.Decorator',
|
|
202
|
+
'x-component': 'TableV2.Column',
|
|
203
|
+
title: generateNTemplate('Expiration'),
|
|
204
|
+
properties: {
|
|
205
|
+
expiresIn: {
|
|
206
|
+
type: 'string',
|
|
207
|
+
'x-component': 'CollectionField',
|
|
208
|
+
'x-read-pretty': true,
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
column4: {
|
|
213
|
+
type: 'void',
|
|
214
|
+
'x-decorator': 'TableV2.Column.Decorator',
|
|
215
|
+
'x-component': 'TableV2.Column',
|
|
216
|
+
title: generateNTemplate('Created at'),
|
|
217
|
+
properties: {
|
|
218
|
+
createdAt: {
|
|
219
|
+
type: 'date',
|
|
220
|
+
// 'x-component': 'CollectionField',
|
|
221
|
+
'x-component': 'DatePicker',
|
|
222
|
+
'x-component-props': {
|
|
223
|
+
format: 'YYYY-MM-DD HH:mm:ss',
|
|
224
|
+
},
|
|
225
|
+
'x-read-pretty': true,
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
actionColumn: {
|
|
230
|
+
type: 'void',
|
|
231
|
+
title: '{{ t("Actions") }}',
|
|
232
|
+
'x-action-column': 'actions',
|
|
233
|
+
'x-decorator': 'TableV2.Column.ActionBar',
|
|
234
|
+
'x-component': 'TableV2.Column',
|
|
235
|
+
properties: {
|
|
236
|
+
columnActions: {
|
|
237
|
+
type: 'void',
|
|
238
|
+
'x-component': 'Space',
|
|
239
|
+
'x-component-props': {
|
|
240
|
+
split: '|',
|
|
241
|
+
},
|
|
242
|
+
properties: {
|
|
243
|
+
delete: {
|
|
244
|
+
type: 'void',
|
|
245
|
+
title: '{{ t("Delete") }}',
|
|
246
|
+
'x-component': 'Action.Link',
|
|
247
|
+
'x-component-props': {
|
|
248
|
+
confirm: {
|
|
249
|
+
title: generateNTemplate('Delete API key'),
|
|
250
|
+
content: "{{t('Are you sure you want to delete it?')}}",
|
|
251
|
+
},
|
|
252
|
+
useAction: useDestroyAction,
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
};
|