Let the platform do the work

Migrating from Sugar 6.x to 7

Introduction

Note: As of release 7.5, most instances can be upgraded from Sugar 6 to 7. This article is for customers who are not interested in upgrading but wish to move their data and customizations from a Sugar 6 instance to a Sugar 7 instance. For information about upgrading, please refer to the Installation and Upgrade Guide specific to the version and edition to which you wish to upgrade.

The vision of Sugar 7 is one that offers immense potential for administrators and developers to exercise their service and enablement skills. Moving to 7 is an opportunity to review an instance's current customizations and workflows and look for where the new capabilities in 7, and your expertise can bring added value and extend success forward.

Migration is both an opportunity to build or extend new features as well as remove customizations that are no longer required and/or optimize existing processes.

While analyzing an instance to be migrated, attention should be given to the following:

  • New Sugar 7 features that could help optimize business processes (i.e., Intelligence Pane, Activity Streams, Forecasts)
  • Technical changes that could influence existing code customizations
    • Optimization for current customizations
    • Custom code that can be replaced with Studio-based functionality for improved manageability and safer upgrades
    • Integrations that the new Sidecar framework and REST API can better service

This may involve performing follow-up discovery sessions to get introduced to the new possibilities and work towards optimizing Sugar to help meet important business objectives.

When reviewing code customizations, there should be attention given to data migration, as some things could be significantly impacted. Areas of focus include:

  • Reviewing data quality in the existing system
  • Defining criteria for finding duplicates and assuring data quality
  • Defining if and which data should not be migrated (e.g., closed tasks that are older than x years)
  • Defining a migration plan to convert Opportunity information to Revenue Line Item (RLI) records in the new Forecast module (Note: this is only available for Enterprise and Ultimate licenses)

Defining a technical upgrade plan should include:

  • Upgrading the existing installation to a proper version of Sugar (6.5.x or 6.7.x) before attempting to upgrade to version 7
  • Determining how many steps are ideal to make the migration manageable
  • Carefully planning migrations requiring interim upgrades so as to gradually progress and minimize disruptions

Initiation Phase

When migrating from 6.x to 7, one has to consider available resources, amount of time required to make desired changes, the required interim steps (if any), and applicable deployment options, including the use of Legacy mode. There is a need, as with any project, to conduct appropriate discovery, estimates and create a project plan, but this document will not cover those concepts.

The focus of this document will be on the items requiring special attention when migrating to Sugar 7 from previous versions. Knowing what to account for when performing this task will, in turn, help build your project plans and allocate resources in a way that supports project success.

Overview

There are some significant changes in the way Sugar is architected when compared to previous versions of the product. Core Sugar is still a PHP-driven application, but moving forward new skills are required to work with the Sugar platform. Perhaps the most import change is the prominent and extended use of JavaScript code, including a new framework developed at SugarCRM, called Sidecar.

Sidecar is largely built and extended from well-established, open, modern libraries; some highlights are noted below:

  • Sidecar itself is a completely new MVC implementation including routing. It is lightweight and skeletal, with no direct application functionality and built largely off of Backbone.js
  • jQuery.js and Underscore.js complement Backbone functionality throughout
  • Templating and HTML content is generally handled via Handlebars.js
  • Entire application is metadata driven
  • Twitter Bootstrap.js library is used extensively for many User Interface (UI) elements

Each of these has their own development communities with additional documentation that you can leverage, along with this overview and the Sugar Developer Guide. With regards to data storage, Sugar 7 currently only supports MySQL. DB2 support will be added with our 7.2 release, and MSSQL and Oracle databases are expected to be added as supported databases with the 7.5 release.

Familiarizing Yourself With Sugar 7

Architecture

Introduced with Sugar 6.7, there are two available rendering modes in the Sugar product:

  • Sugar MVC: The classic view and structure of a module that has existed since Sugar 5. HTML is built server-side, to be rendered on the client.
  • Sidecar: The new Backbone, Handlebars, and Bootstrap-driven module structure. In this case, the server-side backend will send only metadata to the client where the client will build the actual HTML and render it.

