@opengis/fastify-table 1.0.17 → 1.0.19

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.
Files changed (53) hide show
  1. package/.eslintrc.cjs +42 -42
  2. package/Changelog.md +5 -0
  3. package/README.md +26 -26
  4. package/config.js +11 -11
  5. package/crud/controllers/deleteCrud.js +14 -14
  6. package/crud/controllers/insert.js +29 -29
  7. package/crud/controllers/update.js +31 -31
  8. package/crud/controllers/utils/checkXSS.js +45 -45
  9. package/crud/controllers/utils/xssInjection.js +72 -72
  10. package/crud/funcs/dataDelete.js +15 -15
  11. package/crud/funcs/dataInsert.js +24 -24
  12. package/crud/funcs/dataUpdate.js +20 -20
  13. package/crud/funcs/getToken.js +27 -27
  14. package/crud/funcs/isFileExists.js +13 -13
  15. package/crud/funcs/setToken.js +53 -53
  16. package/crud/index.js +29 -29
  17. package/helper.js +28 -28
  18. package/index.js +4 -0
  19. package/notification/controllers/userNotifications.js +19 -0
  20. package/notification/funcs/addNotification.js +8 -0
  21. package/notification/index.js +19 -0
  22. package/package.json +1 -1
  23. package/pg/index.js +35 -35
  24. package/server/migrations/crm.sql +55 -0
  25. package/server/migrations/log.sql +40 -0
  26. package/server/migrations/notifications.sql +14 -0
  27. package/server/templates/select/test.storage.data.json +3 -0
  28. package/server/templates/select/test.storage.data.sql +1 -0
  29. package/server/templates/table/test.dataset.table.json +25 -0
  30. package/server.js +14 -14
  31. package/table/controllers/search.js +41 -0
  32. package/table/index.js +13 -0
  33. package/test/api/crud.test.js +50 -50
  34. package/test/api/crud.xss.test.js +68 -68
  35. package/test/api/notification.test.js +37 -0
  36. package/test/api/table.test.js +12 -4
  37. package/test/api/widget.test.js +39 -0
  38. package/test/config.example +18 -18
  39. package/test/funcs/crud.test.js +76 -76
  40. package/test/funcs/notification.test.js +31 -0
  41. package/test/funcs/pg.test.js +34 -34
  42. package/test/funcs/redis.test.js +19 -19
  43. package/test/templates/cls/test.json +9 -9
  44. package/test/templates/form/cp_building.form.json +32 -32
  45. package/test/templates/select/account_id.json +3 -3
  46. package/test/templates/select/storage.data.json +2 -2
  47. package/test/templates/table/gis.dataset.table.json +20 -20
  48. package/test/widget.test.js +39 -0
  49. package/widget/controllers/utils/obj2db.js +13 -0
  50. package/widget/controllers/widget.del.js +42 -0
  51. package/widget/controllers/widget.get.js +145 -0
  52. package/widget/controllers/widget.set.js +49 -0
  53. package/widget/index.js +29 -0
