@opengis/fastify-table 1.1.50 → 1.1.52
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/Changelog.md +2 -1
- package/cron/index.js +3 -1
- package/cron/schema.js +8 -0
- package/crud/funcs/getAccess.js +2 -0
- package/crud/index.js +1 -6
- package/crud/schema.js +11 -0
- package/notification/controllers/readNotifications.js +2 -5
- package/notification/controllers/testEmail.js +1 -5
- package/notification/controllers/userNotifications.js +2 -5
- package/notification/index.js +3 -8
- package/notification/schema.js +10 -0
- package/package.json +1 -1
- package/server/migrations/roles.sql +6 -0
- package/server.js +1 -1
- package/table/controllers/data.js +8 -1
- package/table/controllers/filter.js +14 -3
- package/table/controllers/search.js +1 -5
- package/table/controllers/utils/gisIRColumn.js +11 -6
- package/table/schema.js +27 -17
- package/user/controllers/user.cls.js +1 -5
- package/user/controllers/user.cls.post.js +2 -5
- package/user/controllers/user.info.js +1 -5
- package/user/index.js +7 -36
- package/user/schema.js +17 -0
- package/util/controllers/logger.file.js +5 -5
- package/util/controllers/properties.add.js +1 -5
- package/util/controllers/properties.get.js +1 -4
- package/util/controllers/utils/checkUserAccess.js +7 -4
- package/util/index.js +2 -6
- package/util/schema.js +19 -0
- package/utils.js +2 -0
- package/widget/controllers/widget.del.js +4 -7
- package/widget/controllers/widget.get.js +1 -7
- package/widget/controllers/widget.set.js +1 -6
package/Changelog.md
CHANGED
package/cron/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import cronApi from './controllers/cronApi.js';
|
|
2
2
|
import addCron from './funcs/addCron.js';
|
|
3
3
|
|
|
4
|
+
import { cronSchema } from './schema.js'
|
|
5
|
+
|
|
4
6
|
async function plugin(fastify, config = {}) {
|
|
5
7
|
const prefix = config.prefix || '/api';
|
|
6
8
|
fastify.decorate('addCron', addCron);
|
|
7
|
-
fastify.get(`${prefix}/cron/:name`, {}, cronApi);
|
|
9
|
+
fastify.get(`${prefix}/cron/:name`, { schema: cronSchema }, cronApi);
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
export default plugin;
|
package/cron/schema.js
ADDED
package/crud/funcs/getAccess.js
CHANGED
|
@@ -30,6 +30,8 @@ export default async function getAccess({ table, user = {} }) {
|
|
|
30
30
|
const body = await getTemplate('table', table) || {};
|
|
31
31
|
|
|
32
32
|
// console.log(user?.type);
|
|
33
|
+
if (body.access === 'admin' && user?.type !== 'admin') return null;
|
|
34
|
+
|
|
33
35
|
if (config.auth?.disable || user?.type === 'admin' || body?.public || body.access === 'public' || (body.access === 'user' && user.uid)) {
|
|
34
36
|
return { actions: ['get'].concat(user.uid ? body.actions || body.action_default || [] : []), query: '1=1' };
|
|
35
37
|
}
|
package/crud/index.js
CHANGED
|
@@ -9,12 +9,7 @@ import insert from './controllers/insert.js';
|
|
|
9
9
|
import deleteCrud from './controllers/deleteCrud.js';
|
|
10
10
|
import getAccessFunc from './funcs/getAccess.js';
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
params: {
|
|
14
|
-
id: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
15
|
-
table: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
|
|
16
|
-
},
|
|
17
|
-
};
|
|
12
|
+
import { tableSchema } from './schema.js';
|
|
18
13
|
|
|
19
14
|
async function plugin(fastify, config = {}) {
|
|
20
15
|
const prefix = config.prefix || '/api';
|
package/crud/schema.js
ADDED
|
@@ -7,7 +7,7 @@ export default async function readNotifications({
|
|
|
7
7
|
return { message: 'access restricted', status: 403 };
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
const { userId } = await pg.query('select uid as "userId" from admin.users where $1 in (uid,login) limit 1', [uid])
|
|
12
12
|
.then((res) => res.rows?.[0] || {});
|
|
13
13
|
|
|
@@ -23,8 +23,5 @@ export default async function readNotifications({
|
|
|
23
23
|
const { rowCount = 0 } = await pg.query(q, [userId, params?.id].filter((el) => el));
|
|
24
24
|
|
|
25
25
|
return { message: `${rowCount} unread notifications marked as read`, status: 200 };
|
|
26
|
-
|
|
27
|
-
catch (err) {
|
|
28
|
-
return { error: err.toString(), status: 500 };
|
|
29
|
-
}
|
|
26
|
+
|
|
30
27
|
}
|
|
@@ -22,7 +22,6 @@ export default async function testNotification({
|
|
|
22
22
|
return { message: 'param to is required', status: 400 };
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
try {
|
|
26
25
|
const {
|
|
27
26
|
to, template, table, id, nocache,
|
|
28
27
|
} = query;
|
|
@@ -43,8 +42,5 @@ export default async function testNotification({
|
|
|
43
42
|
return {
|
|
44
43
|
message: data || 'ok',
|
|
45
44
|
};
|
|
46
|
-
|
|
47
|
-
catch (err) {
|
|
48
|
-
return { error: err.toString(), status: 500 };
|
|
49
|
-
}
|
|
45
|
+
|
|
50
46
|
}
|
|
@@ -31,7 +31,7 @@ export default async function userNotifications({
|
|
|
31
31
|
const limit = Math.min(maxLimit, +(query.limit || 5));
|
|
32
32
|
const offset = query.page && query.page > 0 ? (query.page - 1) * limit : 0;
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
const { userId } = await pg.query('select uid as "userId" from admin.users where $1 in (uid,login) limit 1', [uid])
|
|
36
36
|
.then((res) => res.rows?.[0] || {});
|
|
37
37
|
|
|
@@ -57,8 +57,5 @@ export default async function userNotifications({
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
return { time: Date.now() - time, total: rows?.length, rows };
|
|
60
|
-
|
|
61
|
-
catch (err) {
|
|
62
|
-
return { error: err.toString(), status: 500 };
|
|
63
|
-
}
|
|
60
|
+
|
|
64
61
|
}
|
package/notification/index.js
CHANGED
|
@@ -4,17 +4,12 @@ import testEmail from './controllers/testEmail.js';
|
|
|
4
4
|
import addNotification from './funcs/addNotification.js'; // add to db
|
|
5
5
|
import notification from './funcs/sendNotification.js'; // send notification
|
|
6
6
|
|
|
7
|
+
import emailSchema from './schema.js'
|
|
8
|
+
|
|
7
9
|
async function plugin(fastify, config = {}) {
|
|
8
10
|
const prefix = config.prefix || '/api';
|
|
9
11
|
|
|
10
|
-
fastify.
|
|
11
|
-
method: 'GET',
|
|
12
|
-
url: `${prefix}/test-email`,
|
|
13
|
-
config: {
|
|
14
|
-
policy: ['user'],
|
|
15
|
-
},
|
|
16
|
-
handler: testEmail,
|
|
17
|
-
});
|
|
12
|
+
fastify.get(`${prefix}/test-email`, { config: { policy: ['user'] }, schema: emailSchema }, testEmail);
|
|
18
13
|
|
|
19
14
|
fastify.decorate('addNotification', addNotification);
|
|
20
15
|
fastify.decorate('notification', notification);
|
package/package.json
CHANGED
|
@@ -37,6 +37,8 @@ alter table admin.routes DROP constraint if exists admin_route_menu_id_fkey casc
|
|
|
37
37
|
alter table admin.routes add column if not exists route_id text NOT NULL default next_id();
|
|
38
38
|
alter table admin.routes add column if not exists alias text NOT NULL;
|
|
39
39
|
alter table admin.routes add column if not exists table_name text NOT NULL;
|
|
40
|
+
alter table admin.routes add column if not exists actions text[];
|
|
41
|
+
alter table admin.routes add column if not exists access text;
|
|
40
42
|
alter table admin.routes add column if not exists title text;
|
|
41
43
|
alter table admin.routes add column if not exists public boolean;
|
|
42
44
|
alter table admin.routes add column if not exists menu_id text;
|
|
@@ -50,6 +52,10 @@ alter table admin.routes add CONSTRAINT admin_route_id_pkey PRIMARY KEY (route_i
|
|
|
50
52
|
COMMENT ON TABLE admin.routes IS 'Список інтерфейсів';
|
|
51
53
|
COMMENT ON COLUMN admin.routes.route_id IS 'Ідентифікатор інтерфейса';
|
|
52
54
|
COMMENT ON COLUMN admin.routes.alias IS 'Назва файлу інтерфейса';
|
|
55
|
+
|
|
56
|
+
COMMENT ON COLUMN admin.routes.access IS 'Рівень доступу';
|
|
57
|
+
COMMENT ON COLUMN admin.routes.actions IS 'Дії';
|
|
58
|
+
|
|
53
59
|
COMMENT ON COLUMN admin.routes.table_name IS 'Таблиця в БД';
|
|
54
60
|
COMMENT ON COLUMN admin.routes.title IS 'Назва інтерфейсу українською';
|
|
55
61
|
COMMENT ON COLUMN admin.routes.public IS 'Ознака чи для всіх показується';
|
package/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// This file contains code that we reuse
|
|
2
2
|
// between our tests.
|
|
3
3
|
import Fastify from 'fastify';
|
|
4
|
-
import config from './
|
|
4
|
+
import config from './config.js';
|
|
5
5
|
import appService from './index.js';
|
|
6
6
|
import logger from './logger/getLogger.js';
|
|
7
7
|
import loggerTest from './logger/logger.test.api.js';
|
|
@@ -59,7 +59,14 @@ export default async function dataAPI(req) {
|
|
|
59
59
|
|
|
60
60
|
if (params.id && columnList.includes(params.id)) {
|
|
61
61
|
return gisIRColumn({
|
|
62
|
-
pg,
|
|
62
|
+
pg,
|
|
63
|
+
layer: params.table,
|
|
64
|
+
column: params.id,
|
|
65
|
+
sql: query.sql,
|
|
66
|
+
filter: query.filter,
|
|
67
|
+
state: query.state,
|
|
68
|
+
search: query.search,
|
|
69
|
+
custom: query.custom,
|
|
63
70
|
});
|
|
64
71
|
}
|
|
65
72
|
|
|
@@ -3,17 +3,28 @@ import getSelect from './utils/getSelect.js';
|
|
|
3
3
|
import getMeta from '../../pg/funcs/getMeta.js';
|
|
4
4
|
import getFilterSQL from '../funcs/getFilterSQL/index.js';
|
|
5
5
|
|
|
6
|
-
export default async function
|
|
6
|
+
export default async function filterAPI(req) {
|
|
7
7
|
const time = Date.now();
|
|
8
8
|
|
|
9
9
|
const {
|
|
10
|
-
params,
|
|
10
|
+
params, query = {},
|
|
11
11
|
} = req;
|
|
12
12
|
const loadTable = await getTemplate('table', params.table);
|
|
13
13
|
if (!loadTable) { return { status: 404, message: 'not found' }; }
|
|
14
14
|
const { columns } = await getMeta({ table: loadTable.table });
|
|
15
15
|
|
|
16
|
-
const {
|
|
16
|
+
const {
|
|
17
|
+
filter, custom, state, search,
|
|
18
|
+
} = query;
|
|
19
|
+
|
|
20
|
+
const { optimizedSQL = `select * from ${loadTable.table}` } = loadTable?.sql || filter || custom || state || search ? await getFilterSQL({
|
|
21
|
+
pg: req.pg,
|
|
22
|
+
table: params.table,
|
|
23
|
+
filter,
|
|
24
|
+
custom,
|
|
25
|
+
state,
|
|
26
|
+
search,
|
|
27
|
+
}) : {};
|
|
17
28
|
|
|
18
29
|
const filters = loadTable?.filters || loadTable?.filterList || [];
|
|
19
30
|
await Promise.all(filters.filter((el) => el.data).map(async (el) => {
|
|
@@ -59,7 +59,6 @@ export default async function search({
|
|
|
59
59
|
}) {
|
|
60
60
|
const time = Date.now();
|
|
61
61
|
|
|
62
|
-
try {
|
|
63
62
|
const tables = query.table ? [query.table] : await getTemplates('table');
|
|
64
63
|
const res = { rows: [], sql: [], total: 0 };
|
|
65
64
|
|
|
@@ -73,8 +72,5 @@ export default async function search({
|
|
|
73
72
|
return {
|
|
74
73
|
time: Date.now() - time, total: res.total, count: res.rows.length, rows: res.rows,
|
|
75
74
|
};
|
|
76
|
-
|
|
77
|
-
catch (err) {
|
|
78
|
-
return { error: err.toString(), status: 500 };
|
|
79
|
-
}
|
|
75
|
+
|
|
80
76
|
}
|
|
@@ -6,7 +6,7 @@ import getSelect from './getSelect.js';
|
|
|
6
6
|
import getFilterSQL from '../../funcs/getFilterSQL/index.js';
|
|
7
7
|
|
|
8
8
|
export default async function gisIRColumn({
|
|
9
|
-
pg = pgClients.client, layer, column, sql, query = '1=1',
|
|
9
|
+
pg = pgClients.client, layer, column, sql, query = '1=1', filter, state, search, custom,
|
|
10
10
|
}) {
|
|
11
11
|
const time = Date.now();
|
|
12
12
|
|
|
@@ -14,25 +14,30 @@ export default async function gisIRColumn({
|
|
|
14
14
|
|
|
15
15
|
const body = await getTemplate('table', layer);
|
|
16
16
|
const fData = await getFilterSQL({
|
|
17
|
-
table:
|
|
17
|
+
table: layer,
|
|
18
|
+
filter,
|
|
19
|
+
state,
|
|
20
|
+
search,
|
|
21
|
+
custom,
|
|
18
22
|
});
|
|
19
23
|
|
|
20
24
|
const { tlist } = await pg.one(`select array_agg((select nspname from pg_namespace where oid=relnamespace)||'.'||relname) tlist from pg_class
|
|
21
25
|
where relkind in ('r','v','m')`);
|
|
22
26
|
|
|
23
27
|
const tableName = body?.table || layer;
|
|
24
|
-
if (!tlist.includes(
|
|
28
|
+
if (!tlist.includes(tableName)) return { error: `table not found: ${tableName}`, status: 400 };
|
|
25
29
|
|
|
26
30
|
// eslint-disable-next-line max-len
|
|
27
|
-
const { fields } = await pg.query(`select * from (${fData?.optimizedSQL || `select * from ${
|
|
31
|
+
const { fields } = await pg.query(`select * from (${fData?.optimizedSQL || `select * from ${tableName}`})q limit 0`);
|
|
28
32
|
|
|
29
33
|
const col = fields.find((el) => el.name === column);
|
|
30
34
|
|
|
31
35
|
if (!col) return { status: 404, message: 'not found' };
|
|
32
36
|
const colField = pg.pgType[col.dataTypeID]?.includes('[]') ? `unnest(${column})` : column;
|
|
33
37
|
|
|
34
|
-
const q = `select ${colField} as id, count(*)::int from
|
|
35
|
-
|
|
38
|
+
const q = `select ${colField} as id, count(*)::int from (
|
|
39
|
+
${fData?.optimizedSQL || `select * from ${tableName} where ${body?.query || 'true'}`}
|
|
40
|
+
)t group by ${colField} order by count desc limit 15`;
|
|
36
41
|
|
|
37
42
|
if (sql) return q;
|
|
38
43
|
|
package/table/schema.js
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
const tableSchema = {
|
|
2
|
-
|
|
2
|
+
querystring: {
|
|
3
|
+
limit: { type: 'string', pattern: '^(\\d+)$' },
|
|
3
4
|
page: { type: 'string', pattern: '^(\\d+)$' },
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
// filter: { type: 'string', pattern: '^([\\w\\d_-]+)=([А-Яа-яҐґЄєІіЇї\\d\\w\\s\\/\\[\\]\\(\\)\\{\\}\\|,.!?;:—_=-@%#$&^*+=`~]+)$' },
|
|
6
|
+
// search: { type: 'string', pattern: '^([А-Яа-яҐґЄєІіЇї\\d\\w\\s\\/\\[\\]\\(\\)\\{\\}\\|,.!?;:—_=-@%#$&^*+=`~]+)$' },
|
|
7
|
+
order: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
8
|
+
desc: { type: 'string', pattern: '^(\\d+)$' },
|
|
9
|
+
// state: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
|
|
10
|
+
// custom: { type: 'string', pattern: '^([\\d\\w._-]+)$' },
|
|
11
|
+
bbox: { type: 'string', pattern: '^([\\d\\s,.-]+)$' },
|
|
12
|
+
polyline: { type: 'string', pattern: '^([\\d\\w\\|@\\/\\{\\}~_`]+)$' },
|
|
13
|
+
key: { type: 'string', pattern: '^([А-Яа-яҐґЄєІіЇї\\d\\w\\s_.-]+)$' },
|
|
14
|
+
uid: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
15
|
+
sql: { type: 'string', pattern: '^(\\d)$' },
|
|
6
16
|
},
|
|
7
17
|
params: {
|
|
8
18
|
id: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
9
|
-
table: { type: 'string', pattern: '^([\\
|
|
19
|
+
table: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
10
20
|
},
|
|
11
21
|
};
|
|
12
22
|
|
|
@@ -14,38 +24,38 @@ const searchSchema = {
|
|
|
14
24
|
querystring: {
|
|
15
25
|
page: { type: 'string', pattern: '^(\\d+)$' },
|
|
16
26
|
limit: { type: 'string', pattern: '^(\\d+)$' },
|
|
17
|
-
order: { type: 'string', pattern: '^([\\w_
|
|
18
|
-
desc: { type: 'string', pattern: '^(
|
|
19
|
-
key: { type: 'string', pattern: '^([\\w\\
|
|
20
|
-
table: { type: 'string', pattern: '^([\\
|
|
27
|
+
order: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
28
|
+
desc: { type: 'string', pattern: '^(\\d+)$' },
|
|
29
|
+
key: { type: 'string', pattern: '^([А-Яа-яҐґЄєІіЇї\\d\\w\\s_.-]+)$' },
|
|
30
|
+
table: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
21
31
|
sql: { type: 'string', pattern: '^(\\d)$' },
|
|
22
32
|
},
|
|
23
33
|
};
|
|
24
34
|
|
|
25
35
|
const suggestSchema = {
|
|
26
36
|
querystring: {
|
|
27
|
-
lang: { type: 'string', pattern: '^([\\w
|
|
28
|
-
|
|
29
|
-
sel: { type: 'string', pattern: '^([\\
|
|
30
|
-
name: { type: 'string', pattern: '^([\\
|
|
31
|
-
// key: { type: 'string', pattern: '^([\\
|
|
32
|
-
|
|
37
|
+
lang: { type: 'string', pattern: '^([\\w]+)$' },
|
|
38
|
+
parent: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
39
|
+
sel: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
40
|
+
name: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
41
|
+
// key: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
42
|
+
val: { type: 'string', pattern: '([\\d\\w]+)$' },
|
|
33
43
|
sql: { type: 'string', pattern: '^(\\d)$' },
|
|
34
44
|
},
|
|
35
45
|
params: {
|
|
36
|
-
|
|
46
|
+
// data: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
37
47
|
},
|
|
38
48
|
};
|
|
39
49
|
|
|
40
50
|
const formSchema = {
|
|
41
51
|
params: {
|
|
42
|
-
form: { type: 'string', pattern: '^([\\
|
|
52
|
+
form: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
43
53
|
},
|
|
44
54
|
};
|
|
45
55
|
|
|
46
56
|
const filterSchema = {
|
|
47
57
|
params: {
|
|
48
|
-
table: { type: 'string', pattern: '^([\\
|
|
58
|
+
table: { type: 'string', pattern: '^([\\d\\w_.-]+)$' },
|
|
49
59
|
},
|
|
50
60
|
};
|
|
51
61
|
|
|
@@ -36,7 +36,7 @@ export default async function userCls(req) {
|
|
|
36
36
|
|
|
37
37
|
if (query?.sql) return q;
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
const { rows = [] } = await pg.query(q, [uid, params.id].filter((el) => el));
|
|
41
41
|
|
|
42
42
|
rows.forEach((row) => {
|
|
@@ -68,8 +68,4 @@ export default async function userCls(req) {
|
|
|
68
68
|
}));
|
|
69
69
|
|
|
70
70
|
return { message: { rows: rows.concat(res) }, status: 200 };
|
|
71
|
-
}
|
|
72
|
-
catch (err) {
|
|
73
|
-
return { error: err.toString(), status: 200 };
|
|
74
|
-
}
|
|
75
71
|
}
|
|
@@ -22,7 +22,7 @@ export default async function userClsPost({
|
|
|
22
22
|
return { message: 'invalid params: sql (string)', status: 400 };
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
const { rowCount = 0 } = await pg.query(`with recursive rows as (
|
|
27
27
|
select user_clsid, name, code, icon, color, parent
|
|
28
28
|
from admin.user_cls a
|
|
@@ -48,8 +48,5 @@ export default async function userClsPost({
|
|
|
48
48
|
return { id, children: rows };
|
|
49
49
|
}
|
|
50
50
|
return { id, data };
|
|
51
|
-
|
|
52
|
-
catch (err) {
|
|
53
|
-
return { error: err.toString(), status: 500 };
|
|
54
|
-
}
|
|
51
|
+
|
|
55
52
|
}
|
|
@@ -10,12 +10,8 @@ export default async function userInfo({
|
|
|
10
10
|
const data = await pg.query(`select user_name, sur_name, father_name, user_rnokpp, user_type, email, login from admin.users
|
|
11
11
|
where uid=$1`, [uid]).then((res) => res.rows?.[0] || {});
|
|
12
12
|
|
|
13
|
-
try {
|
|
14
13
|
const { notifications = 0 } = await pg.query(`select count(*)::int as notifications from crm.notifications
|
|
15
14
|
where addressee_id=$1 and read is not true`, [uid]).then((res) => res.rows?.[0] || {});
|
|
16
15
|
return { uid, ...data, notifications };
|
|
17
|
-
|
|
18
|
-
catch (err) {
|
|
19
|
-
return { error: err.toString(), status: 500 };
|
|
20
|
-
}
|
|
16
|
+
|
|
21
17
|
}
|
package/user/index.js
CHANGED
|
@@ -3,44 +3,15 @@ import userClsId from './controllers/user.cls.id.js';
|
|
|
3
3
|
import userInfo from './controllers/user.info.js';
|
|
4
4
|
import userClsPost from './controllers/user.cls.post.js';
|
|
5
5
|
|
|
6
|
+
import { userClsSchema, userClsIdSchema } from './schema.js'
|
|
7
|
+
|
|
6
8
|
async function plugin(fastify, opts) {
|
|
7
9
|
const { prefix = '/api' } = opts || {};
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
},
|
|
14
|
-
schema: {},
|
|
15
|
-
handler: userCls,
|
|
16
|
-
});
|
|
17
|
-
fastify.route({
|
|
18
|
-
method: 'GET',
|
|
19
|
-
url: `${prefix}/user-cls/:id`,
|
|
20
|
-
config: {
|
|
21
|
-
policy: ['user'],
|
|
22
|
-
},
|
|
23
|
-
schema: {},
|
|
24
|
-
handler: userClsId,
|
|
25
|
-
});
|
|
26
|
-
fastify.route({
|
|
27
|
-
method: 'POST',
|
|
28
|
-
url: `${prefix}/user-cls`,
|
|
29
|
-
config: {
|
|
30
|
-
policy: ['user'],
|
|
31
|
-
},
|
|
32
|
-
schema: {},
|
|
33
|
-
handler: userClsPost,
|
|
34
|
-
});
|
|
35
|
-
fastify.route({
|
|
36
|
-
method: 'GET',
|
|
37
|
-
url: `${prefix}/user-info`,
|
|
38
|
-
config: {
|
|
39
|
-
policy: ['user'],
|
|
40
|
-
},
|
|
41
|
-
schema: {},
|
|
42
|
-
handler: userInfo,
|
|
43
|
-
});
|
|
10
|
+
|
|
11
|
+
fastify.get(`${prefix}/user-cls`, { config: { policy: ['user'] }, schema: userClsSchema }, userCls);
|
|
12
|
+
fastify.get(`${prefix}/user-cls/:id`, { config: { policy: ['user'] }, schema: userClsIdSchema }, userClsId);
|
|
13
|
+
fastify.get(`${prefix}/user-info`, { config: { policy: ['user'] } }, userInfo);
|
|
14
|
+
fastify.post(`${prefix}/user-cls/:id`, { config: { policy: ['user'] }, schema: userClsIdSchema }, userClsPost);
|
|
44
15
|
}
|
|
45
16
|
|
|
46
17
|
export default plugin;
|
package/user/schema.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const userClsSchema = {
|
|
2
|
+
params: {
|
|
3
|
+
id: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
4
|
+
},
|
|
5
|
+
quertstring: {
|
|
6
|
+
sql: { type: 'string', pattern: '^(\\d)$' },
|
|
7
|
+
},
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const userClsIdSchema = {
|
|
11
|
+
params: {
|
|
12
|
+
id: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export { userClsSchema, userClsIdSchema };
|
|
17
|
+
export default null;
|
|
@@ -14,13 +14,13 @@ import getRootDir from './utils/getRootDir.js';
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
export default async function loggerFile({
|
|
17
|
-
params = {}, user = {}, query = {}, originalUrl,
|
|
17
|
+
log, params = {}, user = {}, query = {}, originalUrl,
|
|
18
18
|
}, reply) {
|
|
19
19
|
const limit = 200000;
|
|
20
|
-
const access =
|
|
20
|
+
const access = checkUserAccess({ user });
|
|
21
|
+
// log.info('Сервер запущен по адресу?'); // test!
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
if (access?.status === 403 && !config?.local) return access;
|
|
23
|
+
if (access?.status !== 200) return access;
|
|
24
24
|
|
|
25
25
|
// absolute / relative path
|
|
26
26
|
const rootDir = getRootDir();
|
|
@@ -28,7 +28,7 @@ export default async function loggerFile({
|
|
|
28
28
|
const filepath = path.join(rootDir, params['*'] || '');
|
|
29
29
|
|
|
30
30
|
if (!existsSync(filepath)) {
|
|
31
|
-
return {
|
|
31
|
+
return { message: 'file not exists', status: 404 };
|
|
32
32
|
}
|
|
33
33
|
const stat = await lstat(filepath);
|
|
34
34
|
const isFile = stat.isFile();
|
|
@@ -34,7 +34,7 @@ export default async function addExtraProperties({
|
|
|
34
34
|
return { message: 'table not found: crm.properties', status: 400 };
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
await pg.query('delete from crm.properties where object_id=$1', [id]); // rewrite?
|
|
39
39
|
const keyTypeMatch = extraProperties.filter((key) => body[key]).reduce((acc, curr) => Object.assign(acc, checkKeyType({ body, key: curr })), {});
|
|
40
40
|
const res = await Promise.all(Object.keys(keyTypeMatch).map(async (key) => {
|
|
@@ -53,8 +53,4 @@ export default async function addExtraProperties({
|
|
|
53
53
|
return { id: rows[0]?.property_id, type: propertyType, value: body[key] };
|
|
54
54
|
}));
|
|
55
55
|
return { message: { rows: res }, status: 200 };
|
|
56
|
-
}
|
|
57
|
-
catch (err) {
|
|
58
|
-
return { error: err.toString(), status: 500 };
|
|
59
|
-
}
|
|
60
56
|
}
|
|
@@ -5,7 +5,7 @@ export default async function getExtraProperties({
|
|
|
5
5
|
if (!id) {
|
|
6
6
|
return { message: 'not enougn params', status: 400 };
|
|
7
7
|
}
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
const { rows = [] } = pg.pk?.['crm.properties']
|
|
10
10
|
? await pg.query(`select property_key, property_type, property_text, property_int,
|
|
11
11
|
property_json, property_date from crm.properties where property_key is not null and object_id=$1`, [id])
|
|
@@ -14,7 +14,4 @@ export default async function getExtraProperties({
|
|
|
14
14
|
|
|
15
15
|
const data = rows.reduce((acc, curr) => Object.assign(acc, { [curr.property_key]: curr[`property_${curr.property_type}`] }), {});
|
|
16
16
|
return { message: data, status: 200 };
|
|
17
|
-
} catch (err) {
|
|
18
|
-
return { error: err.toString(), status: 500 };
|
|
19
|
-
}
|
|
20
17
|
}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
+
import config from '../../../config.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
*
|
|
3
5
|
* @summary check user access to logger interface - per admin user type or user group
|
|
4
6
|
* @returns {Object} message, status
|
|
5
7
|
*/
|
|
6
8
|
|
|
7
|
-
export default
|
|
8
|
-
user,
|
|
9
|
+
export default function checkUserAccess({
|
|
10
|
+
user = {},
|
|
9
11
|
}) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
if (user?.uid && !config?.local) {
|
|
13
|
+
return { message: 'access restricted', status: 403 };
|
|
14
|
+
}
|
|
12
15
|
|
|
13
16
|
/* if (!['admin', 'superadmin']?.includes(user.user_type) && count === '0') {
|
|
14
17
|
return { message: 'access restricted', status: 403 };
|
package/util/index.js
CHANGED
|
@@ -4,11 +4,7 @@ import nextId from './controllers/next.id.js';
|
|
|
4
4
|
import statusMonitor from './controllers/status.monitor.js';
|
|
5
5
|
import loggerFile from './controllers/logger.file.js';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
params: {
|
|
9
|
-
id: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
10
|
-
},
|
|
11
|
-
};
|
|
7
|
+
import { propertiesSchema, loggerSchema } from './schema.js'
|
|
12
8
|
|
|
13
9
|
async function plugin(fastify, config = {}) {
|
|
14
10
|
const prefix = config.prefix || '/api';
|
|
@@ -17,7 +13,7 @@ async function plugin(fastify, config = {}) {
|
|
|
17
13
|
fastify.get(`${prefix}/status-monitor`, {}, statusMonitor);
|
|
18
14
|
fastify.get(`${prefix}/properties/:id`, { schema: propertiesSchema }, getExtraProperties);
|
|
19
15
|
fastify.post(`${prefix}/properties/:id`, { schema: propertiesSchema }, addExtraProperties);
|
|
20
|
-
fastify.get('/logger-file/*', { config: { policy: ['log'] } }, loggerFile);
|
|
16
|
+
fastify.get('/logger-file/*', { config: { policy: ['log'] }, schema: loggerSchema }, loggerFile);
|
|
21
17
|
}
|
|
22
18
|
|
|
23
19
|
export default plugin;
|
package/util/schema.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const propertiesSchema = {
|
|
2
|
+
params: {
|
|
3
|
+
id: { type: 'string', pattern: '^([\\d\\w]+)$' },
|
|
4
|
+
},
|
|
5
|
+
};
|
|
6
|
+
const loggerSchema = {
|
|
7
|
+
// params: {
|
|
8
|
+
//
|
|
9
|
+
// },
|
|
10
|
+
querystring: {
|
|
11
|
+
download: { type: 'string', pattern: '^(\\d+)$' },
|
|
12
|
+
full: { type: 'string', pattern: '^(\\d+)$' },
|
|
13
|
+
dir: { type: 'string', pattern: '^(\\d+)$' },
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
export {
|
|
17
|
+
propertiesSchema, loggerSchema
|
|
18
|
+
}
|
|
19
|
+
export default null;
|
package/utils.js
CHANGED
|
@@ -14,6 +14,7 @@ import getPGAsync from './pg/funcs/getPGAsync.js';
|
|
|
14
14
|
import initPG from './pg/funcs/init.js';
|
|
15
15
|
import pgClients from './pg/pgClients.js';
|
|
16
16
|
import getRedis from './redis/funcs/getRedis.js';
|
|
17
|
+
import redisClients from './redis/funcs/redisClients.js';
|
|
17
18
|
|
|
18
19
|
import dataInsert from './crud/funcs/dataInsert.js';
|
|
19
20
|
import dataUpdate from './crud/funcs/dataUpdate.js';
|
|
@@ -54,6 +55,7 @@ export {
|
|
|
54
55
|
addCron,
|
|
55
56
|
execMigrations,
|
|
56
57
|
getRedis,
|
|
58
|
+
redisClients,
|
|
57
59
|
logger,
|
|
58
60
|
isFileExists,
|
|
59
61
|
|
|
@@ -34,11 +34,8 @@ export default async function widgetDel({
|
|
|
34
34
|
};
|
|
35
35
|
const sql = sqls[type];
|
|
36
36
|
if (!sql) return { error: 'type not valid', status: 401 };
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
catch (err) {
|
|
42
|
-
return { message: err.toString(), status: 500 };
|
|
43
|
-
}
|
|
37
|
+
|
|
38
|
+
await pg.query(sql, [objectid, user.uid, id]);
|
|
39
|
+
return { data: { id }, user: { uid: user.uid, name: user.user_name } };
|
|
40
|
+
|
|
44
41
|
}
|
|
@@ -65,7 +65,7 @@ export default async function widgetGet({
|
|
|
65
65
|
return { error: 'param type not valid', status: 400 };
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
/* data */
|
|
70
70
|
const time = [Date.now()];
|
|
71
71
|
const { rows } = await pg.query(sql, [objectid, params.type === 'gallery' ? galleryExtList : null].filter((el) => el));
|
|
@@ -93,10 +93,4 @@ export default async function widgetGet({
|
|
|
93
93
|
data: { author: data?.author, cdate: data?.cdate, edate: data?.editor_date },
|
|
94
94
|
objectid: params.objectid,
|
|
95
95
|
};
|
|
96
|
-
}
|
|
97
|
-
catch (err) {
|
|
98
|
-
// 'history', 'file', 'checklist'
|
|
99
|
-
/* 'document', 'image' - Макс на клиенте */
|
|
100
|
-
return { message: err.toString(), status: 500 };
|
|
101
|
-
}
|
|
102
96
|
}
|
|
@@ -26,7 +26,7 @@ export default async function widgetSet(req) {
|
|
|
26
26
|
|
|
27
27
|
const table = tableList[type];
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
if (['gallery', 'file'].includes(type)) {
|
|
31
31
|
const file = await funcs.uploadMultiPart(req);
|
|
32
32
|
const extName = path.extname(file.filepath).slice(1).toLowerCase();
|
|
@@ -71,9 +71,4 @@ export default async function widgetSet(req) {
|
|
|
71
71
|
return {
|
|
72
72
|
rowCount: result.rowCount, data: 'ok', command: result.command, id: result.rows?.[0]?.[pkList[type]] || result?.[pkList[type]],
|
|
73
73
|
};
|
|
74
|
-
}
|
|
75
|
-
catch (err) {
|
|
76
|
-
log.error('widget/upload', { error: err.toString(), params });
|
|
77
|
-
return { error: err.toString(), status: 500 };
|
|
78
|
-
}
|
|
79
74
|
}
|