The key changes from 6.5 to 7.x is that we have incrementally phased out the manner in which the default rendering in the application is done, as well as which modules use the new rendering mode as illustrated in the following chart:

This means moving to Sugar 7 initially does not require converting all of the modules from Sugar MVC to Sidecar. Depending upon the amount of customization applied to a given module, it very well could make sense to leave the module in the Legacy UI and render it using the Sugar MVC view instead of adopting Sidecar for that particular module. Some reasons that lead one to use Legacy mode over Sidecar include:

  • Use of multiple, custom, non-metadata driven views
  • Deep customizations to the edit/detail/list/search views to support specific use cases that the Sidecar equivalents do not easily support
  • Use of after_ui_frame logic hook(s) to display custom designed subpanels that do not fit into the space of a dashlet
  • Variable costs of converting a module to Sidecar

Moving to 7 while leaving modules in Legacy mode does provide you some benefits, such as:

  • An updated SugarCRM mobile app client that has a complementary set of User Experience (UX) patterns and well integrated with the supported platforms (iOS and Android)
  • New RESTful web services
  • Performance improvements
  • A modern platform for building out future modules that can leverage the Sidecar rendering engine and the RESTful API

Note: Native sidecar modules set to run in the Legacy UI are not supported.

Some things to consider when evaluating a migration:

When encountering a project to migrate from Sugar 6.x to Sugar 7, there are a number of business decisions you need to think about before figuring out the best course of action.

Some questions that one should ask include:

  • What is the motivation for someone moving to Sugar 7? Are you eager to use the latest Sugar features or particular new feature, wanting the increased ease of future integration/customization development, desirous of standardization across your practice, or needing to fulfill the requirements of a certain application?
  • What is the current state of the Sugar instance? Are there customizations? How were they done? What (if any) other integrations are there?
  • What is the expectation for the finished product? While you will eventually need to have the full Sidecar experience, how many steps you take between where you are can mean just moving over to the minimum Sugar 7 product (maximum use of Legacy mode) to start; how many steps will make a full migration and over what period of time?
  • What is the timetable/budget? Do we need everything now, or can we deliver bits over time? What budget is set aside for the migration?

Using this as a starting point better describes what is needed to migrate to Sugar 7. A matrix of migration options per module, based on how the module was built initially, can help determine the most efficient migration path:

How Module was Built Migration Options Migration Effort
Module built via Module Builder, no other outside work done to it Should convert automatically to a Sidecar module Easy
Module built via Module Builder, customized outside of Module Builder in an upgrade-safe manner Might convert automatically to a Sidecar module but may require some manual migration Easy to Moderate
Module built via Module Builder, customized outside of Module Builder in a non-upgrade-safe manner Will possibly require manual migration Moderate to Difficult
Many core file modifications Will need significant re-architecture Difficult

In some cases, the most sensible approach may, in fact, be a full jump from 6.x to 7, but it is just as likely that the stepping will be: 6.x MVC to Sidecar + Legacy, and then from Sidecar + Legacy, to a full Sidecar implementation. There may be several gradual steps in between, and every migration should be evaluated and developed based on its own criteria and what is the optimal path to success.

Sugar 7 itself is initially being released with several modules in BCM; a full list is provided in the introductory BCM section of the Sugar Developer Guide.

Sidecar

Sidecar is built atop several components:

Backbone.js

Backbone.js gives structure to web applications by providing models with key-value binding and custom events and collections with a rich API of enumerable functions and views with declarative event handling and connects it all to your existing API over a RESTful JSON interface.

Backbone provides "bare bones" Models, Collections, Routing, Views, and Events. Backbone does not give you logic, DOM structure, data formatting etc.

Layouts, Views, and Fields

Views

For those of you with experience developing solutions based on the pre-7.0 SugarCRM framework, you might find it beneficial to further investigate the files referenced below as they represent equivalents to older views/techniques, within the context of the Sidecar framework.

Sugar 6.x Edit/Detail View:

  • [custom]/modules/<module>/views/view.detail.php
  • [custom]/modules/<module>/views/view.edit.php