@@ -1,20 +1,20 @@
1
- import getPG from '../../pg/funcs/getPG.js';
2
-
3
- import getMeta from '../../pg/funcs/getMeta.js';
4
-
5
- export default async function dataUpdate({
6
- table, id, data,
7
- }) {
8
- const pg = getPG({ name: 'client' });
9
- const { columns, pk } = await getMeta(table);
10
-
11
- const names = columns?.map((el) => el.name);
12
- const filterData = Object.keys(data)
13
- .filter((el) => data[el] && names?.includes(el)).map((el) => [el, data[el]]);
14
-
15
- const updateQuery = `UPDATE ${table} SET ${filterData?.map((key, i) => `"${key[0]}"=$${i + 2}`).join(',')}
16
- WHERE ${pk} = $1 returning *`;
17
- // console.log(updateDataset);
18
- const res = await pg.query(updateQuery, [id, ...filterData.map((el) => (typeof el[1] === 'object' ? JSON.stringify(el[1]) : el[1]))]).then(el => el?.rows?.[0]) || {};
19
- return res;
20
- }
1
+ import getPG from '../../pg/funcs/getPG.js';
2
+
3
+ import getMeta from '../../pg/funcs/getMeta.js';
4
+
5
+ export default async function dataUpdate({
6
+ table, id, data,
7
+ }) {
8
+ const pg = getPG({ name: 'client' });
9
+ const { columns, pk } = await getMeta(table);
10
+
11
+ const names = columns?.map((el) => el.name);
12
+ const filterData = Object.keys(data)
13
+ .filter((el) => data[el] && names?.includes(el)).map((el) => [el, data[el]]);
14
+
15
+ const updateQuery = `UPDATE ${table} SET ${filterData?.map((key, i) => `"${key[0]}"=$${i + 2}`).join(',')}
16
+ WHERE ${pk} = $1 returning *`;
17
+ // console.log(updateDataset);
18
+ const res = await pg.query(updateQuery, [id, ...filterData.map((el) => (typeof el[1] === 'object' ? JSON.stringify(el[1]) : el[1]))]).then(el => el?.rows?.[0]) || {};
19
+ return res;
20
+ }
@@ -1,27 +1,27 @@
1
- import getRedis from '../../redis/funcs/getRedis.js';
2
- import config from '../../config.js';
3
-
4
- function sprintf(str, ...args) {
5
- return str.replace(/%s/g, () => args.shift());
6
- }
7
-
8
- const keys = {
9
- r: '%s:token:view:%s',
10
- a: '%s:token:add:%s',
11
- w: '%s:token:edit:%s',
12
- e: '%s:token:exec:%s',
13
- };
14
-
15
- async function getIdByToken({
16
- uid, token, mode = 'r', json,
17
- }) {
18
- if (mode === 'r') return token;
19
-
20
- const rclient = getRedis({ db: 0 });
21
-
22
- const key = sprintf(keys[mode], config?.pg?.database, uid?.toString());
23
- const id = await rclient.hget(key, token);
24
- return json && id[0] === '{' ? JSON.parse(id) : id;
25
- }
26
-
27
- export default getIdByToken;
1
+ import getRedis from '../../redis/funcs/getRedis.js';
2
+ import config from '../../config.js';
3
+
4
+ function sprintf(str, ...args) {
5
+ return str.replace(/%s/g, () => args.shift());
6
+ }
7
+
8
+ const keys = {
9
+ r: '%s:token:view:%s',
10
+ a: '%s:token:add:%s',
11
+ w: '%s:token:edit:%s',
12
+ e: '%s:token:exec:%s',
13
+ };
14
+
15
+ async function getIdByToken({
16
+ uid, token, mode = 'r', json,
17
+ }) {
18
+ if (mode === 'r') return token;
19
+
20
+ const rclient = getRedis({ db: 0 });
21
+
22
+ const key = sprintf(keys[mode], config?.pg?.database, uid?.toString());
23
+ const id = await rclient.hget(key, token);
24
+ return json && id[0] === '{' ? JSON.parse(id) : id;
25
+ }
26
+
27
+ export default getIdByToken;
@@ -1,13 +1,13 @@
1
- import { access } from 'fs/promises';
2
-
3
- const isFileExists = async (filepath) => {
4
- try {
5
- await access(filepath);
6
- return true;
7
- }
8
- catch (err) {
9
- return false;
10
- }
11
- };
12
-
13
- export default isFileExists;
1
+ import { access } from 'fs/promises';
2
+
3
+ const isFileExists = async (filepath) => {
4
+ try {
5
+ await access(filepath);
6
+ return true;
7
+ }
8
+ catch (err) {
9
+ return false;
10
+ }
11
+ };
12
+
13
+ export default isFileExists;
@@ -1,53 +1,53 @@
1
- import { createHash, randomUUID } from 'crypto';
2
-
3
- import config from '../../config.js';
4
- import getRedis from '../../redis/funcs/getRedis.js';
5
-
6
- const generateCodes = (ids, userToken) => {
7
- const token = userToken || randomUUID();
8
- const notNullIds = ids.filter((el) => el);
9
- const obj = {};
10
- const codes = notNullIds.reduce((acc, id) => {
11
- const newToken = createHash('sha1').update(token + id).digest('base64url').replace(/-/g, '');
12
- acc[newToken] = id; obj[id] = newToken;
13
- return acc;
14
- }, {});
15
- return { codes, obj };
16
- };
17
-
18
- function setToken({
19
- ids: idsOrigin, mode = 'r', uid, referer, array,
20
- }) {
21
- const rclient2 = getRedis({ db: 0 });
22
- // const rclient5 = getRedis({ db: 0, funcs });
23
-
24
- if (!uid) return { user: 'empty' };
25
- if (!Object.keys(idsOrigin).length) return { ids: 'empty' };
26
-
27
- const ids = idsOrigin.map((el) => (typeof el === 'object' ? JSON.stringify(el) : el));
28
- // update/delete
29
-
30
- if (mode === 'r') return null;
31
-
32
- // TODO generate salt
33
- const { codes, obj } = generateCodes(ids, uid);
34
-
35
- if (!Object.keys(codes).length) return { ids: 'empty' };
36
-
37
- rclient2.hmset(`${config.pg.database}:token:${{
38
- e: 'exec', r: 'view', w: 'edit', a: 'add',
39
- }[mode]}:${uid}`, codes);
40
-
41
- // log token for debug. add extra data - uid, mode, date
42
- /* const dt = new Date().toISOString();
43
- const codesLog = Object.keys(codes).reduce((acc, key) => {
44
- acc[key] = `{"referer": "${referer}" ,"uid":"${uid}","mode":"${mode}","date":"${dt}",${codes[key].substr(1)}`;
45
- return acc;
46
- }, {});
47
- rclient5.hmset(`${config.pg.database}:token:edit`, codesLog); // 'EX', 64800 */
48
-
49
- // TODO дополнительно писать в hset token -> uid
50
- return array ? Object.values(obj) : obj;
51
- }
52
-
53
- export default setToken;
1
+ import { createHash, randomUUID } from 'crypto';
2
+
3
+ import config from '../../config.js';
4
+ import getRedis from '../../redis/funcs/getRedis.js';
5
+
6
+ const generateCodes = (ids, userToken) => {
7
+ const token = userToken || randomUUID();
8
+ const notNullIds = ids.filter((el) => el);
9
+ const obj = {};
10
+ const codes = notNullIds.reduce((acc, id) => {
11
+ const newToken = createHash('sha1').update(token + id).digest('base64url').replace(/-/g, '');
12
+ acc[newToken] = id; obj[id] = newToken;
13
+ return acc;
14
+ }, {});
15
+ return { codes, obj };
16
+ };
17
+
18
+ function setToken({
19
+ ids: idsOrigin, mode = 'r', uid, referer, array,
20
+ }) {
21
+ const rclient2 = getRedis({ db: 0 });
22
+ // const rclient5 = getRedis({ db: 0, funcs });
23
+
24
+ if (!uid) return { user: 'empty' };
25
+ if (!Object.keys(idsOrigin).length) return { ids: 'empty' };
26
+
27
+ const ids = idsOrigin.map((el) => (typeof el === 'object' ? JSON.stringify(el) : el));
28
+ // update/delete
29
+
30
+ if (mode === 'r') return null;
31
+
32
+ // TODO generate salt
33
+ const { codes, obj } = generateCodes(ids, uid);
34
+
35
+ if (!Object.keys(codes).length) return { ids: 'empty' };
36
+
37
+ rclient2.hmset(`${config.pg.database}:token:${{
38
+ e: 'exec', r: 'view', w: 'edit', a: 'add',
39
+ }[mode]}:${uid}`, codes);
40
+
41
+ // log token for debug. add extra data - uid, mode, date
42
+ /* const dt = new Date().toISOString();
43
+ const codesLog = Object.keys(codes).reduce((acc, key) => {
44
+ acc[key] = `{"referer": "${referer}" ,"uid":"${uid}","mode":"${mode}","date":"${dt}",${codes[key].substr(1)}`;
45
+ return acc;
46
+ }, {});
47
+ rclient5.hmset(`${config.pg.database}:token:edit`, codesLog); // 'EX', 64800 */
48
+
49
+ // TODO дополнительно писать в hset token -> uid
50
+ return array ? Object.values(obj) : obj;
51
+ }
52
+
53
+ export default setToken;
package/crud/index.js CHANGED
@@ -1,29 +1,29 @@
1
- import getOPt from './funcs/getOpt.js';
2
- import setOpt from './funcs/setOpt.js';
3
- import isFileExists from './funcs/isFileExists.js';
4
- import dataUpdate from './funcs/dataUpdate.js';
5
- import dataInsert from './funcs/dataInsert.js';
6
-
7
- import update from './controllers/update.js';
8
- import insert from './controllers/insert.js';
9
- import deleteCrud from './controllers/deleteCrud.js';
10
-
11
- // import config from '../config.js';
12
-
13
- async function plugin(fastify, config = {}) {
14
- const prefix = config.prefix || '/api';
15
- // funcs
16
- fastify.decorate('setOpt', setOpt);
17
- fastify.decorate('getOpt', getOPt);
18
- fastify.decorate('dataUpdate', dataUpdate);
19
- fastify.decorate('dataInsert', dataInsert);
20
-
21
- fastify.decorate('isFileExists', isFileExists);
22
-
23
- // api
24
- fastify.put(`${prefix}/table/:table/:id`, {}, update);
25
- fastify.delete(`${prefix}/table/:table/:id`, {}, deleteCrud);
26
- fastify.post(`${prefix}/table/:table`, {}, insert);
27
- }
28
-
29
- export default plugin;
1
+ import getOPt from './funcs/getOpt.js';
2
+ import setOpt from './funcs/setOpt.js';
3
+ import isFileExists from './funcs/isFileExists.js';
4
+ import dataUpdate from './funcs/dataUpdate.js';
5
+ import dataInsert from './funcs/dataInsert.js';
6
+
7
+ import update from './controllers/update.js';
8
+ import insert from './controllers/insert.js';
9
+ import deleteCrud from './controllers/deleteCrud.js';
10
+
11
+ // import config from '../config.js';
12
+
13
+ async function plugin(fastify, config = {}) {
14
+ const prefix = config.prefix || '/api';
15
+ // funcs
16
+ fastify.decorate('setOpt', setOpt);
17
+ fastify.decorate('getOpt', getOPt);
18
+ fastify.decorate('dataUpdate', dataUpdate);
19
+ fastify.decorate('dataInsert', dataInsert);
20
+
21
+ fastify.decorate('isFileExists', isFileExists);
22
+
23
+ // api
24
+ fastify.put(`${prefix}/table/:table/:id`, {}, update);
25
+ fastify.delete(`${prefix}/table/:table/:id`, {}, deleteCrud);
26
+ fastify.post(`${prefix}/table/:table`, {}, insert);
27
+ }
28
+
29
+ export default plugin;
package/helper.js CHANGED
@@ -1,28 +1,28 @@
1
- // This file contains code that we reuse
2
- // between our tests.
3
- import Fastify from 'fastify';
4
- import config from './test/config.js';
5
- import appService from './index.js';
6
-
7
- import rclient from './redis/client.js';
8
- import pgClients from './pg/pgClients.js';
9
-
10
- // automatically build and tear down our instance
11
- async function build(t) {
12
- // you can set all the options supported by the fastify CLI command
13
- // const argv = [AppPath]
14
- process.env.NODE_ENV = 'production';
15
- const app = Fastify({ logger: false });
16
- app.register(appService, config);
17
- // close the app after we are done
18
- t.after(() => {
19
- // console.log('close app');
20
- pgClients.client.end();
21
- rclient.quit();
22
- app.close();
23
- });
24
-
25
- return app;
26
- }
27
-
28
- export default build;
1
+ // This file contains code that we reuse
2
+ // between our tests.
3
+ import Fastify from 'fastify';
4
+ import config from './test/config.js';
5
+ import appService from './index.js';
6
+
7
+ import rclient from './redis/client.js';
8
+ import pgClients from './pg/pgClients.js';
9
+
10
+ // automatically build and tear down our instance
11
+ async function build(t) {
12
+ // you can set all the options supported by the fastify CLI command
13
+ // const argv = [AppPath]
14
+ process.env.NODE_ENV = 'production';
15
+ const app = Fastify({ logger: false });
16
+ app.register(appService, config);
17
+ // close the app after we are done
18
+ t.after(() => {
19
+ // console.log('close app');
20
+ pgClients.client.end();
21
+ rclient.quit();
22
+ app.close();
23
+ });
24
+
25
+ return app;
26
+ }
27
+
28
+ export default build;
package/index.js CHANGED
@@ -6,6 +6,8 @@ import config from './config.js';
6
6
  import redisPlugin from './redis/index.js';
