by eggsurplus

Control what your users can access and save time, money, and frustrations. Lock down sensitive data in SugarCRM or SuiteCRM to specific groups or teams. Supports unlimited assigned users, unlimited group assignments to records, custom layouts for each group, login/sudo capabilities and much more.

Free Trial

By clicking you consent to share your profile with the developer

#214 - Fatal Error on 6.5.13

Open Bug? created by markriggins 8 years ago

Fatal error, while displaying a Security Group's detail page, and trying to select an item from a custom module 'PDI_Dealerships' to belong to the security group.

Fatal error: Call to a member function addBean() on a non-object in /home2/mark/dev/www/PDI/data/Relationships/M2MRelationship.php on line 136 Call Stack: 0.0003 342048 1. {main}() /home2/mark/dev/www/PDI/index.php:0 0.1195 17301316 2. SugarApplication->execute() /home2/mark/dev/www/PDI/index.php:46 0.1551 20099388 3. SugarController->execute() /home2/mark/dev/www/PDI/include/MVC/SugarApplication.php:89 0.1551 20099388 4. SugarController->process() /home2/mark/dev/www/PDI/include/MVC/Controller/SugarController.php:289 0.1576 20473776 5. SugarController->handleActionMaps() /home2/mark/dev/www/PDI/include/MVC/Controller/SugarController.php:375 0.1579 20533620 6. require_once('/home2/mark/dev/www/PDI/include/generic/Save2.php') /home2/mark/dev/www/PDI/include/MVC/Controller/SugarController.php:897 0.1605 20778640 7. Link2->add() /home2/mark/dev/www/PDI/include/generic/Save2.php:197 0.1672 21227128 8. M2MRelationship->add() /home2/mark/dev/www/PDI/data/Link2.php:492

  1. eggsurplus member avatar

    eggsurplus Provider Affiliate

    8 years ago

    Hello Mark, hooking up custom modules takes a bit of work. If using the Premium version, which is for sale on this site, you use the Hookup admin tool found in the Security Suite admin panel on the Admin page. This creates the correct relationship (creating a relationship in Studio does not work for this). If using the free, basic version this needs to be hand coded. How to do this is in this pdf: http://www.sugarforge.org/frs/download.php/6477/SecuritySuite_Documentation_2.1.pdf. Make sure to not copy/paste that code as you may get some junk characters.

  2. markriggins member avatar

    markriggins

    8 years ago

    This doc tells how to manually create the relationships. I used your "Hookup Module" admin tool instead. Everything else seems to work. When I view the details of my custom module, I can select security groups for the record, and the mass update panel is there on the list view.

    But when I view the details of the security group itself, I cannot select any custom modules items for it.

    My MetaData.php file looks like this:

    pdi_dealerships_securitygroups_1MetaData.php <?php // created: 2013-08-24 11:07:10 $dictionary["pdi_dealerships_securitygroups_1"] = array ( 'true_relationship_type' => 'many-to-many', 'from_studio' => true, 'relationships' => array ( 'pdi_dealerships_securitygroups_1' => array ( 'lhs_module' => 'SecurityGroups', 'lhs_table' => 'securitygroups', 'lhs_key' => 'id', 'rhs_module' => 'PDI_Dealerships', 'rhs_table' => 'pdi_dealerships', 'rhs_key' => 'id', 'relationship_type' => 'many-to-many', 'join_table' => 'securitygroups_records', 'join_key_lhs' => 'securitygroup_id', 'join_key_rhs' => 'record_id', 'relationship_role_column' => 'module', 'relationship_role_column_value' => 'PDI_Dealerships', ), ), );

  3. markriggins member avatar

    markriggins

    8 years ago

    In the code below $rhs->$rhsLinkName is empty. Should there be a call to load_relationship first?

    Also, why does the code call addBean twice?

    public function add($lhs, $rhs, $additionalFields = array()) { $lhsLinkName = $this->lhsLink; $rhsLinkName = $this->rhsLink;

        /* BEGIN - SECURITY GROUPS */
        //Need to hijack this as security groups will not contain a link on the module side
        //due to the way the module works. Plus it would remove the relative ease of adding custom module support
    
        if(get_class($rhs) != &#039;User&#039; && get_class($rhs) != &#039;ACLRole&#039; && get_class($lhs) == &#039;SecurityGroup&#039;) {
            $rhs->$rhsLinkName->addBean($lhs);          
    
  4. markriggins member avatar

    markriggins

    8 years ago

    This appears to fix it:

        if(get_class($rhs) != &#039;User&#039; && get_class($rhs) != &#039;ACLRole&#039; && get_class($lhs) == &#039;SecurityGroup&#039;) {
          //MDR: bug fix
          $rhs->load_relationship($rhsLinkName);
            $rhs->$rhsLinkName->addBean($lhs);          
            $this->callBeforeAdd($rhs, $lhs, $rhsLinkName);
    
            $dataToInsert = $this->getRowToInsert($lhs, $rhs, $additionalFields);
            $this->addRow($dataToInsert);
            $rhs->$rhsLinkName->addBean($lhs);
            $this->callAfterAdd($lhs, $rhs, $lhsLinkName);
        } else if(get_class($lhs) != &#039;User&#039; && get_class($lhs) != &#039;ACLRole&#039; && get_class($rhs) == &#039;SecurityGroup&#039;) {
          //MDR: bug fix
          $lhs->load_relationship($lhsLinkName);
            $lhs->$lhsLinkName->addBean($rhs);          
            $this->callBeforeAdd($lhs, $rhs, $lhsLinkName);
    
            $dataToInsert = $this->getRowToInsert($lhs, $rhs, $additionalFields);
            $this->addRow($dataToInsert);
            $lhs->$lhsLinkName->addBean($rhs);
            $this->callAfterAdd($rhs, $lhs, $rhsLinkName);
        } else {
    
  5. markriggins member avatar

    markriggins

    8 years ago

    This might be refactored a bit better

        $lhsLinkName = $this->lhsLink;
        $rhsLinkName = $this->rhsLink;
    
        if (empty($lhs->$lhsLinkName) && !$lhs->load_relationship($lhsLinkName))
        {
            $lhsClass = get_class($lhs);
            $GLOBALS[&#039;log&#039;]->fatal("could not load LHS $lhsLinkName in $lhsClass");
            return false;
        }
        if (empty($rhs->$rhsLinkName) && !$rhs->load_relationship($rhsLinkName))
        {
            $rhsClass = get_class($rhs);
            $GLOBALS[&#039;log&#039;]->fatal("could not load RHS $rhsLinkName in $rhsClass");
            return false;
        }
    
        /* BEGIN - SECURITY GROUPS */
        //Need to hijack this as security groups will not contain a link on the module side
        //due to the way the module works. Plus it would remove the relative ease of adding custom module support
    
        if(get_class($rhs) != &#039;User&#039; && get_class($rhs) != &#039;ACLRole&#039; && get_class($lhs) == &#039;SecurityGroup&#039;) {
            $rhs->$rhsLinkName->addBean($lhs);          
            $this->callBeforeAdd($rhs, $lhs, $rhsLinkName);
    
            $dataToInsert = $this->getRowToInsert($lhs, $rhs, $additionalFields);
            $this->addRow($dataToInsert);
            $rhs->$rhsLinkName->addBean($lhs);
            $this->callAfterAdd($lhs, $rhs, $lhsLinkName);
        } else if(get_class($lhs) != &#039;User&#039; && get_class($lhs) != &#039;ACLRole&#039; && get_class($rhs) == &#039;SecurityGroup&#039;) {
            $lhs->$lhsLinkName->addBean($rhs);          
            $this->callBeforeAdd($lhs, $rhs, $lhsLinkName);
    
            $dataToInsert = $this->getRowToInsert($lhs, $rhs, $additionalFields);
            $this->addRow($dataToInsert);
            $lhs->$lhsLinkName->addBean($rhs);
            $this->callAfterAdd($rhs, $lhs, $rhsLinkName);
        } else {
        /* END - SECURITY GROUPS */
    
    
            $lhs->$lhsLinkName->addBean($rhs);
            $rhs->$rhsLinkName->addBean($lhs);
    
            $this->callBeforeAdd($lhs, $rhs, $lhsLinkName);
            $this->callBeforeAdd($rhs, $lhs, $rhsLinkName);
    
        //Many to many has no additional logic, so just add a new row to the table and notify the beans.
        $dataToInsert = $this->getRowToInsert($lhs, $rhs, $additionalFields);
    
        $this->addRow($dataToInsert);
    
        if ($this->self_referencing)
            $this->addSelfReferencing($lhs, $rhs, $additionalFields);
    
            $lhs->$lhsLinkName->addBean($rhs);
            $rhs->$rhsLinkName->addBean($lhs);
    
            $this->callAfterAdd($lhs, $rhs, $lhsLinkName);
            $this->callAfterAdd($rhs, $lhs, $rhsLinkName);
    
        /* BEGIN - SECURITY GROUPS */
        } //end normal 
        /* END - SECURITY GROUPS */
    
        return true;
    
  6. markriggins member avatar

    markriggins

    8 years ago

    Ok this buys me one free question:

    I understand Roles as ways to determine a users access rights to entire modules in mostly a subtractive way. If a user has 2 roles, then they get the most restrictive access to a given module.

    I understand Groups as a way to control access to individual objects.

    So a User U in Role R and in Groups G can access A an object in module M if both of these are true: 1) R grants access A on module M 2) the object in M belongs to one of the groups in G

    Is that right?

    Now I have no idea what it means to add a Role to a Group.

    Does it mean that every member of the Group is restricted to the role? What happens when we show the detail view of the User, and see his/her roles? Can we delete the role that was implicitly added via the group? Does the role even appear.

    Why can we add Roles to Groups? What function does it serve. Sorry to be thick but I just don't get it yet.

    • eggsurplus member avatar

      eggsurplus Provider Affiliate

      8 years ago

      By default in SugarCRM it gives restrictive rights. So that if a user is a member of multiple roles it gets the most restrictive. In SecuritySuite this can be turned on/off with the "Additive Rights" setting.

      To make administrating users easier you can add roles to a Security Group instead of to users. I like to use this approach and when I need to support a one-off scenario for a user I assign a role directly to the user instead. When it comes to determining rights, SecuritySuite will collect all roles either directly assigned to a user or assigned to a group that the user belongs to. It will then use either the most restrictive or permissive rights based on the "Additive Rights" setting.

      When you view a user you can view the access grid to see how those permissions have been inherited from all of the user's roles and group roles.

      For your initial question "So a User U in Role R and in Groups G can access A an object in module M if both of these are true", yes to both depending on the rights that the user has been given. If a user is given Group Only rights for a module action then the user can only perform that action if a group of the user is assigned to the record OR if the user is the "Assigned To" user. Order of rights: All, Group Only, Owner, None.

  7. markriggins member avatar

    markriggins

    8 years ago

    Very cool, so I can use groups to manage roles. This may come in very handy for us. We anticipate having lots of users in little fiefdoms. These fiefdoms have sub-fiefdoms in small hierarchies, but the top-level fiefdoms are orthogonal -- unrelated.

    This presents a problem for us -- I would like to delegate the administration of roles, groups and users to each top-level fiefdom. But unfortunately, when they try to select which users to add to their groups the selection list will be overwhelmed with users from other fiefdoms that they do not even know, and worse yet, may have similar names.

    Have you considered adding "Realms"?

    • eggsurplus member avatar

      eggsurplus Provider Affiliate

      8 years ago

      Haven't had that request before. I wonder if just getting Users to show on the role grid and then setting List to Group for the admins would be enough to filter the list to show just their users... Not sure off-hand what that would take to get the Users module to be configurable on the role grid. Even then, it wouldn't solve the issue necessarily because the users would have to be in the appropriate group first.

      Of course, another option is to just custom code the user view to show only those users from the same group.

    • markriggins member avatar

      markriggins

      8 years ago

      No that wouldn't solve my problem. I want to delegate the group admin abilities to the groups owner. That includes adding new members to the group.

      The problem is that the group owner should only be able to see users in his realm.

      In a perfect world, one realm should not be aware of the other realms at all.

      This would allow me to make one sugar instance look very much like a dozen completely independent instances. !!

This case is public. Please leave out any sensitive information such as URLs, passwords, etc.
Saving Comment Saving Comment...
Rating
Rating
  • "Very responsive development team, both in their communication and in having improvements incorporated and issues resolved." - kevin

    Read More Reviews