Sugar 7.x Record View:

  • [custom]/modules/<module>/clients/base/views/record/record.js
  • [custom]/modules/<module>/clients/base/views/record/record.hbs
Fields

Sugar 6.x Multiselect Field

  • [custom]/include/SugarFields/Fields/Enum/SugarFieldEnum.php

Sugar 7.x Multiselect Field

  • [custom]/clients/base/fields/enum/enum.js

Everything that is renderable on the page is a component. A layout (a feature introduced in 7.x) is a component that serves as a canvas for one or more views and/or other layouts. All pages will have at least one base layout, and that base layout can contain multiple nested layouts.

Example layouts include:

  • Rows
  • Columns
  • Bootstrap fluid layouts, and
  • Drawers/dropdowns
  • Extend from Backbone.View
  • Render method and $el
  • Event handling

Views are components which render data from a context and may or may not include field components. Example views include not only record and list views but also widgets including:

  • Graphs or other data visualizations
  • External data views such as Twitter, LinkedIn, or other web service integrations
  • The global header

Fields render widgets for individual values pulled from the models and handle formatting (or stripping the formatting of) field values. Just like Layouts and Views, Fields also extend Backbone Views.

A Context is a container for the relevant data for a page, and it has three major attributes:

  • Module: The name of the module this context is based on
  • Model: The primary or selected model for this context
  • Collection: The set of models currently loaded on this context

Contexts can be used to retrieve related data and to paginate through lists of data.

Beans extend from the Backbone.Model and handle numerous functions, including:

  • Validation checks
  • Interacting with the SugarAPI to save and load data
  • Triggering events that widgets use to update/render

Routes have also changed in Sugar 7. The router listens for changes to the #route and calls into the controller. Most routes just call loadView (which actually loads a layout) and the layout loaded is based on the action specified in the route. Applications that require custom routing must add them to the router directly (this is not usually necessary as layouts determine the page content).

Example Layouts

Each component on a Layout can either be a Sidecar View or another Layout. By nesting them, you can create complex and dynamic pages that are easy to manage. In the Figure above, you can see an example page view in Sidecar. A Row Layout is at the top level with two components, View1 and a Column Layout. The Column Layout also has two components, View 2 and View 3.

In the diagram above, you can see a Bootstrap Fluid Layout. The fluid grid system uses percents for column widths. The default Bootstrap grid system uses 12 columns. To have 3 columns, you can have 3 simple layouts in a fluid layout with span4 set for each one.

Metadata

There have been some changes with respect to metadata management; below is an example:

Sugar 6.x:

  • [custom]/modules/<module>/metadata/detailviewdefs.php
  • [custom]/modules/<module>/metadata/editviewdefs.php

Sugar 7.x:

  • [custom]/modules/<module>/clients/base/views/record/record.php
UX/Presentation Layer

Bootstrap.js is used for the Sugar 7 presentation layer. It is a very robust, extensible library initially released by Twitter.

The new styleguide structure is packaged with all builds of Sugar and is accessible to Admin-level users by simply entering the following URL into their web browser: https://your_sugar_url/styleguide

Your application should have its own folder inside styleguide if your stylesheet needs to differ from the base one. Variables for different themes are contained in this folder, and you can create a default theme for your that has different colors than the base one.

  • config.less contains all the LESS files you will want to import
  • There are subfolders for the reference Twitter Bootstrap library, as well as those for Sugar customizations made on Twitter Bootstrap and Sugar customizations independent from Twitter Bootstrap.

Portal Example

/less/clients/portal/config.less is the file that imports the LESS files for the Portal platform:

  /* Configuration file for importing LESS files */

// Variables

@import "../../fixed_variables.less";

// Twitter bootstrap files

@import "../../twitter-bootstrap/bootstrap.less";

blah

  // Sugar customizations made on bootstrap files

@import "../../sugar-bootstrap/bootstrap.less";

// Sugar customizations independent from Twitter Bootstrap

@import "../../sugar-specific/config.less";

// Sugar customizations for this platform

@import "custom.less";
@import "alerts.less";

This contains the includes and variables (all the Bootstrap and independent classes)

What do I need to pull the CSS file dynamically?