7
7
  import pgPlugin from './pg/index.js';
8
8
  import tablePlugin from './table/index.js';
9
+ import notificationPlugin from './notification/index.js';
10
+ import widgetPlugin from './widget/index.js';
9
11
  import crudPlugin from './crud/index.js';
10
12
  import policyPlugin from './policy/index.js';
11
13
 
@@ -27,6 +29,8 @@ async function plugin(fastify, opt) {
27
29
  await pgPlugin(fastify, opt);
28
30
  tablePlugin(fastify, opt);
29
31
  crudPlugin(fastify, opt);
32
+ notificationPlugin(fastify, opt);
33
+ widgetPlugin(fastify, opt);
30
34
  }
31
35
  export default fp(plugin);
32
36
  // export { rclient };
@@ -0,0 +1,19 @@
1
+ export default async function userNotifications({
2
+ pg, session = {}, query = {},
3
+ }) {
4
+ const time = Date.now();
5
+ try {
6
+ const { uid } = session.passport?.user || {};
7
+ if (!uid) return { error: 'access restricted', status: 403 };
8
+
9
+ const queryFunc = query.nocache ? pg.query : pg.queryCache;
10
+
11
+ // queryCache not supports $1 params
12
+ const { rows } = await queryFunc(`select notification_id as id, notification_type as type,
13
+ notification_status as status, title, body, link, uid from crm.notification where uid='${uid}'`);
14
+ return { time: Date.now() - time, total: rows?.length, rows };
15
+ }
16
+ catch (err) {
17
+ return { error: err.toString(), status: 500 };
18
+ }
19
+ }
@@ -0,0 +1,8 @@
1
+ export default async function addNotification({
2
+ pg, session = {}, title, body, link, notificationType, uid: uid1,
3
+ }) {
4
+ const uid = uid1 || session.passport?.user?.uid || {};
5
+ const { id, status } = await pg.one(`insert into crm.notification(title, body, link, notification_type, uid)
6
+ values($1,$2,$3,$4,$5) returning notification_id as id, notification_status as status`, [title, body, link, notificationType, uid]);
7
+ return { id, status };
8
+ }
@@ -0,0 +1,19 @@
1
+ // api
2
+ import userNotifications from './controllers/userNotifications.js';
3
+ // funcs
4
+ import addNotification from './funcs/addNotification.js';
5
+
6
+ async function plugin(fastify, config = {}) {
7
+ const prefix = config.prefix || '/api';
8
+ fastify.route({
9
+ method: 'GET',
10
+ url: `${prefix}/notification`,
11
+ config: {
12
+ policy: ['user'], // implement user auth check policy??
13
+ },
14
+ handler: userNotifications,
15
+ });
16
+ fastify.decorate('addNotification', addNotification);
17
+ }
18
+
19
+ export default plugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/fastify-table",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "type": "module",
5
5
  "description": "core-plugins",
