Dolibarr / dolibarr

Dolibarr ERP CRM is a modern software package to manage your company or foundation's activity (contacts, suppliers, invoices, orders, stocks, agenda, accounting, ...). it's an open source Web application (written in PHP) designed for businesses of any sizes, foundations and freelancers.
https://www.dolibarr.org
GNU General Public License v3.0
5.45k stars 2.79k forks source link

Bug: selectobject.php not returning anything for custom modules #23149

Open karozans opened 1 year ago

karozans commented 1 year ago

Bug

I created a custom module called Vehicles. Then created another new custom module and added a row to the new module that references Vehicles. Nothing gets returned when searching for the vehicle in the select box.

Environment Version

16.0.3

Environment OS

Mac OS 13.0

Environment Web server

Apache 2.4.46

Environment PHP

PHP 7.4.21

Environment Database

MySQL 5.7.34

Environment URL(s)

/core/ajax/selectobject.php

Expected and actual behavior

The selectobject.php code appears to hang at line 87 where it does a permissions check.

The check should pass and results should be returned.

Steps to reproduce the behavior

  1. Create a new module with fields. Module A.
  2. Create another new module with fields. Module B. And add a new field to Module B that references Module A.
  3. Add records to Module A.

In the new Module B, when you try to enter in a value into the select box to search for, the hour glass will only spin and no results are returned. The select box appears to use ajax to call /core/ajax/selectObject.php.

The ajax call to selectObject.php appears to hang up on line 87 where there is a call for restrictedArea().

If I comment out this line, the functionality works as expected. However, there is no security check.

In Module B, if you reference a Dolibarr built in object such as Societe or Contrat, the search box appears to work fine even with the security check. It appears to only fail when you have a new module that references another new custom module.

Attached files

No response

milenmk commented 1 year ago

Instead of 2 separate modules, work with objects. I.e. 2 objects in the same module. It's easier.

Also, in the class file:

Let's say you have an object "vehicle brand" and another object "model", and you want to link each model to a vehicle brand.

In the class file for the model, you should have a field for example fk_vehicle brand as follow:

public $fields=array( 'fk_vehicle' => array('type'=>'integer:Vehicle_brand:custom/yourmodulename/class/vehicle_brand.class.php', 'label'=>'FkVehicleBrand', 'enabled'=>'1', 'position'=>15, 'notnull'=>1, 'visible'=>-1,), );

Where "Vehicle_brand" is the class name for the vehicle brand object and "vehicle_brand.class.php" is the file containing this class. The same code can be used to link to another module, as you want. For example, to link a table field to a particular product, you can use:

public $fields=array( 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php:1', 'label'=>'Fkproduct', 'enabled'=>'1', 'position'=>25, 'notnull'=>0, 'visible'=>1,), );

With the above code, when you try to create a vehicle model, you will have a dropdown to select vehicle brand.

karozans commented 1 year ago

That might be a work around, but in my opinion, that should not be how Dolibarr works.

I can see no good reason why one custom module should not be able to reference another custom module, and that references only work with built-in modules.

Especially when there is no actual error message produced, but just a spinning icon.

milenmk commented 1 year ago

You can reference a custom module from another custom module. The code is the same. I was just suggesting using one module for brands and models if both are made by you.

karozans commented 1 year ago

No you can't. This is the bug. Did you try to replicate it?

See the attachments. It does not work with 2 custom modules. It only works when referencing a built-in module such as Societe. Screenshot 2022-12-07 at 9 09 47 AM Screenshot 2022-12-07 at 9 11 00 AM Screenshot 2022-12-07 at 9 11 26 AM Screenshot 2022-12-07 at 9 11 39 AM Screenshot 2022-12-07 at 9 27 05 AM Screenshot 2022-12-07 at 9 12 14 AM

karozans commented 1 year ago

Authentication error. Screenshot 2022-12-07 at 9 37 02 AM

milenmk commented 1 year ago

If $objecttmp is from module B, and you want to search in module A, you cannot have $form->selectForFormsLists($objecttmp.

You must initialize module A, like:

dol_include_once('/custom/modulA/path_to_class_file');
$moduleA = new ModuleA($db);
$form->selectForFormsLists($moduleA

Please make a post in the forum with more code examples.

karozans commented 1 year ago

I am not using any of the Form elements. I am totally relying on the pages that are automatically generated by the module builder. Below is the create action from claims_card.php. Screenshot 2022-12-07 at 10 12 05 AM

milenmk commented 1 year ago

Have you tried this code in your claims class file?

public $fields=array( 'fk_vehicle' => array('type'=>'integer:Vehicle_brand:custom/yourmodulename/class/vehicle_brand.class.php', 'label'=>'FkVehicleBrand', 'enabled'=>'1', 'position'=>15, 'notnull'=>1, 'visible'=>-1,), );

Can you attach this file here? Or at least the code before __constructmethod?

ivanmestre commented 1 year ago

Authentication error. Screenshot 2022-12-07 at 9 37 02 AM

The bug seems to be on the restrictedArea() method on security.lib.php:

When checking the user permissions it only uses the object element, and does not use the module.

In this case, I have a module with name riopretomodule, and an object with element shiftrecord. It should be checking for user->rights->riopretomodule->shiftrecord->read, but instead it is checking user->rights->shiftrecord->read, and returns the Authentication error

image

image

carmelchas commented 8 months ago

I am having a similar problem. I have a module with an object in it.

mymodule/class/myobject

I setup the rights for:

   $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used)
    $this->rights[$r][1] = 'Read MyObject objects of MyModule'; // Permission label
    $this->rights[$r][4] = 'myobject'; 
    $this->rights[$r][5] = 'read';
    $r++;

The right shows up in the user object as: user->rights->mymodule->myobject->read

However, the selectobject.php calls restrictedArea which only checks for "user->rights->myobject" which does not exist.

I am trying to leverage the feature MYOBJECT_USE_SEARCH_TO_SELECT instead of the combox box.

NOTE: When "selectobject.php" calls the "restrictedArea" function it does not provide any information about the object's module association. It only passes "restrictedArea($user, $objecttmp->element, $id);" ; It would be useful if it passed "$objecttmp" in as the third parameter so that the module for the object could be determined. Then code-logic could be modified with something like the following.

`
$found_rights = false; if ( !empty($user->rights->$feature->lire) ) $found_rights = true; if ( !empty($user->rights->$feature->read) ) $found_rights = true; if ( !empty($user->rights->$feature->run) ) $found_rights = true; if (is_object($object) && ! empty($object->module) ) { $objmod = $object->module; if ( ! empty($user->rights->$objmod) ) { if ( !empty($user->rights->$objmod->$feature->lire) ) $found_rights = true; if ( !empty($user->rights->$objmod->$feature->read) ) $found_rights = true; if ( !empty($user->rights->$objmod->$feature->run) ) $found_rights = true; } } if ( ! $found_rights ) { $readok = 0; $nbko++; }

`

carmelchas commented 8 months ago

I found a way around this problem with the permissions check failing while using Dolibarr v.18.

There is a hook for "restrictedArea" whereby you can "return 1" to bypass the permissions check in the situations where you desire.

custom/mymodule/class/actions_mymodule.class.php

function restrictedArea($parameters, &$object, &$action, $hookmanager) { global $conf, $db, $langs, $user; if ( ! empty($parameters['features']) && $parameters['features'] == 'myobject' ) { return 1; } }