A new configuration var has been added in config.js:

/**

* Loads css dynamically when the app inits

* Defaults to false otherwise set "url" or "text"

* @cfg {String}

*/

loadCss : "url"

Explanation:

  • Regarding the default to false: Do not load any CSS dynamically; do not make a call to the Theme API.
  • url: Make a call to the Rest API, which returns the link of the CSS file, and adds a <link> tag on the page to load the file.
  • text: Make a call to the Rest API, which returns the plain text css and adds a <style> tag on the page to load the file (note that our API does not allow that yet).

Sugar 7 API

The new REST API was introduced in 6.7, but is being fully realized with Sugar 7. Much of Sugar 7 is driven by it, and it is fully documented through the API endpoint: /rest/v10/help. Please note that the 6.7 implementation is not a direct equivalent of the 7.0 implementation. The 7.0 implementation is richer and offers additional functionality.

There are many reasons to move to a fully RESTful API:

  • Ease of maintenance
  • Ease of creating integrations/working with other web services
  • Easier to debug and fix issues
  • Scalability and improved cache handling
  • New SugarCRM mobile app enablement
  • Improved throughput using JSON instead of XML
How the API works

A new configuration var has been added:

/**

* Loads css dynamically when the app inits

* Defaults to false otherwise set "url" or "text"

* @cfg {String}

*/

loadCss : "url"

Explanation:

  • Before calling app.metadata.sync, the app will make an API call to the ThemeApi (endpoint: /rest/v10/css) with config.platform and config.themeName as arguments.
  • The API will compile bootstrap.css if it does not exist yet and put it in /cache/.
  • It will take care of compiling the bootstrap.css for your platform, so make sure that the platform name in your config and the folder in styleguide/less/clients is the same.
  • If themeName is undefined or does not exist, the API will take the default theme.
  • If your platform is not defined in the style guide, the API will take the base theme.

Deployment Options

The following should be taken into consideration:

  • 7.1.x is for new on-site installs on the LAMP stack and upgrades from 7.0 in Sugar's cloud environment.
  • 7.1.5 is for select SugarCloud instances running the 6.7.x release who are ready to migrate to Sugar 7.
  • Any instances running 6.7.x should contact Sugar Support to see if their instance is capable of being upgraded. This release will also be an available upgrade for on-site installs running 7.1.0.
  • 7.2 will be available for both SugarCloud and on-site deployments on the LAMP stack as well as instances running DB2 in conjunction with Linux, Apache, and PHP.
  • 7.5 will be available for both SugarCloud and on-site deployments on all stacks supported for 6.5 (Windows/Linux and MySQL/MSSQL/Oracle/DB2)

With the release of Sugar 7.x, the SugarCloud environment is moving fully to a Rapid Release schedule. Upgrades occur automatically (with advance notification on major feature versions), and the ability to park an instance at a particular version indefinitely is no longer possible. Using Sugar's cloud service means that instances with customizations will have to be managed via regular validation of customizations in sandbox environments (which Sugar's cloud service can provide) and subsequently pushed to a test/staging instance and/or production. While ultimately how this is structured is up to you, Sugar generally recommends:

  • One development sandbox
  • One staging/test sandbox, which is cloned from production and refreshed at regular intervals to maintain clear parity with the production instance.
  • Production. No development should be done directly on this with only modifications made and/or customizations added via Module Loader after being developed and validated on a sandbox.

Note: In Sugar's cloud environment, your overall file system usage is determined by your product purchase, including the number of allowed sandboxes. Packages for additional storage and sandboxes are available.

Elasticsearch

Starting with 7.1, you will now be required to have Elasticsearch deployed and enter your Elasticsearch server details during installation. During the Sugar upgrade/install, a full system index will run with or without demo data. This affects both silent install and the install wizard. For those that are completely new to Elasticsearch and how it powers Sugar Full-Text Search (FTS ) take a look at the Elasticsearch overview referenced below:

For those of you utilizing the silent install option, update the config_si.php file and add the following snippet to the $sugar_config_si array:

'setup_fts_type' => 'Elastic',