6
6
  "main": "index.js",
package/pg/index.js CHANGED
@@ -1,35 +1,35 @@
1
- // import fp from 'fastify-plugin';
2
- //import pg from 'pg';
3
- import pgClients from './funcs/pgClients.js';
4
- import init from './funcs/init.js';
5
- import autoIndex from './funcs/autoIndex.js';
6
- import getMeta from './funcs/getMeta.js';
7
- import getPG from './funcs/getPG.js';
8
-
9
- function close() {
10
- // console.log('pg close');
11
- Object.keys(pgClients).forEach((el) => {
12
- // console.log(el);
13
- pgClients[el].end();
14
- });
15
-
16
- // return pgClients.client.end();
17
- }
18
-
19
- async function plugin(fastify, config) {
20
- const client = getPG({ ...config.pg || {}, name: 'client' })
21
- await init(client);
22
- fastify.addHook('onRequest', async (req) => {
23
- // req.funcs = fastify;
24
- req.pg = client;
25
- });
26
- //pgClients.client = client;
27
-
28
- // fastify.decorate('pg', client);
29
- fastify.decorate('autoIndex', autoIndex);
30
- fastify.decorate('getMeta', getMeta);
31
- fastify.decorate('getPG', getPG);
32
- fastify.addHook('onClose', close);
33
- }
34
-
35
- export default plugin;
1
+ // import fp from 'fastify-plugin';
2
+ //import pg from 'pg';
3
+ import pgClients from './funcs/pgClients.js';
4
+ import init from './funcs/init.js';
5
+ import autoIndex from './funcs/autoIndex.js';
6
+ import getMeta from './funcs/getMeta.js';
7
+ import getPG from './funcs/getPG.js';
8
+
9
+ function close() {
10
+ // console.log('pg close');
11
+ Object.keys(pgClients).forEach((el) => {
12
+ // console.log(el);
13
+ pgClients[el].end();
14
+ });
15
+
16
+ // return pgClients.client.end();
17
+ }
18
+
19
+ async function plugin(fastify, config) {
20
+ const client = getPG({ ...config.pg || {}, name: 'client' })
21
+ await init(client);
22
+ fastify.addHook('onRequest', async (req) => {
23
+ // req.funcs = fastify;
24
+ req.pg = client;
25
+ });
26
+ //pgClients.client = client;
27
+
28
+ // fastify.decorate('pg', client);
29
+ fastify.decorate('autoIndex', autoIndex);
30
+ fastify.decorate('getMeta', getMeta);
31
+ fastify.decorate('getPG', getPG);
32
+ fastify.addHook('onClose', close);
33
+ }
34
+
35
+ export default plugin;
@@ -0,0 +1,55 @@
1
+ -- crm.notification
2
+ CREATE TABLE IF NOT EXISTS crm.notification();
3
+ ALTER TABLE crm.notification DROP CONSTRAINT IF EXISTS notification_key;
4
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS notification_id text NOT NULL DEFAULT admin.next_id();
5
+
6
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS notification_user_id text;
7
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS notification_type text DEFAULT 'notify'::text;
8
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS notification_status text DEFAULT 'not sent'::text;
9
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS title text;
10
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS body text;
11
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS link text;
12
+
13
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS uid text;
14
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
15
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS editor_id text;
16
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
17
+ ALTER TABLE crm.notification ADD CONSTRAINT notification_key PRIMARY KEY (notification_id);
18
+
19
+ -- crm.file
20
+ CREATE TABLE IF NOT EXISTS crm.file();
21
+ ALTER TABLE crm.file DROP CONSTRAINT IF EXISTS crm_file_pkey;
22
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS file_id text NOT NULL DEFAULT admin.next_id();
23
+
24
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS upload_name text;
25
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS object_id text;
26
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS file_type text;
27
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS doc_type text;
28
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS title text;
29
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS size numeric;
30
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS ext text;
31
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS file_path text;
32
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS ismain boolean default false;
33
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS isverified boolean default false;
34
+
35
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS uid text;
36
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
37
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS editor_id text;
38
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
39
+ ALTER TABLE crm.file ADD CONSTRAINT crm_file_pkey PRIMARY KEY (file_id);
40
+
41
+ -- crm.comment
42
+ CREATE TABLE IF NOT EXISTS crm.comment();
43
+ ALTER TABLE crm.comment DROP CONSTRAINT IF EXISTS comment_key;
44
+ ALTER TABLE crm.comment ADD COLUMN IF NOT EXISTS comment_id text NOT NULL DEFAULT admin.next_id();
45
+
46
+ ALTER TABLE crm.comment ADD COLUMN IF NOT EXISTS object_id text;
47
+ ALTER TABLE crm.comment ADD COLUMN IF NOT EXISTS title text;
48
+ ALTER TABLE crm.comment ADD COLUMN IF NOT EXISTS body text;
49
+ ALTER TABLE crm.comment ADD COLUMN IF NOT EXISTS mark numeric;
50
+
51
+ ALTER TABLE crm.comment ADD COLUMN IF NOT EXISTS uid text;
52
+ ALTER TABLE crm.comment ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
53
+ ALTER TABLE crm.comment ADD COLUMN IF NOT EXISTS editor_id text;
54
+ ALTER TABLE crm.comment ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
55
+ ALTER TABLE crm.comment ADD CONSTRAINT comment_key PRIMARY KEY (comment_id);
@@ -0,0 +1,40 @@
1
+ CREATE TABLE IF NOT EXISTS log.table_change();
2
+ ALTER TABLE log.table_change DROP CONSTRAINT IF EXISTS log_table_change_pkey;
3
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS table_change_id text NOT NULL DEFAULT admin.next_id();
4
+
5
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS table_name text;
6
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS change_key text;
7
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS change_date date;
8
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS json_old json;
9
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS json_new json;
10
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS date_old timestamp without time zone;
11
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS date_new timestamp without time zone;
12
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS number_old numeric;
13
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS number_new numeric;
14
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS bool_old boolean;
15
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS bool_new boolean;
16
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS text_old text;
17
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS text_new text;
18
+
19
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS uid text;
20
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
21
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS editor_id text;
22
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
23
+ ALTER TABLE log.table_change ADD CONSTRAINT log_table_change_pkey PRIMARY KEY (table_change_id);
24
+
25
+ CREATE TABLE IF NOT EXISTS log.user_auth();
26
+ ALTER TABLE log.user_auth DROP CONSTRAINT IF EXISTS log_user_auth_pkey;
27
+ ALTER TABLE log.user_auth DROP CONSTRAINT IF EXISTS log_user_auth_user_id_fkey;
28
+
29
+ ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS user_auth_id text NOT NULL DEFAULT admin.next_id();
30
+
31
+ ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS user_id text;
32
+ ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS user_auth_date timestamp without time zone;
33
+ ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS user_auth_type text;
34
+
35
+ ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS uid text;
36
+ ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
37
+ ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS editor_id text;
38
+ ALTER TABLE log.user_auth ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
39
+ ALTER TABLE log.user_auth ADD CONSTRAINT log_user_auth_pkey PRIMARY KEY (user_auth_id);
40
+ ALTER TABLE log.user_auth ADD CONSTRAINT log_user_auth_user_id_fkey FOREIGN KEY (user_id) REFERENCES admin.users (uid) MATCH SIMPLE;
@@ -0,0 +1,14 @@
1
+ CREATE TABLE IF NOT EXISTS crm.notification();
2
+ ALTER TABLE crm.notification DROP CONSTRAINT IF EXISTS notification_key;
3
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS notification_id text NOT NULL DEFAULT admin.next_id();
4
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS notification_user_id text;
5
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS notification_type text DEFAULT 'notify'::text;
6
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS notification_status text DEFAULT 'not sent'::text;
7
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS title text;
8
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS body text;
9
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS link text;
10
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS uid text;
11
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS cdate timestamp without time zone DEFAULT (now())::timestamp without time zone;
12
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS editor_id text;
13
+ ALTER TABLE crm.notification ADD COLUMN IF NOT EXISTS editor_date timestamp without time zone;
14
+ ALTER TABLE crm.notification ADD CONSTRAINT notification_key PRIMARY KEY (notification_id);
@@ -0,0 +1,3 @@
1
+ {
2
+ "key": "dataset_id"
3
+ }
@@ -0,0 +1 @@
1
+ select dataset_id,dataset_name from gis.dataset
@@ -0,0 +1,25 @@
1
+ {
2
+ "columns": [
3
+ {
4
+ "name": "dataset_id",
5
+ "title": "22"
6
+ },
7
+ {
8
+ "name": "dataset_name",
9
+ "title": "dataset_name"
10
+ }
11
+ ],
12
+ "table": "gis.dataset",
13
+ "order": "dataset_name",
14
+ "meta": {
15
+ "title": "dataset_name",
16
+ "search": "dataset_name,dataset_id"
17
+ },
18
+ "filters": [
19
+ {
20
+ "ua": "Назва набору",
21
+ "name": "dataset_name",
22
+ "type": "text"
23
+ }
24
+ ]
25
+ }