@opengis/fastify-table 1.1.126 → 1.1.127

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/fastify-table",
3
- "version": "1.1.126",
3
+ "version": "1.1.127",
4
4
  "type": "module",
5
5
  "description": "core-plugins",
6
6
  "keywords": ["fastify", "table", "crud", "pg", "backend" ],
@@ -124,6 +124,7 @@ ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS editor_date timestamp with
124
124
  ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS expiration date;
125
125
  ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS access_granted text;
126
126
  ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS access_granted_time timestamp without time zone;
127
+ ALTER TABLE admin.user_roles ADD COLUMN IF NOT EXISTS actions text [];
127
128
 
128
129
  ALTER TABLE admin.user_roles ADD CONSTRAINT admin_user_roles_pkey PRIMARY KEY (ugr_id);
129
130
 
@@ -135,6 +136,7 @@ COMMENT ON COLUMN admin.user_roles.uid IS 'Користувач, який ств
135
136
  COMMENT ON COLUMN admin.user_roles.expiration IS 'закінчення терміну дії доступу до групи';
136
137
  COMMENT ON COLUMN admin.user_roles.access_granted IS 'Ідентифікатор користувача який надав доступ';
137
138
  COMMENT ON COLUMN admin.user_roles.access_granted_time IS 'Час коли надали доступ';
139
+ COMMENT ON COLUMN admin.user_roles.actions IS 'Рівень доступу користувача в межах групи';
138
140
 
139
141
  CREATE INDEX IF NOT EXISTS admin_user_roles_access_user_uid_idx ON admin.user_roles USING btree (user_uid COLLATE pg_catalog."default");
140
142
  CREATE INDEX IF NOT EXISTS admin_user_roles_cdate_btree_idx ON admin.user_roles USING btree (cdate);
@@ -1,52 +1,52 @@
1
- import pgClients from '../../pg/pgClients.js';
2
- import getTemplate from '../../table/funcs/getTemplate.js';
3
- import applyHook from '../../hook/funcs/applyHook.js';
4
-
5
- const q = `select a.route_id as id, coalesce(b.actions,array['view']) as "userActions", b.scope as "userScope"
6
- from admin.routes a
7
- left join admin.role_access b on
8
- a.route_id=b.route_id
9
- left join admin.roles c on
10
- b.role_id=c.role_id
11
- and c.enabled
12
- left join admin.user_roles d on
13
- c.role_id=d.role_id
14
- and ( case when
15
- d.expiration is not null
16
- then d.expiration > CURRENT_DATE
17
- else 1=1
18
- end )
19
- where $1 in (a.route_id, a.alias, a.table_name) and $2 in (b.user_uid, d.user_uid)`;
20
-
21
- export default async function getAccess({ table, user = {} }) {
22
- if (!table) return null;
23
-
24
- const hookData = await applyHook('getAccess', { table, user });
25
- if (hookData) return hookData;
26
-
27
- const { uid, user_type: userType = 'regular' } = user;
28
-
29
- if (userType.includes('admin')) {
30
- return { actions: ['view', 'edit', 'add', 'del'], query: '1=1' };
31
- }
32
-
33
- const body = await getTemplate('table', table);
34
- const tableActions = ['view'].concat(body?.actions || body?.action_default || []);
35
-
36
- if (body?.public || body?.access === 'public') {
37
- return { actions: tableActions, query: '1=1' };
38
- }
39
-
40
- if (body?.access === 'user' && uid) {
41
- return { actions: tableActions, query: '1=1' };
42
- }
43
-
44
- const { userScope, userActions = [] } = uid
45
- ? await pgClients.client.query(q, [table, uid]).then(el => el.rows?.[0] || {})
46
- : {};
47
-
48
- const query = uid && userScope === 'my' ? `uid='${uid}'` : '1=1';
49
- const actions = userActions.filter((el => tableActions.includes(el)));
50
-
51
- return { scope: userScope, actions, query };
52
- }
1
+ import pgClients from '../../pg/pgClients.js';
2
+ import getTemplate from '../../table/funcs/getTemplate.js';
3
+ import applyHook from '../../hook/funcs/applyHook.js';
4
+
5
+ const q = `select a.route_id as id, coalesce(b.actions,array['view']) as "userActions", b.scope as "userScope"
6
+ from admin.routes a
7
+ left join admin.role_access b on
8
+ a.route_id=b.route_id
9
+ left join admin.roles c on
10
+ b.role_id=c.role_id
11
+ and c.enabled
12
+ left join admin.user_roles d on
13
+ c.role_id=d.role_id
14
+ and ( case when
15
+ d.expiration is not null
16
+ then d.expiration > CURRENT_DATE
17
+ else 1=1
18
+ end )
19
+ where $1 in (a.route_id, a.alias, a.table_name) and $2 in (b.user_uid, d.user_uid)`;
20
+
21
+ export default async function getAccess({ table, user = {} }) {
22
+ if (!table) return null;
23
+
24
+ const hookData = await applyHook('getAccess', { table, user });
25
+ if (hookData) return hookData;
26
+
27
+ const { uid, user_type: userType = 'regular' } = user;
28
+
29
+ if (userType.includes('admin')) {
30
+ return { actions: ['view', 'edit', 'add', 'del'], query: '1=1' };
31
+ }
32
+
33
+ const body = await getTemplate('table', table);
34
+ const tableActions = ['view'].concat(body?.actions || body?.action_default || []);
35
+
36
+ if (body?.public || body?.access === 'public') {
37
+ return { actions: tableActions, query: '1=1' };
38
+ }
39
+
40
+ if (body?.access === 'user' && uid) {
41
+ return { actions: tableActions, query: '1=1' };
42
+ }
43
+
44
+ const { userScope, userActions = [] } = uid
45
+ ? await pgClients.client.query(q, [table, uid]).then(el => el.rows?.[0] || {})
46
+ : {};
47
+
48
+ const query = uid && userScope === 'my' ? `uid='${uid}'` : '1=1';
49
+ const actions = userActions.filter((el => tableActions.includes(el)));
50
+
51
+ return { scope: userScope, actions, query };
52
+ }
@@ -1,8 +1,6 @@
1
1
  import config from '../../../../config.js';