'setup_fts_host' => 'localhost', //Your Elastic server host

'setup_fts_port' => '9200', //Your Elastic server port
  • Install wizard: Elasticsearch host and port fields are required fields. Therefore, you will not be able to proceed to the next step of the wizard. Also, the install verifies a successful connection before you can proceed to the next step.
  • Silent install: You will be prompted to enter the Elasticsearch server details.

By default, you do not have to run silentFTSIndex.php. The system does that for you automatically during the install. This is true regardless if you install with or without demo data. However, if you do not wish the system to run the full system index during installation, you have the option to skip it only during silent installation. This can be simply done by adding the following in your silent install configuration (config_si.php) file:

  • 'setup_fts_skip' => true,

References

With respect to Full-Text Search, you can use REST calls to:

Search for everything that contains something:

  • GET /search?q=<needle>

Filter for only some modules:

  • GET /search? q=<needle>&module_list=<module_list>

The Filter API

Examples of Filter API queries:

  • GET /<module>?filter[0][field_1]=value_1&filter[1][link_name.field_2]=value_2

Or if you like things a little more clean and readable:

/<module>?filter=[

    {'field_1': 'value_1'},

    {'link_name.field_2': 'value_2'}

    ]
GET /Accounts?filter[0][billing_address_state]=CA&filter[1][cases.status]=New

