osiell / oerplib

OERPLib is a Python RPC library which aims to provide an easy way to remotely pilot and manage an OpenERP server.
GNU Lesser General Public License v3.0
21 stars 20 forks source link

Configure user privileges #11

Open dbareiro opened 9 years ago

dbareiro commented 9 years ago

Hi, Sébastien/etsinko.

After being able to automate the creation of a database with the corresponding administrator, I wonder if it is possible to configure access to "technical features" also automatically after creation (I think this is basic to an administrator user), using oerplib. I think the res_groups table is used for set the privileges, although I didn't see the relation with res_users.

I was also investigating how to create an administrator user with restricted permissions (eg he/her can not install modules). At first I tried it from the web interface for viewing the mechanism to follow and try to replicate it with oerplib, but I could not get it yet. The official documentation on the Odoo official site also was not very useful for me. This is also achieved by configuring the user group?

Thanks again for your time.

Kind regards, Daniel

sebalix commented 9 years ago

Hi,

It is possible of course. First thing to know is that any database record can be created in two way: manually by a user (through the interface or OERPLib), or automatically when installing a module. Almost all basic data you will find after the creation of a new database have been created automatically with the installation of a module. These records are declared in XML files (often with tags <record id="..." [...]>[...]</record>), and this is the case of the Technical Features group, which is part of the base module.

The important point here is the id=... attribute in such records, this is what we call the external ID or also XML ID. This external ID is very helpful to identify and retrieve a specific record from the Odoo database, because it does not rely on the database ID (given by PostgreSQL) which can be different from one database to another.

So, you have to know the external ID of this Technical Features group, and from there you will be able to set it on any user accounts you want with OERPLib:

Now you have the external ID, you can get the corresponding database ID on the fly, and use it the way you want:

>>> oerp.get('ir.model.data').get_object_reference('base', 'group_no_one')
['res.groups', 8]

ir.model.data is a data model responsible of the mapping between the external IDs and the database IDs, and get_object_reference() is one of its method helping to find information. Here we can see that the base.group_no_one external ID corresponds to the ID 8 of the res.groups data model. Now it is easy to do what you want:

>>> data_model = oerp.get('ir.model.data')
>>> user_model = oerp.get('res.users')
>>> res_model, res_id = data_model.get_object_reference('base', 'group_no_one')
>>> user = user_model.browse(1)    # User account to update
>>> user.groups_id += res_id       # We add the 'Technical Features' group to the user
>>> oerp.write_record(user)        # Save modifications

The groups_id field is a many2many between res.users and res.groups data models, you can see it in any user form with the Odoo developer mode activated.

Regards,

dbareiro commented 9 years ago

Hi, Sébastien.

As always, I thank you for your time and good will.

Before opening this issue I had researched the use of the Developer Mode, as you've suggested before and I found it very interesting. Without to have a theoretical basis as theoretical as you gave me (thanks for that!), I had observed that in Users -> Administrator, with Developer Mode enabled, when positioned the mouse over Technical Features, I found the following:

Field: in_group_8
Object: res.users
Type: boolean

Then, making a dump of the database I found where this value was, although mine was somewhat rustic. I was losing the theoretical base.

INSERT INTO ir_ui_view (id, create_date, write_uid, write_date, active, arch, field_parent, inherit_id, name, model_data_id, priority, mode, model, type, create_uid) VALUES (156, '2014-12-16 23:19:04.318361', 1, '2014-12-16 23:19:04.318361', true, '<?xml version=''1.0'' encoding=''utf-8''?>
<field position="replace" name="groups_id">
  <separator colspan="4" string="Application"/>
  <field name="sel_groups_7" groups="base.group_no_one"/>
  <newline/>
  <field name="sel_groups_9_10"/>
  <newline/>
  <field name="sel_groups_5"/>
  <newline/>
  <field name="sel_groups_3_4"/>
  <newline/>
  <separator colspan="4" string="Usability"/>
  <field name="in_group_6"/>
  <field name="in_group_8"/>
  <separator colspan="4" string="Other"/>
  <field name="in_group_11"/>
  <field name="in_group_1"/>
  <field name="in_group_2"/>
</field>
', NULL, 153, 'res.users.groups', 2441, 16, 'extension', 'res.users', 'form', 1);

I was testing the code in your example (thanks for the comments), but I get the following error which apparently happens in the line:

res_model, res_id = data_model.get_object_reference('base', 'group_no_one')

The exception produced is the following:

python

./create_odoo_databaseV3.py opcionlibre 0 es_AR 95678

Traceback (most recent call last): File "./create_odoo_databaseV3.py", line 50, in res_model, res_id = data_model.get_object_reference('base', 'group_no_one') File "/usr/local/lib/python2.7/dist-packages/oerplib/service/osv/osv.py", line 244, in rpc_method self._browse_class.osv['name'], method, args, kwargs) File "/usr/local/lib/python2.7/dist-packages/oerplib/oerp.py", line 277, in execute_kw raise error.RPCError(exc.message, exc.oerp_traceback) oerplib.error.RPCError: 1


