From f6e1938ff9f56cfd653a75434d1c401a105885da Mon Sep 17 00:00:00 2001 From: Tomas Bures Date: Sat, 29 Jul 2017 22:42:07 +0300 Subject: [PATCH] Lists list and CUD Custom forms list Updated DB schema (not yet implemented in the server, which means that most of the server is not broken). - custom forms are independent of a list - order and visibility of fields is now in custom_fields - first_name and last_name has been turned to a regular custom field --- access-control.md | 47 +++- app.js | 9 +- client/src/account/Login.js | 2 +- client/src/lib/form.js | 44 ++- client/src/lib/table.js | 2 + client/src/lib/tree.js | 2 + client/src/lists/CUD.js | 228 +++++++++++++++ client/src/lists/List.js | 89 ++++++ client/src/lists/forms/List.js | 85 ++++++ client/src/lists/root.js | 61 ++++ client/src/reports/CUD.js | 4 +- client/src/reports/Output.js | 5 +- client/src/reports/View.js | 5 +- client/src/reports/templates/CUD.js | 2 - client/src/shares/Share.js | 17 +- client/src/shares/UserShares.js | 9 +- client/webpack.config.js | 3 +- config/default.toml | 36 ++- lib/context-helpers.js | 11 +- lib/db.js | 2 +- lib/dbcheck.js | 2 +- lib/models/lists.js | 10 +- lib/namespace-helpers.js | 10 +- lib/passport.js | 3 +- lib/permissions.js | 10 + models/forms.js | 261 ++++++++++++++++++ models/lists.js | 92 +++++- models/namespaces.js | 3 + models/report-templates.js | 6 +- models/reports.js | 10 +- models/shares.js | 18 +- models/users.js | 14 +- routes/{forms.js => forms-legacy.js} | 0 routes/lists-legacy-integration.js | 10 + routes/{lists.js => lists-legacy.js} | 12 + routes/reports.js | 3 +- routes/rest/account.js | 3 +- routes/rest/forms.js | 42 +++ routes/rest/lists.js | 26 +- routes/rest/reports.js | 9 +- .../20170507083345_create_namespaces.js | 14 +- .../20170507084114_create_permissions.js | 3 +- ...0728220422_drop_id_in_custom_forms_data.js | 10 + ...5_make_custom_forms_independent_of_list.js | 9 + ...fields_and_make_all_fields_configurable.js | 97 +++++++ shared/lists.js | 14 + workers/reports/report-processor.js | 13 +- 47 files changed, 1245 insertions(+), 122 deletions(-) create mode 100644 client/src/lists/CUD.js create mode 100644 client/src/lists/List.js create mode 100644 client/src/lists/forms/List.js create mode 100644 client/src/lists/root.js create mode 100644 models/forms.js rename routes/{forms.js => forms-legacy.js} (100%) create mode 100644 routes/lists-legacy-integration.js rename routes/{lists.js => lists-legacy.js} (99%) create mode 100644 routes/rest/forms.js create mode 100644 setup/knex/migrations/20170728220422_drop_id_in_custom_forms_data.js create mode 100644 setup/knex/migrations/20170729160135_make_custom_forms_independent_of_list.js create mode 100644 setup/knex/migrations/20170729160422_move_form_field_order_to_custom_fields_and_make_all_fields_configurable.js create mode 100644 shared/lists.js diff --git a/access-control.md b/access-control.md index 8e99b6a1..aad39e45 100644 --- a/access-control.md +++ b/access-control.md @@ -60,9 +60,18 @@ A namespace role further defines allowed operations for entity types within and The following defines the role master for scope "global". This effectively means that in "Create/Edit User" form, the user can be given role "Master". -The role gives the permission to rebuild the permission cache. Further, it specifies that the +The role gives the permission to rebuild the permission cache. + +Further, it specifies that the holder of the role will automatically be given access (share) to the root namespace in the -namespace role "master". This role is also an admin role, which means that user id 1 will always be reset to this role. +namespace role "master" (specified by ```rootNamespaceRole="master"```). This access to the root namespace is given irrespective of the namespace +in which the user is created. This highlight the dual purpose of namespaces: a) they group +entities w.r.t. access management, b) they allow categorizing entities and users in a hierarchy +to potentially reflect the organisational or process hierarchy. The latter is especially useful for +more enterprise applications where a single installation of Mailtrain serves a number of rather +independent groups. + +The global role defined below is also an admin role (denoted by the ```admin=true```), which means that user id 1 will always be reset to this role. This serves as a kind of bootstrap that makes sure that there is always a user that can be used to give access to other users. ``` @@ -74,11 +83,23 @@ permissions=["rebuildPermissions"] rootNamespaceRole="master" ``` -This defines the role "master" for "report" entities. It lists the operations that a user +Another example for a global role is the following. This one is intended for regular users. +As such, it does not automatically give access to everything. Rather, it gives limited access +to entities under the namespace in which the user has been created. This is specified by the +```ownNamespaceRole="editor"``` +``` +[roles.global.editor] +name="Editor" +description="Anything under own namespace except operations related to sending and doing reports" +permissions=[] +ownNamespaceRole="editor" +``` + +The roles for entities are defined in a similar fashion. The example below shows the definition +of the role "master" for "report" entities. It lists the operations that a user that has "master" access to a particular report can do with the report. Note that to get the "master" access to a particular report through this role, the report would either have to be shared with the user -with role "master". - +with role "master". ``` [roles.report.master] name="Master" @@ -86,6 +107,14 @@ description="All permissions" permissions=["view", "edit", "delete", "share", "execute", "viewContent", "viewOutput"] ``` +The same for the restricted role "editor" can look as follows. +``` +[roles.report.editor] +name="Editor" +description="Anything under own namespace except operations related to sending and doing reports" +permissions=["view", "viewContent", "viewOutput"] +``` + The following defines the role "master" for "namespace" entities. Similarly to the example above, it lists operations that relate to a namespace. In particular all "create" operations pertain to a namespace rathen than to an entity, which at the time of creation does not exist yet. @@ -101,4 +130,12 @@ permissions=["view", "edit", "delete", "share", "createNamespace", "createReport reportTemplate=["view", "edit", "delete", "share", "execute"] report=["view", "edit", "delete", "share", "execute", "viewContent", "viewOutput"] namespace=["view", "edit", "delete", "share", "createNamespace", "createReportTemplate", "createReport", "manageUsers"] +``` + +And the same for the more restricted role "editor". +``` +[roles.namespace.editor.children] +reportTemplate=[] +report=["view", "viewContent", "viewOutput"] +namespace=["view", "edit", "delete"] ``` \ No newline at end of file diff --git a/app.js b/app.js index 64039a41..dc876977 100644 --- a/app.js +++ b/app.js @@ -22,14 +22,14 @@ const tools = require('./lib/tools'); const contextHelpers = require('./lib/context-helpers'); const routes = require('./routes/index'); -const lists = require('./routes/lists'); +const lists = require('./routes/lists-legacy'); const settings = require('./routes/settings'); const settingsModel = require('./lib/models/settings'); const templates = require('./routes/templates'); const campaigns = require('./routes/campaigns'); const links = require('./routes/links'); const fields = require('./routes/fields'); -const forms = require('./routes/forms'); +const forms = require('./routes/forms-legacy'); const segments = require('./routes/segments'); const triggers = require('./routes/triggers'); const webhooks = require('./routes/webhooks'); @@ -51,12 +51,14 @@ const reportTemplatesRest = require('./routes/rest/report-templates'); const reportsRest = require('./routes/rest/reports'); const campaignsRest = require('./routes/rest/campaigns'); const listsRest = require('./routes/rest/lists'); +const formsRest = require('./routes/rest/forms'); const sharesRest = require('./routes/rest/shares'); const namespacesLegacyIntegration = require('./routes/namespaces-legacy-integration'); const usersLegacyIntegration = require('./routes/users-legacy-integration'); const accountLegacyIntegration = require('./routes/account-legacy-integration'); const reportsLegacyIntegration = require('./routes/reports-legacy-integration'); +const listsLegacyIntegration = require('./routes/lists-legacy-integration'); const interoperableErrors = require('./shared/interoperable-errors'); @@ -253,6 +255,7 @@ if (config.reports && config.reports.enabled === true) { app.use('/users', usersLegacyIntegration); app.use('/namespaces', namespacesLegacyIntegration); app.use('/account', accountLegacyIntegration); +app.use('/lists', listsLegacyIntegration); if (config.reports && config.reports.enabled === true) { app.use('/reports', reports); @@ -270,6 +273,7 @@ app.use('/rest', usersRest); app.use('/rest', accountRest); app.use('/rest', campaignsRest); app.use('/rest', listsRest); +app.use('/rest', formsRest); app.use('/rest', sharesRest); if (config.reports && config.reports.enabled === true) { @@ -329,6 +333,7 @@ if (app.get('env') === 'development') { return next(); } + console.log(err); if (req.needsJSONResponse) { const resp = { message: err.message, diff --git a/client/src/account/Login.js b/client/src/account/Login.js index b3b8c103..6d2c9770 100644 --- a/client/src/account/Login.js +++ b/client/src/account/Login.js @@ -105,7 +105,7 @@ export default class Login extends Component {
- +