2
2
  import xssInjection from '../xssInjection.js';
3
3
 
4
- // RTE - rich text editor
5
-
6
4
  function checkXSS({ body, schema = {} }) {
7
5
  const data = typeof body === 'string' ? body : JSON.stringify(body);
8
6
  const stopWords = xssInjection.filter((el) => data.toLowerCase().includes(el));
@@ -11,7 +9,7 @@ function checkXSS({ body, schema = {} }) {
11
9
  const stopSpecialSymbols = data.match(/\p{S}OR\p{S}|\p{P}OR\p{P}| OR |\+OR\+/gi);
12
10
  if (stopSpecialSymbols?.length) stopSpecialSymbols?.forEach((el) => stopWords.push(el));
13
11
 
14
- // escape arrows on non-RTE
12
+ // escape arrows on non-rich text editor inputs
15
13
  const skipScreening = config.skipScreening || ['Summernote', 'Tiny', 'Ace', 'Texteditor'];
16
14
  Object.keys(body)
17
15
  .filter((key) => ['<', '>'].find((el) => body[key]?.includes?.(el))
@@ -20,23 +18,17 @@ function checkXSS({ body, schema = {} }) {
20
18
  Object.assign(body, { [key]: body[key].replace(/</g, '&lt;').replace(/>/g, '&gt;') });
21
19
  });
22
20
 
23
- // try { } catch (err) { return { error: err.toString() }; }
24
-
25
21
  if (!stopWords.length) return { body };
26
22
 
27
23
  const disabledCheckFields = Object.keys(schema || {})?.filter((el) => schema?.[el]?.xssCheck === false); // exclude specific columns
28
24
 
29
- // check RTE
30
- /* const richTextFields = Object.keys(schema).filter((el) => skipScreening.includes(schema[el]?.type));
31
- richTextFields.filter((key) => !checkList.find((el) => body[key].includes(el)))?.forEach((key) => {
32
- disabledCheckFields.push(key);
33
- }); */
34
-
35
25
  const field = Object.keys(body)
36
26
  ?.find((key) => body[key]?.toLowerCase
37
27
  && !disabledCheckFields.includes(key)
28
+ && (skipScreening.includes(schema?.[key]?.type) ? stopWords.find(el => !['href=', 'src='].includes(el)) : true)
38
29
  && body[key].toLowerCase().includes(stopWords[0]));
39
30
  if (field) {
31
+ console.error(stopWords[0], field, body[field]);
40
32
  return { error: `rule: ${stopWords[0]} | attr: ${field} | val: ${body[field]}`, body };
41
33
  }
42
34
  return { body };
@@ -1,22 +1,22 @@
1
- import update from './controllers/update.js';
2
- import insert from './controllers/insert.js';
3
- import deleteCrud from './controllers/deleteCrud.js';
4
- import table from './controllers/table.js';
5
-
6
- const tableSchema = {
7
- params: {
8
- id: { type: 'string', pattern: '^([\\d\\w]+)$' },
9
- table: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
10
- },
11
- };
12
-
13
- async function plugin(fastify, config = {}) {
14
- const prefix = config.prefix || '/api';
15
- const policy = ['public'];
16
- fastify.put(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, update);
17
- fastify.delete(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, deleteCrud);
18
- fastify.post(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, insert);
19
- fastify.get(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, table);
20
- }
21
-
22
- export default plugin;
1
+ import update from './controllers/update.js';
2
+ import insert from './controllers/insert.js';
3
+ import deleteCrud from './controllers/deleteCrud.js';
4
+ import table from './controllers/table.js';
5
+
6
+ const tableSchema = {
7
+ params: {
8
+ id: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
9
+ table: { type: 'string', pattern: '^([\\w\\d_.]+)$' },
10
+ },
11
+ };
12
+
13
+ async function plugin(fastify, config = {}) {
14
+ const prefix = config.prefix || '/api';
15
+ const policy = ['public'];
16
+ fastify.put(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, update);
17
+ fastify.delete(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, deleteCrud);
18
+ fastify.post(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, insert);
19
+ fastify.get(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, table);
20
+ }
21
+
22
+ export default plugin;