Perhaps the Odoo log can help us more:

2014-12-29 21:53:24,421 24017 ERROR opcionlibre openerp.http: get_object_reference() got an unexpected keyword argument 'context' Traceback (most recent call last): File "/opt/odoo/odoo-server/openerp/http.py", line 108, in dispatch_rpc result = dispatch(method, params) File "/opt/odoo/odoo-server/openerp/service/model.py", line 37, in dispatch res = fn(db, uid, params) File "/opt/odoo/odoo-server/openerp/service/model.py", line 162, in execute_kw return execute(db, uid, obj, method, args, kw or {}) File "/opt/odoo/odoo-server/openerp/service/model.py", line 113, in wrapper return f(dbname, *args, *kwargs) File "/opt/odoo/odoo-server/openerp/service/model.py", line 170, in execute res = execute_cr(cr, uid, obj, method, args, kw) File "/opt/odoo/odoo-server/openerp/service/model.py", line 159, in execute_cr return getattr(object, method)(cr, uid, *args, *kw) File "/opt/odoo/odoo-server/openerp/api.py", line 237, in wrapper return old_api(self, args, **kwargs) TypeError: get_object_reference() got an unexpected keyword argument 'context'



There seems to be an incorrect argument in the call. It can be?

Thanks again.

Best regards,
Daniel
sebalix commented 9 years ago

Indeed, most RPC methods accept a context argument (containing the user's lang, its timezone, and other contextual metadata, needed to process requests properly like translations), but some of them don't. By default OERPLib send the context argument (the user does not have to care about it), but an error is raised when using some RPC method which does not accept it. You can just disable this behaviour for such methods:

>>> oerp.config['auto_context'] = False
>>> res_model, res_id = data_model.get_object_reference('base', 'group_no_one')
>>> oerp.config['auto_context'] = True

See: http://pythonhosted.org//OERPLib/faq.html#some-osv-methods-does-not-accept-the-context-parameter

Regards,

dbareiro commented 9 years ago

Hi, Sébastien.

Great! Thanks for the reference on the documentation!

Regarding the second point that I had commented in the original message:

I was also investigating how to create an administrator user with restricted permissions 
(eg he/her can not install modules). At first I tried it from the web interface for viewing 
the mechanism to follow and try to replicate it with oerplib, but I could not get it yet. 
The official documentation on the Odoo official site also was not very useful for me. 
This is also achieved by configuring the user group?

In Lauchpad I found the following code that you had commented to create a user:

oerp.login('admin', 'password', 'opcionlibre')

user_obj = oerp.get('res.users')
user_obj.create({'name':'Wolfgang Boehmer', 'login':'wolfgangb', 'password':'password2'})

I guess the goal would be to have the technical features enabled but without the Modules menu (correct me if I'm wrong, please). Although I'm still new at in this matter of privilege settings and I am investigating how do it. Any help is welcome.

I was also thinking if it is possible that the "subadmin" user has permissions to install only a subset of the available modules, although this is something (let's say) more ambitious.

Best regards, Daniel

sebalix commented 9 years ago

Sorry for the delay, time is a scarce resource ;) Your goal implies several things, it is not "simple".

Merge all of this, and you will be able to do what you want.