@opengis/fastify-table 1.4.70 → 1.4.72
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/index.js +2 -0
- package/package.json +1 -1
- package/server/plugins/access/funcs/getAdminAccess.js +14 -0
- package/server/plugins/access/index.mjs +6 -0
- package/server/plugins/policy/funcs/checkPolicy.js +1 -1
- package/server/routes/access/controllers/access.group.js +28 -0
- package/server/routes/access/controllers/access.group.post.js +57 -0
- package/server/routes/access/controllers/access.interface.js +37 -0
- package/server/routes/access/index.mjs +12 -0
- package/server/routes/access/schema.mjs +68 -0
- package/server/routes/table/controllers/getFormByTable.js +13 -9
- package/server/routes/util/controllers/code.generator.js +94 -0
- package/server/routes/util/index.js +2 -0
- package/utils.js +2 -0
package/index.js
CHANGED
|
@@ -33,6 +33,7 @@ import loggerRoutes from './server/routes/logger/index.js';
|
|
|
33
33
|
import propertiesRoutes from './server/routes/properties/index.js';
|
|
34
34
|
import tableRoutes from './server/routes/table/index.js';
|
|
35
35
|
import utilRoutes from './server/routes/util/index.js';
|
|
36
|
+
import accessRoutes from './server/routes/access/index.mjs';
|
|
36
37
|
|
|
37
38
|
// utils
|
|
38
39
|
import addTemplateDir from './server/plugins/table/funcs/addTemplateDir.js';
|
|
@@ -138,6 +139,7 @@ async function plugin(fastify, opt) {
|
|
|
138
139
|
propertiesRoutes(fastify, opt);
|
|
139
140
|
tableRoutes(fastify, opt);
|
|
140
141
|
utilRoutes(fastify, opt);
|
|
142
|
+
accessRoutes(fastify, opt);
|
|
141
143
|
widgetRoutes(fastify, opt);
|
|
142
144
|
|
|
143
145
|
menuRoutes(fastify, opt);
|
package/package.json
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import config from '../../../../config.js';
|
|
2
|
+
|
|
3
|
+
export default async function getAdminAccess({
|
|
4
|
+
id, user = {},
|
|
5
|
+
}) {
|
|
6
|
+
if (!id) {
|
|
7
|
+
return { message: 'not enough params: id', status: 400 };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (!config?.local && !['admin'].includes(user.user_type, user.type)) {
|
|
11
|
+
return { message: 'access restricted: admin', status: 403 };
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
@@ -19,7 +19,7 @@ export default function checkPolicy(req, reply) {
|
|
|
19
19
|
originalUrl: path, hostname, query, params, headers, method, session, routeOptions, unittest,
|
|
20
20
|
} = req;
|
|
21
21
|
|
|
22
|
-
if (config.local || unittest) { return null; }
|
|
22
|
+
if (config.local || unittest || config.env === 'test') { return null; }
|
|
23
23
|
|
|
24
24
|
const body = JSON.stringify(req?.body || {}).substring(30);
|
|
25
25
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { pgClients, getAdminAccess } from '../../../../utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function accessGroup({
|
|
4
|
+
pg = pgClients.client, params = {}, user = {}, unittest,
|
|
5
|
+
}, reply) {
|
|
6
|
+
if (!params?.id) {
|
|
7
|
+
return reply.status(400).send('not enough params: id');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// restrict access - admin only
|
|
11
|
+
const check = await getAdminAccess({
|
|
12
|
+
id: params.id, user,
|
|
13
|
+
});
|
|
14
|
+
if (check?.message && check?.status && !unittest) {
|
|
15
|
+
return reply.status(check?.status).send(check?.message);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const { rows: routes = [] } = await pg.query(`select a.route_id as path, b.actions from admin.routes a
|
|
19
|
+
left join admin.role_access b on a.route_id=b.route_id
|
|
20
|
+
where b.role_id=$1`, [params.id]);
|
|
21
|
+
|
|
22
|
+
const { rows: users = [] } = await pg.query(`select user_uid as id, user_name as name, access_granted,
|
|
23
|
+
b.cdate as user_created, b.last_activity_date as last_activity from admin.user_roles a
|
|
24
|
+
left join admin.users b on a.user_uid=b.uid
|
|
25
|
+
where a.role_id=$1`, [params.id]);
|
|
26
|
+
|
|
27
|
+
return { routes, users };
|
|
28
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { pgClients, getAdminAccess } from '../../../../utils.js';
|
|
2
|
+
import accessGroup from './access.group.js';
|
|
3
|
+
|
|
4
|
+
export default async function accessGroupPost({
|
|
5
|
+
pg = pgClients.client, params = {}, user = {}, body = {}, unittest,
|
|
6
|
+
}, reply) {
|
|
7
|
+
const { id } = params;
|
|
8
|
+
if (!user?.uid) {
|
|
9
|
+
return reply.status(401).send('unauthorized');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// restrict access - admin only
|
|
13
|
+
const check = await getAdminAccess({ id, user });
|
|
14
|
+
if (check?.message && check?.status && !unittest) {
|
|
15
|
+
return reply.status(check?.status).send(check?.message);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const { users = [], routes = [] } = body;
|
|
19
|
+
|
|
20
|
+
if (!routes?.length) {
|
|
21
|
+
// return { message: 'not enough params: users / routes', status: 400 };
|
|
22
|
+
await pg.query('delete from admin.role_access where role_id=$1', [id]);
|
|
23
|
+
|
|
24
|
+
if (!users?.length) {
|
|
25
|
+
return reply.status(200).send({ id, routes });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (routes?.length) {
|
|
30
|
+
const { routesDB = [] } = await pg.query('select array_agg(route_id) as "routesDB" from admin.routes where enabled')
|
|
31
|
+
.then((res1) => res1.rows?.[0] || {});
|
|
32
|
+
await pg.query('delete from admin.role_access where role_id=$1;', [id]);
|
|
33
|
+
|
|
34
|
+
const q = 'insert into admin.role_access(role_id,route_id,actions) values ($1,$2,$3)';
|
|
35
|
+
await Promise.all(routes.filter(el => routesDB.includes(el.path) && el.actions).map(el => pg.query(q, [id, el.path, el.actions])));
|
|
36
|
+
|
|
37
|
+
const { rows } = await pg.query(`select a.route_id as path, b.actions as actions from admin.routes a
|
|
38
|
+
left join admin.role_access b on a.route_id=b.route_id
|
|
39
|
+
where b.role_id=$1`, [id]);
|
|
40
|
+
|
|
41
|
+
if (!users?.length) {
|
|
42
|
+
return reply.status(200).send({ id, routes: rows });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const q = `delete from admin.user_roles where role_id='${id.replace(/'/g, "''")}';
|
|
47
|
+
insert into admin.user_roles(role_id,user_uid,access_granted)
|
|
48
|
+
values ${users.filter((el) => el?.id).map((el) => `('${id.replace(/'/g, "''")}','${el.id.replace(/'/g, "''")}','${user?.uid?.replace(/'/g, "''")}')`)}`;
|
|
49
|
+
|
|
50
|
+
await pg.query(q);
|
|
51
|
+
|
|
52
|
+
const res = await accessGroup({
|
|
53
|
+
pg, params, user, unittest,
|
|
54
|
+
}, reply);
|
|
55
|
+
|
|
56
|
+
return res;
|
|
57
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { pgClients, metaFormat, getAdminAccess } from '../../../../utils.js';
|
|
2
|
+
|
|
3
|
+
const q = `select a.route_id as id, coalesce(b.user_uid, d.user_uid) as user_uid, coalesce(d.actions, b.actions, array['view']) as actions, b.scope, c.role_id
|
|
4
|
+
from admin.routes a
|
|
5
|
+
left join admin.role_access b on
|
|
6
|
+
a.route_id=b.route_id
|
|
7
|
+
left join admin.roles c on
|
|
8
|
+
b.role_id=c.role_id
|
|
9
|
+
and c.enabled
|
|
10
|
+
left join admin.user_roles d on
|
|
11
|
+
c.role_id=d.role_id
|
|
12
|
+
and ( case when
|
|
13
|
+
d.expiration is not null
|
|
14
|
+
then d.expiration > CURRENT_DATE
|
|
15
|
+
else 1=1
|
|
16
|
+
end )
|
|
17
|
+
where $1 in (a.route_id, a.alias, a.table_name) and coalesce(b.user_uid, d.user_uid) is not null`;
|
|
18
|
+
|
|
19
|
+
export default async function accessInterface(req, reply) {
|
|
20
|
+
const {
|
|
21
|
+
pg = pgClients.client, params = {}, user = {}, unittest,
|
|
22
|
+
} = req;
|
|
23
|
+
|
|
24
|
+
// restrict access - admin only
|
|
25
|
+
const check = await getAdminAccess({
|
|
26
|
+
id: params.name, user,
|
|
27
|
+
});
|
|
28
|
+
if (check?.message && check?.status && !unittest) {
|
|
29
|
+
return reply.status(check?.status).send(check?.message);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const { rows = [] } = await pg.query(q, [params.name]);
|
|
33
|
+
|
|
34
|
+
const cls = { user_uid: 'core.user_uid', actions: 'core.actions', role_id: 'core.roles' };
|
|
35
|
+
await metaFormat({ rows, cls, sufix: false });
|
|
36
|
+
return { rows };
|
|
37
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import accessGroup from './controllers/access.group.js';
|
|
2
|
+
import accessGroupPost from './controllers/access.group.post.js';
|
|
3
|
+
import accessInterface from './controllers/access.interface.js';
|
|
4
|
+
|
|
5
|
+
import { accessGroupPostSchema, accessGroupSchema, accessInterfaceSchema } from './schema.mjs';
|
|
6
|
+
|
|
7
|
+
export default async function route(fastify, config) {
|
|
8
|
+
const { prefix = '/api' } = config;
|
|
9
|
+
fastify.get(`${prefix}/access-group/:id`, { schema: accessGroupSchema }, accessGroup);
|
|
10
|
+
fastify.post(`${prefix}/access-group/:id`, { schema: accessGroupPostSchema }, accessGroupPost);
|
|
11
|
+
fastify.get(`${prefix}/access-interface/:name`, { schema: accessInterfaceSchema }, accessInterface);
|
|
12
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export default null;
|
|
2
|
+
export { accessGroupSchema, accessGroupPostSchema, accessInterfaceSchema }
|
|
3
|
+
|
|
4
|
+
const accessGroupSchema = {
|
|
5
|
+
params: {
|
|
6
|
+
type: 'object',
|
|
7
|
+
properties: {
|
|
8
|
+
id: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
|
|
9
|
+
},
|
|
10
|
+
required: ['id'],
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const accessInterfaceSchema = {
|
|
15
|
+
params: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
name: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
|
|
19
|
+
},
|
|
20
|
+
required: ['name'],
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const accessGroupPostSchema = {
|
|
25
|
+
params: {
|
|
26
|
+
type: 'object',
|
|
27
|
+
properties: {
|
|
28
|
+
id: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
|
|
29
|
+
},
|
|
30
|
+
required: ['id'],
|
|
31
|
+
},
|
|
32
|
+
body: {
|
|
33
|
+
type: 'object',
|
|
34
|
+
properties: {
|
|
35
|
+
users: {
|
|
36
|
+
type: 'array',
|
|
37
|
+
items: {
|
|
38
|
+
type: 'object',
|
|
39
|
+
properties: {
|
|
40
|
+
id: {
|
|
41
|
+
type: 'string',
|
|
42
|
+
pattern: '^([\\d\\w._-]+)$',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
routes: {
|
|
48
|
+
type: 'array',
|
|
49
|
+
/*items: {
|
|
50
|
+
type: 'object',
|
|
51
|
+
properties: {
|
|
52
|
+
path: {
|
|
53
|
+
type: 'string',
|
|
54
|
+
pattern: '^([\\d\\w._-]+)$',
|
|
55
|
+
},
|
|
56
|
+
actions: {
|
|
57
|
+
type: 'array',
|
|
58
|
+
items: {
|
|
59
|
+
type: 'string',
|
|
60
|
+
enum: ['get', 'add', 'edit', 'del'],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},*/
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
config, applyHook, getTemplate, pgClients, getAccess, setToken, getSelectMeta,
|
|
2
|
+
config, applyHook, getTemplate, pgClients, getAccess, setToken, getSelectMeta, getToken,
|
|
3
3
|
} from '../../../../utils.js';
|
|
4
4
|
|
|
5
5
|
import getEditData from '../../crud/controllers/table.js';
|
|
@@ -29,13 +29,17 @@ export default async function getForm({
|
|
|
29
29
|
return reply.status(hookData?.status).send(hookData?.message);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const
|
|
32
|
+
const tokenData = await getToken({ token: params.name, uid: user?.uid, json: 1 }) || {};
|
|
33
|
+
|
|
34
|
+
const table = tokenData?.table || hookData?.table || params.name;
|
|
35
|
+
|
|
36
|
+
const { form } = await getTemplate('table', table) || {};
|
|
33
37
|
|
|
34
38
|
if (!form) {
|
|
35
39
|
return reply.status(404).send('form not found');
|
|
36
40
|
}
|
|
37
41
|
|
|
38
|
-
const { actions = [] } = await getAccess({ table
|
|
42
|
+
const { actions = [] } = await getAccess({ table, form, user }, pg) || {};
|
|
39
43
|
|
|
40
44
|
const loadTemplate = form ? await getTemplate('form', form) : null;
|
|
41
45
|
|
|
@@ -56,13 +60,13 @@ export default async function getForm({
|
|
|
56
60
|
const res = { mode: 'form', time: 0, schema };
|
|
57
61
|
|
|
58
62
|
if (user.uid) {
|
|
59
|
-
if (!actions.includes('add') && !config.local) {
|
|
63
|
+
if (!actions.includes('add') && !config.local && config.env !== 'test') {
|
|
60
64
|
return reply.status(403).send('access restricted: actions');
|
|
61
65
|
}
|
|
62
66
|
const addTokens = setToken({
|
|
63
67
|
ids: [
|
|
64
68
|
JSON.stringify({
|
|
65
|
-
table
|
|
69
|
+
table,
|
|
66
70
|
form,
|
|
67
71
|
})],
|
|
68
72
|
uid: user.uid,
|
|
@@ -71,17 +75,17 @@ export default async function getForm({
|
|
|
71
75
|
Object.assign(res, { token: addTokens[0], mode: 'add' });
|
|
72
76
|
}
|
|
73
77
|
|
|
74
|
-
if (edit && user.uid) {
|
|
75
|
-
if (!actions.includes('edit') && !config.local) {
|
|
78
|
+
if ((edit || tokenData?.id) && user.uid) {
|
|
79
|
+
if (!actions.includes('edit') && !config.local && config.env !== 'test') {
|
|
76
80
|
return reply.status(403).send('access restricted: actions');
|
|
77
81
|
}
|
|
78
82
|
const editTokens = setToken({
|
|
79
|
-
ids: [JSON.stringify({ id: edit
|
|
83
|
+
ids: [JSON.stringify({ id: edit || tokenData?.id, table, form })],
|
|
80
84
|
uid: user.uid,
|
|
81
85
|
array: 1,
|
|
82
86
|
});
|
|
83
87
|
const data = await getEditData({
|
|
84
|
-
pg, params: { table:
|
|
88
|
+
pg, params: { table, id: edit || tokenData?.id }, user,
|
|
85
89
|
}, reply, true);
|
|
86
90
|
Object.assign(res, { token: editTokens[0], data, mode: 'edit' });
|
|
87
91
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import getTemplate from '../../../plugins/table/funcs/getTemplate.js';
|
|
2
|
+
import pgClients from '../../../plugins/pg/pgClients.js';
|
|
3
|
+
import getToken from '../../../plugins/crud/funcs/getToken.js';
|
|
4
|
+
import { handlebarsSync } from '../../../../utils.js';
|
|
5
|
+
|
|
6
|
+
function dayOfTheYear(date) {
|
|
7
|
+
const start = new Date(date.getFullYear(), 0, 0);
|
|
8
|
+
const diff = (date - start) + ((start.getTimezoneOffset() - date.getTimezoneOffset()) * 60 * 1000);
|
|
9
|
+
const oneDay = 1000 * 60 * 60 * 24;
|
|
10
|
+
const day = Math.floor(diff / oneDay);
|
|
11
|
+
return day;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default async function codeGenerator({
|
|
15
|
+
pg = pgClients.client, params = {}, user = {}, query = {},
|
|
16
|
+
}, reply) {
|
|
17
|
+
const { token, column } = params;
|
|
18
|
+
const data = query.data?.split?.(';') || [];
|
|
19
|
+
|
|
20
|
+
if (!token || !column) {
|
|
21
|
+
return reply.status(400).send('not enough params: token / column');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!user?.uid) {
|
|
25
|
+
return reply.status(401).send('unauthorized');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const tokenData = await getToken({ token, uid: user?.uid, json: 1 }) || {};
|
|
29
|
+
|
|
30
|
+
if (!tokenData?.form || !tokenData?.table) {
|
|
31
|
+
return reply.status(401).send('token not allow');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const loadTemplate = await getTemplate('form', tokenData.form);
|
|
35
|
+
const schema = loadTemplate?.schema || loadTemplate;
|
|
36
|
+
|
|
37
|
+
if (!schema) {
|
|
38
|
+
return reply.status(404).send('form not found');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (!schema?.[column]?.template) {
|
|
42
|
+
return reply.status(400).send('template not specified');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const columnValue = data.find(el => el.startsWith(column))?.split('=')?.pop();
|
|
46
|
+
|
|
47
|
+
const loadTable = await getTemplate('table', tokenData.table);
|
|
48
|
+
const table = loadTable?.table || tokenData.table;
|
|
49
|
+
|
|
50
|
+
if (!pg.pk?.[table]) {
|
|
51
|
+
return reply.status(404).send('table pk not found');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const { count = 0 } = await pg.query(
|
|
55
|
+
`select count(*) from ${table} where ${columnValue ? `${column}::text = '${columnValue}'` : 'true'} limit 1`,
|
|
56
|
+
).then(el => el.rows?.[0] || {});
|
|
57
|
+
|
|
58
|
+
const { NUMY = 0 } = await pg.query(
|
|
59
|
+
`select ${column} as "NUMY" from ${table} where ${column} is not null and date_part('year', cdate) = $1 order by cdate desc limit 1`,
|
|
60
|
+
[(new Date()).getFullYear()],
|
|
61
|
+
).then(el => el.rows?.[0] || {});
|
|
62
|
+
|
|
63
|
+
const date = new Date();
|
|
64
|
+
|
|
65
|
+
const template = schema[column].template.match(/NUM[M|Y] \d/g)
|
|
66
|
+
.reduce(
|
|
67
|
+
(acc, curr) => acc.replace(
|
|
68
|
+
curr.startsWith('{{{') ? `{{{${curr}}}}` : `{{${curr}}}`,
|
|
69
|
+
handlebarsSync.compile('{{paddingNumber value padding}}')({ padding: curr.substring(4, curr.length)?.trim?.(), value: curr.startsWith('NUMY') ? NUMY : +count + 1 }),
|
|
70
|
+
),
|
|
71
|
+
schema[column].template,
|
|
72
|
+
);
|
|
73
|
+
const result = handlebarsSync.compile(template)({
|
|
74
|
+
HH: date.getHours(), // hours 24h: 14:00 = 14
|
|
75
|
+
HH12: (date.getHours() + 24) % 12 || 12, // hours 12h: 14:00 = 2
|
|
76
|
+
HH24: date.getHours(), // hours 24h: 14:00 = 14
|
|
77
|
+
MI: date.getMinutes(), // minutes
|
|
78
|
+
SS: date.getSeconds(), // seconds
|
|
79
|
+
|
|
80
|
+
YYYY: date.getFullYear(), // full year: 2025
|
|
81
|
+
YY: date.getFullYear().toString().substring(2, 4), // last 2 digits of year: 25
|
|
82
|
+
|
|
83
|
+
MONTH: date.toLocaleString('en', { month: 'long' }).toUpperCase(), // month name: MARCH
|
|
84
|
+
MON: date.toLocaleString('en', { month: 'long' }).substring(0, 3).toUpperCase(), // month name abbrev: MAR
|
|
85
|
+
MM: date.getMonth() + 1, // month number: 1 - january, 12 - december
|
|
86
|
+
|
|
87
|
+
D: date.getDay(), // day of the week: 1 - monday, 7 - sunday
|
|
88
|
+
DD: date.getDate(), // day of the month: january 4 = 4
|
|
89
|
+
DDD: dayOfTheYear(date), // day of the year: march 4 = 63
|
|
90
|
+
...data,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return reply.status(200).send(result);
|
|
94
|
+
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import nextId from './controllers/next.id.js';
|
|
2
2
|
import statusMonitor from './controllers/status.monitor.js';
|
|
3
3
|
import userTokens from './controllers/user.tokens.js';
|
|
4
|
+
import codeGenerator from './controllers/code.generator.js';
|
|
4
5
|
|
|
5
6
|
async function plugin(app, config = {}) {
|
|
6
7
|
const { prefix = '/api' } = config;
|
|
7
8
|
app.get(`${prefix}/next-id`, { config: { policy: ['public'] } }, nextId);
|
|
8
9
|
app.get(`${prefix}/status-monitor`, {}, statusMonitor);
|
|
9
10
|
app.get(`${prefix}/user-tokens/:token`, { config: { policy: ['user', 'site'] } }, userTokens);
|
|
11
|
+
app.get(`${prefix}/code-gen/:token/:column/:id?`, { config: { policy: ['user'] } }, codeGenerator);
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export default plugin;
|
package/utils.js
CHANGED
|
@@ -107,6 +107,8 @@ import getExport from './server/plugins/file/getExport.js';
|
|
|
107
107
|
import jsonToCsv from './server/routes/file/controllers/utils/jsonToCsv.js';
|
|
108
108
|
import jsonToXls from './server/routes/file/controllers/utils/jsonToXls.js';
|
|
109
109
|
|
|
110
|
+
export { default as getAdminAccess } from './server/plugins/access/funcs/getAdminAccess.js';
|
|
111
|
+
|
|
110
112
|
export default null;
|
|
111
113
|
export {
|
|
112
114
|
config,
|