From d3b50c077b903983fc2701e88c3575da14bfa63f Mon Sep 17 00:00:00 2001 From: yuri Date: Thu, 3 Dec 2015 12:42:25 +0200 Subject: [PATCH] ability to disable scope --- .../Espo/Controllers/EntityManager.php | 3 ++ application/Espo/Core/Acl/Table.php | 30 ++++++++++++---- application/Espo/Core/Utils/EntityManager.php | 17 ++++++--- .../Modules/Crm/Controllers/Activities.php | 4 +++ .../Crm/Resources/i18n/en_US/Global.json | 6 ++-- .../metadata/clientDefs/Account.json | 23 ++++++------ .../Resources/metadata/clientDefs/Case.json | 9 +++-- .../metadata/clientDefs/Contact.json | 9 +++-- .../Resources/metadata/clientDefs/Lead.json | 9 +++-- .../metadata/clientDefs/Opportunity.json | 9 +++-- .../Resources/metadata/scopes/Activities.json | 2 +- .../Resources/i18n/en_US/EntityManager.json | 3 +- .../views/lead/record/panels/converted-to.js | 6 ++-- .../views/meeting/record/panels/attendees.js | 4 +-- .../entity-manager/modals/edit-entity.tpl | 12 +++++-- frontend/client/src/acl.js | 20 ++++++----- frontend/client/src/metadata.js | 35 +++++++++++++++++++ .../src/views/admin/entity-manager/index.js | 16 ++++++--- .../entity-manager/modals/edit-entity.js | 28 ++++++++++----- .../client/src/views/admin/layouts/index.js | 10 +++--- .../client/src/views/record/detail-bottom.js | 23 ++++++++++-- .../client/src/views/record/detail-side.js | 18 ++++++++-- .../client/src/views/role/record/table.js | 5 +-- .../settings/fields/quick-create-list.js | 4 +-- .../src/views/settings/fields/tab-list.js | 12 +++---- frontend/client/src/views/site/navbar.js | 10 ++++-- .../src/views/user/record/detail-side.js | 8 +++-- 27 files changed, 245 insertions(+), 90 deletions(-) diff --git a/application/Espo/Controllers/EntityManager.php b/application/Espo/Controllers/EntityManager.php index 1a2f7fac38..aac5791a86 100644 --- a/application/Espo/Controllers/EntityManager.php +++ b/application/Espo/Controllers/EntityManager.php @@ -69,6 +69,9 @@ class EntityManager extends \Espo\Core\Controllers\Base if (!empty($data['stream'])) { $params['stream'] = $data['stream']; } + if (!empty($data['disabled'])) { + $params['disabled'] = $data['disabled']; + } if (!empty($data['sortBy'])) { $params['sortBy'] = $data['sortBy']; } diff --git a/application/Espo/Core/Acl/Table.php b/application/Espo/Core/Acl/Table.php index e69191e2b9..2cbbc1df68 100644 --- a/application/Espo/Core/Acl/Table.php +++ b/application/Espo/Core/Acl/Table.php @@ -122,14 +122,14 @@ class Table private function load() { - $aclTables = []; + $aclTableList = []; $assignmentPermissionList = []; $userPermissionList = []; $userRoles = $this->user->get('roles'); foreach ($userRoles as $role) { - $aclTables[] = $role->get('data'); + $aclTableList[] = $role->get('data'); $assignmentPermissionList[] = $role->get('assignmentPermission'); $userPermissionList[] = $role->get('userPermission'); } @@ -138,13 +138,21 @@ class Table foreach ($teams as $team) { $teamRoles = $team->get('roles'); foreach ($teamRoles as $role) { - $aclTables[] = $role->get('data'); + $aclTableList[] = $role->get('data'); $assignmentPermissionList[] = $role->get('assignmentPermission'); $userPermissionList[] = $role->get('userPermission'); } } - $this->data['table'] = $this->merge($aclTables); + $aclTable = $this->merge($aclTableList); + + foreach ($this->getScopeList() as $scope) { + if ($this->metadata->get('scopes.' . $scope . '.disabled')) { + $aclTable[$scope] = false; + } + } + + $this->data['table'] = $aclTable; $this->data['assignmentPermission'] = $this->mergeValues($assignmentPermissionList, $this->metadata->get('app.acl.valueDefaults.assignmentPermission', 'all')); $this->data['userPermission'] = $this->mergeValues($userPermissionList, $this->metadata->get('app.acl.valueDefaults.userPermission', 'no')); @@ -183,7 +191,7 @@ class Table return $result; } - private function getScopeList() + private function getScopeWithAclList() { $scopeList = []; $scopes = $this->metadata->get('scopes'); @@ -195,10 +203,20 @@ class Table return $scopeList; } + private function getScopeList() + { + $scopeList = []; + $scopes = $this->metadata->get('scopes'); + foreach ($scopes as $scope => $d) { + $scopeList[] = $scope; + } + return $scopeList; + } + private function merge($tables) { $data = array(); - $scopeList = $this->getScopeList(); + $scopeList = $this->getScopeWithAclList(); foreach ($tables as $table) { foreach ($scopeList as $scope) { diff --git a/application/Espo/Core/Utils/EntityManager.php b/application/Espo/Core/Utils/EntityManager.php index 34c16b19fb..e58deb955c 100644 --- a/application/Espo/Core/Utils/EntityManager.php +++ b/application/Espo/Core/Utils/EntityManager.php @@ -123,6 +123,10 @@ class EntityManager if (!empty($params['stream'])) { $stream = $params['stream']; } + $disabled = false; + if (!empty($params['disabled'])) { + $disabled = $params['disabled']; + } $labelSingular = $name; if (!empty($params['labelSingular'])) { $labelSingular = $params['labelSingular']; @@ -139,6 +143,7 @@ class EntityManager $scopesData = Json::decode($scopesDataContents, true); $scopesData['stream'] = $stream; + $scopesData['disabled'] = $disabled; $scopesData['type'] = $type; $scopesData['module'] = 'Custom'; $scopesData['object'] = true; @@ -179,10 +184,14 @@ class EntityManager throw new Error('Entity ['.$name.'] does not exist.'); } - if (isset($data['stream'])) { - $scopeData = array( - 'stream' => (true == $data['stream']) - ); + if (isset($data['stream']) || isset($data['disabled'])) { + $scopeData = array(); + if (isset($data['stream'])) { + $scopeData['stream'] = true == $data['stream']; + } + if (isset($data['disabled'])) { + $scopeData['disabled'] = true == $data['disabled']; + } $this->getMetadata()->set('scopes', $name, $scopeData); } diff --git a/application/Espo/Modules/Crm/Controllers/Activities.php b/application/Espo/Modules/Crm/Controllers/Activities.php index e21813cca6..75c72dcc8d 100644 --- a/application/Espo/Modules/Crm/Controllers/Activities.php +++ b/application/Espo/Modules/Crm/Controllers/Activities.php @@ -105,6 +105,10 @@ class Activities extends \Espo\Core\Controllers\Base public function actionList($params, $data, $request) { + if (!$this->getAcl()->check('Activities')) { + throw new Forbidden(); + } + $name = $params['name']; if (!in_array($name, ['activities', 'history'])) { diff --git a/application/Espo/Modules/Crm/Resources/i18n/en_US/Global.json b/application/Espo/Modules/Crm/Resources/i18n/en_US/Global.json index 03d1d55987..d96cac93eb 100644 --- a/application/Espo/Modules/Crm/Resources/i18n/en_US/Global.json +++ b/application/Espo/Modules/Crm/Resources/i18n/en_US/Global.json @@ -16,7 +16,8 @@ "TargetList": "Target List", "MassEmail": "Mass Email", "EmailQueueItem": "Email Queue Item", - "CampaignTrackingUrl": "Tracking URL" + "CampaignTrackingUrl": "Tracking URL", + "Activities": "Activities" }, "scopeNamesPlural": { "Account": "Accounts", @@ -35,7 +36,8 @@ "TargetList": "Target Lists", "MassEmail": "Mass Emails", "EmailQueueItem": "Email Queue Items", - "CampaignTrackingUrl": "Tracking URLs" + "CampaignTrackingUrl": "Tracking URLs", + "Activities": "Activities" }, "dashlets": { "Leads": "My Leads", diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Account.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Account.json index 78df90e870..321d4e6621 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Account.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Account.json @@ -1,36 +1,39 @@ { "controller": "controllers/record", - "views":{ - "detail":"Crm:Account.Detail" + "views": { + "detail":"crm:views/account/detail" }, - "sidePanels":{ - "detail":[ + "sidePanels": { + "detail": [ { "name":"activities", "label":"Activities", - "view":"Crm:Record.Panels.Activities" + "view":"crm:views/record/panels/activities", + "aclScope": "Activities" }, { "name":"history", "label":"History", - "view":"Crm:Record.Panels.History" + "view":"crm:views/record/panels/history", + "aclScope": "Activities" }, { "name":"tasks", "label":"Tasks", - "view":"Crm:Record.Panels.Tasks" + "view":"crm:views/record/panels/tasks", + "aclScope": "Task" } ] }, - "relationshipPanels":{ - "contacts":{ + "relationshipPanels": { + "contacts": { "layout":"listForAccount" }, "opportunities":{ "layout":"listForAccount" }, "campaignLogRecords": { - "rowActionsView": "Record.RowActions.Empty", + "rowActionsView": "views/record/row-actions/empty", "select": false, "create": false } diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Case.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Case.json index 34f6a665c1..7c977c84d2 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Case.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Case.json @@ -12,17 +12,20 @@ { "name":"activities", "label":"Activities", - "view":"Crm:Case.Record.Panels.Activities" + "view":"crm:views/record/panels/activities", + "aclScope": "Activities" }, { "name":"history", "label":"History", - "view":"Crm:Record.Panels.History" + "view":"crm:views/record/panels/history", + "aclScope": "Activities" }, { "name":"tasks", "label":"Tasks", - "view":"Crm:Record.Panels.Tasks" + "view":"crm:views/record/panels/tasks", + "aclScope": "Task" } ] }, diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Contact.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Contact.json index 57b2f8def4..fef32b2932 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Contact.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Contact.json @@ -8,17 +8,20 @@ { "name":"activities", "label":"Activities", - "view":"Crm:Record.Panels.Activities" + "view":"crm:views/record/panels/activities", + "aclScope": "Activities" }, { "name":"history", "label":"History", - "view":"Crm:Record.Panels.History" + "view":"crm:views/record/panels/history", + "aclScope": "Activities" }, { "name":"tasks", "label":"Tasks", - "view":"Crm:Record.Panels.Tasks" + "view":"crm:views/record/panels/tasks", + "aclScope": "Task" } ] }, diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Lead.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Lead.json index b966230de3..c6b9ff7754 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Lead.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Lead.json @@ -36,17 +36,20 @@ { "name":"activities", "label":"Activities", - "view":"Crm:Record.Panels.Activities" + "view":"crm:views/record/panels/activities", + "aclScope": "Activities" }, { "name":"history", "label":"History", - "view":"Crm:Record.Panels.History" + "view":"crm:views/record/panels/history", + "aclScope": "Activities" }, { "name":"tasks", "label":"Tasks", - "view":"Crm:Record.Panels.Tasks" + "view":"crm:views/record/panels/tasks", + "aclScope": "Task" } ], "edit": [ diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Opportunity.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Opportunity.json index e2bb777aec..e6027250e0 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Opportunity.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Opportunity.json @@ -8,17 +8,20 @@ { "name":"activities", "label":"Activities", - "view":"Crm:Record.Panels.Activities" + "view":"crm:views/record/panels/activities", + "aclScope": "Activities" }, { "name":"history", "label":"History", - "view":"Crm:Record.Panels.History" + "view":"crm:views/record/panels/history", + "aclScope": "Activities" }, { "name":"tasks", "label":"Tasks", - "view":"Crm:Record.Panels.Tasks" + "view":"crm:views/record/panels/tasks", + "aclScope": "Task" } ] }, diff --git a/application/Espo/Modules/Crm/Resources/metadata/scopes/Activities.json b/application/Espo/Modules/Crm/Resources/metadata/scopes/Activities.json index d22d5e93df..341728c1a7 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/scopes/Activities.json +++ b/application/Espo/Modules/Crm/Resources/metadata/scopes/Activities.json @@ -2,7 +2,7 @@ "entity": false, "layouts": false, "tab": false, - "acl": false, + "acl": "boolean", "module": "Crm", "customizable": false } diff --git a/application/Espo/Resources/i18n/en_US/EntityManager.json b/application/Espo/Resources/i18n/en_US/EntityManager.json index 75a3cfeec1..05f9bc527e 100644 --- a/application/Espo/Resources/i18n/en_US/EntityManager.json +++ b/application/Espo/Resources/i18n/en_US/EntityManager.json @@ -19,7 +19,8 @@ "sortDirection": "Default Order (direction)", "relationName": "Middle Table Name", "linkMultipleField": "Link Multiple Field", - "linkMultipleFieldForeign": "Foreign Link Multiple Field" + "linkMultipleFieldForeign": "Foreign Link Multiple Field", + "disabled": "Disabled" }, "options": { "type": { diff --git a/frontend/client/modules/crm/src/views/lead/record/panels/converted-to.js b/frontend/client/modules/crm/src/views/lead/record/panels/converted-to.js index dc3de98736..0e36e1aa85 100644 --- a/frontend/client/modules/crm/src/views/lead/record/panels/converted-to.js +++ b/frontend/client/modules/crm/src/views/lead/record/panels/converted-to.js @@ -33,14 +33,14 @@ Espo.define('crm:views/lead/record/panels/converted-to', 'views/record/panels/si setup: function () { this.fieldList = []; - if (this.getAcl().check('Account')) { + if (this.getAcl().check('Account') && !this.getMetadata().get('scopes.Account.disabled')) { this.fieldList.push('createdAccount'); } - if (this.getAcl().check('Contact')) { + if (this.getAcl().check('Contact') && !this.getMetadata().get('scopes.Contact.disabled')) { this.fieldList.push('createdContact'); } - if (this.getAcl().check('Opportunity')) { + if (this.getAcl().check('Opportunity') && !this.getMetadata().get('scopes.Opportunity.disabled')) { this.fieldList.push('createdOpportunity'); } diff --git a/frontend/client/modules/crm/src/views/meeting/record/panels/attendees.js b/frontend/client/modules/crm/src/views/meeting/record/panels/attendees.js index b50aa14f3a..aa02dc2a98 100644 --- a/frontend/client/modules/crm/src/views/meeting/record/panels/attendees.js +++ b/frontend/client/modules/crm/src/views/meeting/record/panels/attendees.js @@ -35,10 +35,10 @@ Espo.define('crm:views/meeting/record/panels/attendees', 'views/record/panels/si this.fieldList.push('users'); - if (this.getAcl().check('Contact')) { + if (this.getAcl().check('Contact') && !this.getMetadata().get('scopes.Contact.disabled')) { this.fieldList.push('contacts'); } - if (this.getAcl().check('Lead')) { + if (this.getAcl().check('Lead') && !this.getMetadata().get('scopes.Lead.disabled')) { this.fieldList.push('leads'); } diff --git a/frontend/client/res/templates/admin/entity-manager/modals/edit-entity.tpl b/frontend/client/res/templates/admin/entity-manager/modals/edit-entity.tpl index d902b4d3b7..6e48a426ae 100644 --- a/frontend/client/res/templates/admin/entity-manager/modals/edit-entity.tpl +++ b/frontend/client/res/templates/admin/entity-manager/modals/edit-entity.tpl @@ -26,16 +26,24 @@ -{{#if stream}} +
+
+ +
+ {{{disabled}}} +
+
+ {{#if stream}}
{{{stream}}}
+ {{/if}}
-{{/if}} + {{#if sortBy}}
diff --git a/frontend/client/src/acl.js b/frontend/client/src/acl.js index 60dcf1abe1..7f356d06d6 100644 --- a/frontend/client/src/acl.js +++ b/frontend/client/src/acl.js @@ -63,25 +63,25 @@ Espo.define('acl', [], function () { return this.data[name] || null; }, - check: function (controller, action, isOwner, inTeam) { + check: function (scope, action, isOwner, inTeam) { if (this.user.isAdmin()) { return true; } - if (controller in this.data.table) { - if (this.data.table[controller] === false) { + if (scope in this.data.table) { + if (this.data.table[scope] === false) { return false; } - if (this.data.table[controller] === true) { + if (this.data.table[scope] === true) { return true; } - if (typeof this.data.table[controller] === 'string') { + if (typeof this.data.table[scope] === 'string') { return true; } if (typeof action !== 'undefined') { - if (action in this.data.table[controller]) { - var value = this.data.table[controller][action]; + if (action in this.data.table[scope]) { + var value = this.data.table[scope][action]; if (value === 'all' || value === true) { return true; @@ -96,7 +96,7 @@ Espo.define('acl', [], function () { } if (isOwner && action == 'delete' && value === 'no') { - return this.check(controller, 'edit', isOwner); + return this.check(scope, 'edit', isOwner); } if (!value || value === 'no') { @@ -121,6 +121,10 @@ Espo.define('acl', [], function () { return true; }, + checkScope: function (scope, action) { + return this.check(scope, action); + }, + checkModel: function (model, action) { if (action == 'edit') { if (!model.isEditable()) { diff --git a/frontend/client/src/metadata.js b/frontend/client/src/metadata.js index 5378fc1bde..5f4edc534d 100644 --- a/frontend/client/src/metadata.js +++ b/frontend/client/src/metadata.js @@ -106,6 +106,41 @@ Espo.define('metadata', [], function () { } }, + getScopeList: function () { + var scopes = this.get('scopes') || {}; + var scopeList = []; + for (scope in scopes) { + var d = scopes[scope]; + if (d.disabled) continue; + scopeList.push(scope); + } + return scopeList; + }, + + getScopeObjectList: function () { + var scopes = this.get('scopes') || {}; + var scopeList = []; + for (scope in scopes) { + var d = scopes[scope]; + if (d.disabled) continue; + if (!d.object) continue; + scopeList.push(scope); + } + return scopeList; + }, + + getScopeEntityList: function () { + var scopes = this.get('scopes') || {}; + var scopeList = []; + for (scope in scopes) { + var d = scopes[scope]; + if (d.disabled) continue; + if (!d.entity) continue; + scopeList.push(scope); + } + return scopeList; + } + }, Backbone.Events); return Metadata; diff --git a/frontend/client/src/views/admin/entity-manager/index.js b/frontend/client/src/views/admin/entity-manager/index.js index 54a2510bb8..2f16cf404a 100644 --- a/frontend/client/src/views/admin/entity-manager/index.js +++ b/frontend/client/src/views/admin/entity-manager/index.js @@ -106,7 +106,7 @@ Espo.define('views/admin/entity-manager/index', 'view', function (Dep) { }, createEntity: function () { - this.createView('edit', 'Admin.EntityManager.Modals.EditEntity', {}, function (view) { + this.createView('edit', 'views/admin/entity-manager/modals/edit-entity', {}, function (view) { view.render(); this.listenTo(view, 'after:save', function () { @@ -114,11 +114,15 @@ Espo.define('views/admin/entity-manager/index', 'view', function (Dep) { this.setupScopeData(); this.render(); }, this); - }.bind(this)); + + this.listenTo(view, 'close', function () { + this.clearView('edit'); + }, this); + }, this); }, editEntity: function (scope) { - this.createView('edit', 'Admin.EntityManager.Modals.EditEntity', { + this.createView('edit', 'views/admin/entity-manager/modals/edit-entity', { scope: scope }, function (view) { view.render(); @@ -128,7 +132,11 @@ Espo.define('views/admin/entity-manager/index', 'view', function (Dep) { this.setupScopeData(); this.render(); }, this); - }.bind(this)); + + this.listenTo(view, 'close', function () { + this.clearView('edit'); + }, this); + }, this); }, removeEntity: function (scope) { diff --git a/frontend/client/src/views/admin/entity-manager/modals/edit-entity.js b/frontend/client/src/views/admin/entity-manager/modals/edit-entity.js index c5bb363dc8..e0a7d78863 100644 --- a/frontend/client/src/views/admin/entity-manager/modals/edit-entity.js +++ b/frontend/client/src/views/admin/entity-manager/modals/edit-entity.js @@ -80,12 +80,13 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo this.model.set('labelPlural', this.translate(scope, 'scopeNamesPlural')); this.model.set('type', this.getMetadata().get('scopes.' + scope + '.type') || ''); this.model.set('stream', this.getMetadata().get('scopes.' + scope + '.stream') || false); + this.model.set('disabled', this.getMetadata().get('scopes.' + scope + '.disabled') || false); this.model.set('sortBy', this.getMetadata().get('entityDefs.' + scope + '.collection.sortBy')); this.model.set('sortDirection', this.getMetadata().get('entityDefs.' + scope + '.collection.asc') ? 'asc' : 'desc'); } - this.createView('type', 'Fields.Enum', { + this.createView('type', 'views/fields/enum', { model: model, mode: 'edit', el: this.options.el + ' .field-type', @@ -100,7 +101,7 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo }); if (this.hasStreamField) { - this.createView('stream', 'Fields.Bool', { + this.createView('stream', 'views/fields/bool', { model: model, mode: 'edit', el: this.options.el + ' .field-stream', @@ -110,6 +111,15 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo }); } + this.createView('disabled', 'views/fields/bool', { + model: model, + mode: 'edit', + el: this.options.el + ' .field-disabled', + defs: { + name: 'disabled' + } + }); + this.createView('name', 'Fields.Varchar', { model: model, mode: 'edit', @@ -122,7 +132,7 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo }, readOnly: scope != false }); - this.createView('labelSingular', 'Fields.Varchar', { + this.createView('labelSingular', 'views/fields/varchar', { model: model, mode: 'edit', el: this.options.el + ' .field-labelSingular', @@ -133,7 +143,7 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo } } }); - this.createView('labelPlural', 'Fields.Varchar', { + this.createView('labelPlural', 'views/fields/varchar', { model: model, mode: 'edit', el: this.options.el + ' .field-labelPlural', @@ -161,7 +171,7 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo translatedOptions[item] = this.translate(item, 'fields', scope); }, this); - this.createView('sortBy', 'Fields.Enum', { + this.createView('sortBy', 'views/fields/enum', { model: model, mode: 'edit', el: this.options.el + ' .field-sortBy', @@ -174,7 +184,7 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo } }); - this.createView('sortDirection', 'Fields.Enum', { + this.createView('sortDirection', 'views/fields/enum', { model: model, mode: 'edit', el: this.options.el + ' .field-sortDirection', @@ -214,7 +224,8 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo 'type', 'labelSingular', 'labelPlural', - 'stream' + 'stream', + 'disabled' ]; if (this.scope) { @@ -254,7 +265,8 @@ Espo.define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'mo labelSingular: this.model.get('labelSingular'), labelPlural: this.model.get('labelPlural'), type: this.model.get('type'), - stream: this.model.get('stream') + stream: this.model.get('stream'), + disabled: this.model.get('disabled') }; if (this.scope) { diff --git a/frontend/client/src/views/admin/layouts/index.js b/frontend/client/src/views/admin/layouts/index.js index 28e8397944..ee0321c71b 100644 --- a/frontend/client/src/views/admin/layouts/index.js +++ b/frontend/client/src/views/admin/layouts/index.js @@ -26,11 +26,11 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -Espo.define('Views.Admin.Layouts.Index', 'View', function (Dep) { +Espo.define('views/admin/layouts/index', 'view', function (Dep) { return Dep.extend({ - template: 'admin.layouts.index', + template: 'admin/layouts/index', scopeList: null, @@ -82,16 +82,16 @@ Espo.define('Views.Admin.Layouts.Index', 'View', function (Dep) { setup: function () { this.scopeList = []; - var scopesAll = Object.keys(this.getMetadata().get('scopes')).sort(function (v1, v2) { + var scopeFullList = this.getMetadata().getScopeList().sort(function (v1, v2) { return this.translate(v1, 'scopeNamesPlural').localeCompare(this.translate(v2, 'scopeNamesPlural')); }.bind(this)); - scopesAll.forEach(function (scope) { + scopeFullList.forEach(function (scope) { if (this.getMetadata().get('scopes.' + scope + '.entity') && this.getMetadata().get('scopes.' + scope + '.layouts')) { this.scopeList.push(scope); } - }.bind(this)); + }, this); this.on('after:render', function () { $("#layouts-menu button[data-scope='" + this.options.scope + "'][data-type='" + this.options.type + "']").addClass('disabled'); diff --git a/frontend/client/src/views/record/detail-bottom.js b/frontend/client/src/views/record/detail-bottom.js index a660fec3a9..198be17c78 100644 --- a/frontend/client/src/views/record/detail-bottom.js +++ b/frontend/client/src/views/record/detail-bottom.js @@ -26,11 +26,11 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -Espo.define('Views.Record.DetailBottom', 'View', function (Dep) { +Espo.define('views/record/detail-bottom', 'view', function (Dep) { return Dep.extend({ - template: 'record.bottom', + template: 'record/bottom', mode: 'detail', @@ -72,7 +72,7 @@ Espo.define('Views.Record.DetailBottom', 'View', function (Dep) { panelList.push({ "name":"stream", "label":"Stream", - "view":"Stream.Panel", + "view":"views/stream/panel", "sticked": true }); } @@ -112,6 +112,18 @@ Espo.define('Views.Record.DetailBottom', 'View', function (Dep) { this.scope = this.model.name; this.setupPanels(); + + var panelList = []; + this.panelList.forEach(function (p) { + if (p.aclScope) { + if (!this.getAcl().checkScope(p.aclScope)) { + return; + } + } + panelList.push(p); + }, this); + this.panelList = panelList; + this.setupPanelViews(); if (this.relationshipPanels) { @@ -122,6 +134,8 @@ Espo.define('Views.Record.DetailBottom', 'View', function (Dep) { setupRelationshipPanels: function () { var scope = this.scope; + var scopesDefs = this.getMetadata().get('scopes') || {}; + this.wait(true); this._helper.layoutManager.get(this.model.name, 'relationships', function (layout) { var panelList = layout; @@ -144,6 +158,9 @@ Espo.define('Views.Record.DetailBottom', 'View', function (Dep) { } var foreignScope = links[name].entity; + + if ((scopesDefs[foreignScope] || {}).disabled) return; + if (!this.getAcl().check(foreignScope, 'read')) { return; } diff --git a/frontend/client/src/views/record/detail-side.js b/frontend/client/src/views/record/detail-side.js index 41b2436f85..4a11dcaca9 100644 --- a/frontend/client/src/views/record/detail-side.js +++ b/frontend/client/src/views/record/detail-side.js @@ -25,7 +25,8 @@ * In accordance with Section 7(b) of the GNU General Public License version 3, * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ - Espo.define('views/record/detail-side', 'view', function (Dep) { + +Espo.define('views/record/detail-side', 'view', function (Dep) { return Dep.extend({ @@ -117,6 +118,17 @@ this.panelList.push(panel); }, this); + var panelList = []; + this.panelList.forEach(function (p) { + if (p.aclScope) { + if (!this.getAcl().checkScope(p.aclScope)) { + return; + } + } + panelList.push(p); + }, this); + this.panelList = panelList; + this.panelList.forEach(function (p) { var o = { model: this.options.model, @@ -139,8 +151,8 @@ } else { p.title = view.title; } - }.bind(this)); - }.bind(this)); + }, this); + }, this); }, getFields: function () { diff --git a/frontend/client/src/views/role/record/table.js b/frontend/client/src/views/role/record/table.js index f230492c7b..a7ed364e38 100644 --- a/frontend/client/src/views/role/record/table.js +++ b/frontend/client/src/views/role/record/table.js @@ -26,11 +26,11 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -Espo.define('Views.Role.Record.Table', 'View', function (Dep) { +Espo.define('views/role/record/table', 'view', function (Dep) { return Dep.extend({ - template: 'role.table', + template: 'role/table', scopeList: null, @@ -139,6 +139,7 @@ Espo.define('Views.Role.Record.Table', 'View', function (Dep) { }.bind(this)); scopesAll.forEach(function (scope) { + if (this.getMetadata().get('scopes.' + scope + '.disabled')) return; var acl = this.getMetadata().get('scopes.' + scope + '.acl'); if (acl) { this.scopeList.push(scope); diff --git a/frontend/client/src/views/settings/fields/quick-create-list.js b/frontend/client/src/views/settings/fields/quick-create-list.js index fefbc257b0..81e9443aad 100644 --- a/frontend/client/src/views/settings/fields/quick-create-list.js +++ b/frontend/client/src/views/settings/fields/quick-create-list.js @@ -32,14 +32,14 @@ Espo.define('views/settings/fields/quick-create-list', 'views/fields/array', fun setup: function () { this.params.options = Object.keys(this.getMetadata().get('scopes')).filter(function (scope) { + if (this.getMetadata().get('scopes.' + scope + '.disabled')) return; return this.getMetadata().get('scopes.' + scope + '.entity') && this.getMetadata().get('scopes.' + scope + '.tab'); }, this).sort(function (v1, v2) { return this.translate(v1, 'scopeNamesPlural').localeCompare(this.translate(v2, 'scopeNamesPlural')); }.bind(this)); Dep.prototype.setup.call(this); - }, - + } }); diff --git a/frontend/client/src/views/settings/fields/tab-list.js b/frontend/client/src/views/settings/fields/tab-list.js index 5f7d21e202..570a548acc 100644 --- a/frontend/client/src/views/settings/fields/tab-list.js +++ b/frontend/client/src/views/settings/fields/tab-list.js @@ -25,22 +25,22 @@ * In accordance with Section 7(b) of the GNU General Public License version 3, * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -Espo.define('Views.Settings.Fields.TabList', 'Views.Fields.Array', function (Dep) { +Espo.define('views/settings/fields/tab-list', 'views/fields/array', function (Dep) { return Dep.extend({ - + setup: function () { this.params.options = Object.keys(this.getMetadata().get('scopes')).filter(function (scope) { + if (this.getMetadata().get('scopes.' + scope + '.disabled')) return; return this.getMetadata().get('scopes.' + scope + '.tab'); }, this).sort(function (v1, v2) { return this.translate(v1, 'scopeNamesPlural').localeCompare(this.translate(v2, 'scopeNamesPlural')); }.bind(this)); Dep.prototype.setup.call(this); - }, - - + } + }); - + }); diff --git a/frontend/client/src/views/site/navbar.js b/frontend/client/src/views/site/navbar.js index 0a21ee61c4..948055c689 100644 --- a/frontend/client/src/views/site/navbar.js +++ b/frontend/client/src/views/site/navbar.js @@ -30,7 +30,7 @@ Espo.define('views/site/navbar', 'view', function (Dep) { return Dep.extend({ - template: 'site.navbar', + template: 'site/navbar', currentTab: null, @@ -102,15 +102,19 @@ Espo.define('views/site/navbar', 'view', function (Dep) { tabList = tabList || []; + var scopes = this.getMetadata().get('scopes') || {}; + this.tabList = tabList.filter(function (scope) { - if (this.getMetadata().get('scopes.' + scope + '.acl')) { + if ((scopes[scope] || {}).disabled) return; + if ((scopes[scope] || {}).acl) { return this.getAcl().check(scope); } return true; }, this); this.quickCreateList = (this.getConfig().get('quickCreateList') || []).filter(function (scope) { - if (this.getMetadata().get('scopes.' + scope + '.acl')) { + if ((scopes[scope] || {}).disabled) return; + if ((scopes[scope] || {}).acl) { return this.getAcl().check(scope, 'edit'); } return true; diff --git a/frontend/client/src/views/user/record/detail-side.js b/frontend/client/src/views/user/record/detail-side.js index 9c08553ca0..18b12336d7 100644 --- a/frontend/client/src/views/user/record/detail-side.js +++ b/frontend/client/src/views/user/record/detail-side.js @@ -34,7 +34,7 @@ Espo.define('views/user/record/detail-side', 'views/record/detail-side', functio { name: 'default', label: false, - view: 'Record.Panels.Side', + view: 'views/record/panels/side', options: { fieldList: ['avatar'], mode: 'detail', @@ -65,13 +65,15 @@ Espo.define('views/user/record/detail-side', 'views/record/detail-side', functio "name":"activities", "label":"Activities", "view":"crm:views/record/panels/activities", - "hidden": !showActivities + "hidden": !showActivities, + "aclScope": "Activities" }); this.panelList.push({ "name":"history", "label":"History", "view":"crm:views/record/panels/history", - "hidden": !showActivities + "hidden": !showActivities, + "aclScope": "Activities" }); }