{

"next_offset": -1, "records": [{

"id": "f01e2bde-4284-e3ec-2379-524644b976fd",

"name": "T-Squared Techs", //...

"_module": "Accounts" }, {

"id": "eeea02c2-6171-f506-035b-5246440e0fdc",

"name": "Calm Sailing Inc", //...

"_module": "Accounts"

Debugging and Troubleshooting Sugar 7

Debugging Sidecar and the Portal (Client Side)

Cleaning App Cache

Chrome:

  • Right-click on the active page.
  • Click on Console tab.
  • Type:
SUGAR.App.cache.cutAll(true)
  • Refresh the page. You will have to sign in again.

Memory Leak Checks

With Layouts, Views, and Fields (components), dispose calls will unbind all known events, remove the element(s) from the DOM, and sets things up for garbage collection.

Dispose calls:

  • unbindData: Removes this component's event handlers from model and collection (balanced with bindDataChange)
  • unbind: Removes all event callbacks registered within this component and "undelegates" Backbone events
  • remove: Removes this view by taking the element out of the DOM, and removing any applicable Backbone Events listeners

Sidecar removes listeners on dispose:

model/collection/context.on('event', function() {}, this);

All events on view, layout, and field:

app.events.on('event', function() {},this);
  • controller.loadView() clears all events on models and collections in the context

How to avoid problems:

  • Do not change elements outside of your views.
  • Do not bind events to elements outside of your views.
  • Do not add DOM elements outside of your views.
  • Do not forget to dispose your custom code properly and to call parent (inheritance) dispose properly.
  • You should use Sugar plugins as much as possible (e.g., Tooltip, EllipsisInline).
  • You should manually remove all listeners yourself on things like:
this.context.parent.on('change', function() {}, this);

field.view.on('change', function() {}, field);

Sugar Visibility/ACL Layer

Sugar now has the ability to implement very granular control within its visibility rules.

Visibility

Implementation

This implementation provides more complex controls over which records can be accessed and in which manner, in a pluggable upgrade-safe fashion, while preserving current Sugar functionality and causing minimal disruption. By using additional vardef parameters per module, you can define which additional visibility classes to activate for every module. If Elasticsearch is desired, one needs to be sure the same security model is implemented, too.

Filtering

Visibility filtering is applied on lists of objects (list views, popups, exports, et al). It is implemented as an SQL query modification, so the query does not return records which are not visible. This is necessary because of the requirements of the way Sugar does pagination/navigation which requires a DB query to return page_size+1 records. Visibility filtering is managed by the BeanVisibility class. The SugarBean automatically loads it via the loadVisibility() method, passing a "visibility" vardef part as a parameter. This part is an array containing the list of visibility implementation classes:

$vardefs = array(

 'visibility' => array('TeamSecurity' => true),

); 

The key for the array is the class name, and the value is passed to the class constructor unless it is false. In that case, the class is skipped, which allows customizations to remove visibility classes by changing their values to false.

Implementation Classes

Visibility implementation classes extend the SugarVisibility class and can implement two methods:

  • addVisibilityFrom
  • addVisibilityWhere

Both accept query strings and are supposed to modify it if records need to be filtered. The addVisibilityFrom query is before WHERE is applied (so it can only contain JOINs), and addVisibilityWhere is with a WHERE clause (which can be empty). A class can implement only one of the methods if the other part is not modified. See examples of such classes below:

public function addVisibilityWhere(&$query, $options = null)

public function addVisibilityFrom(&$query, $options = null)

The options parameter is an array. The handling options depend on the implementing classes. Currently, the following options are used:

  • table_alias: Used in a FROM clause in case it is used multiple times in the same query, in order to distinguish parts of the query
  • join_teams: Used in a FROM clause for TeamSecurity implementation in order to add to the/a teams table
  • action: Used in a WHERE clause to add a current view. By default, it is assumed that the current view is the list view

The system classes are loaded from data/visibility, and the custom classes from custom/data/visibility. The file name should match the class name with a .php suffix.

Currently Implemented Classes

Standard Sugar functionality has two visibility classes:

  1. TeamSecurity: In commercial editions only, this class implements team security as a FROM query. This is enabled by default for all objects inheriting the team_security template.
  2. ACLVisibility: Implements ACL limitations (such as "owner only" policy) as a WHERE query. This is enabled for all beans implementing ACL.

The method add_team_security_where_clause on a SugarBean currently adds only a FROM clause as it did before the refactoring.

Please take note of the following:

  • create_new_list_query applies to both FROM and WHERE clauses.
  • retrieve applies to FROM (team security) but not to WHERE (ACLs) clauses.
  • All customizations that create their own lists.
  • create_new_list_query should be checked to properly apply visibility rules.

ACLs

ACLs are a generic interface to determine if the user has rights to access certain functions such as a certain view or field on a particular module.

Generic Interface

SugarACL::checkAccess($module, $action, $context = array())

Checks access for a module to do the action. All other ACL checks ultimately go through this check.

SugarACL::checkField($module, $field, $action,  $context = array())

Checks access to a field of a module. See below for actions list.

SugarACL::getFieldAccess($module, $field, $context = array())

Gets access level for the field and returns one of the following:

SugarACL::ACL_NO_ACCESS - access denied

SugarACL::ACL_READ_ONLY - read only access

SugarACL::ACL_READ_WRITE - full access

 

SugarACL::filterModuleList($list, $action = 'access', $use_value = false)

Filters the list of modules and returns only those to which access is enabled. If use_value is true, the value in the list is used as the module name. Otherwise, the key is used.

SugarACL::disabledModuleList($list, $action = 'access', $use_value = false)

Returns the list of modules to which access is disabled.

SugarACL::moduleSupportsACL($module)

Checks if any ACL classes are attached to the module. This can be used to prevent running any ACL checks if the module has no ACL definitions.

SugarACL::listFilter(&$list, $context = array(), $options = array())

listFilter filters the list of fields and returns fields to which access is enabled. The following options are accepted in the Filter fields list:

  • blank_value (boolean): instead of removing inaccessible fields, include "there"
  • add_acl (boolean): instead of removing fields add 'acl' value with access level
  • suffix (string): strip suffix from field names
  • min_access (integer): require this level of access for field
  • use_value (boolean): look for field name in value, not in key of the list

Bean Functions

The SugarBean has additional functions to use for ACLs when bean context is available. These functions automatically fill the bean parameter of the context.

public function ACLAccess($view, $context = null)

Checks access to a specific view/action for the bean. If true is passed as context, it sets the owner_override context parameter (see below).

public function ACLFieldAccess($field, $action = 'access', $context = array())

Checks access to a specific field for the bean.

public function ACLFieldGet($field, $context = array())

Returns access level for the field (see getFieldAccess() above).

public function ACLFilterFields($view = 'detail', $context = array()) 

Cleans fields that current ACL does not allow access to.

public function ACLFilterFieldList(&$list, $context = array(), $options = array())

Legacy Functions

These are functions from legacy ACLs that were converted to the new ACL model since they are still frequently used:

ACLController::checkAccess($category, $action, $is_owner=false, $type='module') 

Similar to checkAccess() above, this is used as a measure while Legacy mode is in use.

ACLController::displayNoAccess($redirect_home = false) 

Displays a "no access" message for pages.

ACLController::moduleSupportsACL($module)

ACL Implementations

ACL implementation should extend the SugarACLStrategy class. It should implement the abstract method:

abstract public function checkAccess($module, $action, $context); 

The method returns true if access is allowed (default) and false otherwise. If any of the ACLs denies access to the action, the access is denied, even if other modules allow it. If ACL implementation does not recognize an action it should return true.

Other methods provided by the class include:

public function getCurrentUser($context) 

Extracts the user from context (defaults to the current user).

public function getUserID($context) 

Extracts the user ID from context (defaults to the current user).

ACLs for the module are defined by ACLs parameter in vardefs. This is merged with the list of default ACLs returned by function defaultACLs() of the bean. The parameter is an array, the key for the array is the class name, the value is passed to the class constructor, unless it is false, in which case the class is skipped (this allows customizations to remove ACL classes by changing their values to false).

Custom implementations are loaded from custom/data/acl and data/acl. Class name should start with SugarACL and the filename should match the class name with a .php suffix.

Field List Functions

These functions operate on a complete list of fields. By default, the code just applies a per-field function to each element of the list, however, if you can determine on which fields you want to operate up front, you may want to override this. SugarACLStatic overrides these methods.

public function checkFieldList($module, $field_list, $action, $context)

Checks a list of fields. This is like SugarACL::checkField but it operates on a list of fields together. $field_list is an array of key/value pairs. Value is the field name to be checked, and the return value should be an array containing the same keys and values should be true or false depending on if access is allowed or not. A special case is returning array() - then it means access to all fields is allowed. This allows shortcutting the check if we know this ACL does not change anything in specific context. See an example of usage of it in SugarACLStatic.

public function getFieldListAccess($module, $field_list, $context)  

The same as above, but instead of checking access for specific action, gets access level, like SugarACL::getFieldAccess. Should again return an array of key/values with access levels, or array() which means no access restrictions.

Current implementation

Currently implemented ACLs:

  • SugarACLStatic: The default Sugar ACLs.

Available ACLs

The following ACLs are currently supported; note that names are not case-sensitive:

  • index, list, listview: For module ListView access
  • detail, detailview, view: For module DetailView access
  • popupeditview, editview: For module EditView access
  • edit, save: Editing module data
  • import: Importing into the module
  • export: Exporting from the module
  • delete: Deleting the module record
  • team_security: Should this module have team security enabled?
  • field: Access field ACLs. Action is specified via context, and is one of the following:
    • access: Any access to field data
    • read, detail: Read access
    • write, edit: Write access
  • subpanel: Checks if subpanel should be displayed. Should have "subpanel" context option.

Context Options

The following options are used in contexts:

  • bean: Current SugarBean object
  • user: Current user (overrides global current user)
  • user_id: Current user ID (overrides global current user). If the current user object is available, use the user context, since it has priority over this one
  • owner_override: If set to true, apply ACLs as if the current user were the owner of the object
  • field, action: Used to specify field name and action name for field ACL requests
  • subpanel: Used in subpanel action to provide a subpanel object describing the panel
  • massupdate: True if a save operation is a mass update

Admin Visibility and the Security Model

Admin permissions now work in the following manner:

  • Admin sections are subdivided by module, e.g., Users, Products, Administration, et al.
  • It is possible to discover specifics in two ways:
    • related module listed as module parameter in underlying URL
    • admin defs metadata file (identifies modules in the key for each entry)
  • If a user has developer/admin rights for any module, admin sections for that module will be accessible to them.
  • If the user has admin rights for any module, Studio and Workflow are accessible to them.
  • The Administration module itself is only accessible by the global admin.