diff --git a/__openerp__.py b/__openerp__.py index eeb618d63ccf933f4b2e3d3aad7984519a58990e_X19vcGVuZXJwX18ucHk=..151a4edd9121e28e4df3f9436e2647eaac919f71_X19vcGVuZXJwX18ucHk= 100644 --- a/__openerp__.py +++ b/__openerp__.py @@ -35,7 +35,8 @@ 'data': [ 'data/auth_saml.xml', + 'data/ir_config_parameter.xml', 'security/ir.model.access.csv', 'views/auth_saml.xml', @@ -38,7 +39,8 @@ 'security/ir.model.access.csv', 'views/auth_saml.xml', + 'views/base_settings.xml', 'views/res_users.xml', ], diff --git a/data/ir_config_parameter.xml b/data/ir_config_parameter.xml new file mode 100644 index 0000000000000000000000000000000000000000..151a4edd9121e28e4df3f9436e2647eaac919f71_ZGF0YS9pcl9jb25maWdfcGFyYW1ldGVyLnhtbA== --- /dev/null +++ b/data/ir_config_parameter.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data noupdate="1"> + + <!-- Add a setting; to be manipulated via "general settings". --> + + <record id="allow_saml_uid_and_internal_password" model="ir.config_parameter"> + <field name="key">auth_saml.allow_saml.uid_and_internal_password</field> + <field name="value">0</field> + </record> + + </data> +</openerp> diff --git a/documentation/index.rst b/documentation/index.rst index eeb618d63ccf933f4b2e3d3aad7984519a58990e_ZG9jdW1lbnRhdGlvbi9pbmRleC5yc3Q=..151a4edd9121e28e4df3f9436e2647eaac919f71_ZG9jdW1lbnRhdGlvbi9pbmRleC5yc3Q= 100644 --- a/documentation/index.rst +++ b/documentation/index.rst @@ -84,3 +84,5 @@ and make sure the URLs point where they should. Edit the file if necessary. Then save its content into the corresponding box in the openerp SAML2 Provider form. + +There are additional SAML-related settings in Configuration > General settings. diff --git a/model/__init__.py b/model/__init__.py index eeb618d63ccf933f4b2e3d3aad7984519a58990e_bW9kZWwvX19pbml0X18ucHk=..151a4edd9121e28e4df3f9436e2647eaac919f71_bW9kZWwvX19pbml0X18ucHk= 100644 --- a/model/__init__.py +++ b/model/__init__.py @@ -1,5 +1,6 @@ # flake8: noqa import auth_saml +import base_settings import res_users import saml_token diff --git a/model/base_settings.py b/model/base_settings.py new file mode 100644 index 0000000000000000000000000000000000000000..151a4edd9121e28e4df3f9436e2647eaac919f71_bW9kZWwvYmFzZV9zZXR0aW5ncy5weQ== --- /dev/null +++ b/model/base_settings.py @@ -0,0 +1,98 @@ +from openerp import SUPERUSER_ID +from openerp.osv import fields +from openerp.osv import orm + + +_SAML_UID_AND_PASS_SETTING = 'auth_saml.allow_saml.uid_and_internal_password' + + +class base_settings(orm.TransientModel): + """Inherit from base.config.settings to add a setting. This is only here + for easier access; the setting is not actually stored by this (transient) + collection. Instead, it is kept in sync with the + "auth_saml.allow_saml.uid_and_internal_password" global setting. See + comments in the definition of the "res.config.settings" collection for + details. + """ + + _inherit = 'base.config.settings' + + _columns = { + 'allow_saml_uid_and_internal_password': fields.boolean( + ( + 'Allow SAML users to posess an Odoo password (warning: ' + 'decreases security)' + ), + ), + } + + def allow_saml_uid_and_internal_password(self, cr, context=None): + """Read the allow_saml_uid_and_internal_password setting. + Use the admin account to bypass security restrictions. + """ + + uid = SUPERUSER_ID + + config_obj = self.pool['ir.config_parameter'] + + config_ids = config_obj.search( + cr, uid, + [('key', '=', _SAML_UID_AND_PASS_SETTING)], + limit=1, + context=context + ) + if not config_ids: + return False + + config = config_obj.browse( + cr, uid, config_ids, context=context + )[0] + return (True if config.value == '1' else False) + + def get_default_allow_saml_uid_and_internal_password( + self, cr, uid, fields, context=None + ): + """Read the allow_saml_uid_and_internal_password setting. This function + is called when the form is shown. + """ + + ret = {} + + if 'allow_saml_uid_and_internal_password' in fields: + ret['allow_saml_uid_and_internal_password'] = ( + self.allow_saml_uid_and_internal_password(cr, context) + ) + + return ret + + def set_allow_saml_uid_and_internal_password( + self, cr, uid, ids, context=None + ): + """Update the allow_saml_uid_and_internal_password setting. This + function is called when saving the form. + """ + + dlg = self.browse(cr, uid, ids, context=context)[0] + + setting_value = ( + '1' if dlg.allow_saml_uid_and_internal_password else '0' + ) + + config_obj = self.pool['ir.config_parameter'] + config_ids = config_obj.search( + cr, uid, + [('key', '=', _SAML_UID_AND_PASS_SETTING)], + limit=1, + context=context + ) + if config_ids: + config_obj.write( + cr, uid, config_ids, {'value': setting_value}, context=context + ) + else: + # The setting doesn't exist; create it. + config_obj.create( + cr, uid, + {'key': _SAML_UID_AND_PASS_SETTING, 'value': setting_value}, + context=context + ) diff --git a/model/res_users.py b/model/res_users.py index eeb618d63ccf933f4b2e3d3aad7984519a58990e_bW9kZWwvcmVzX3VzZXJzLnB5..151a4edd9121e28e4df3f9436e2647eaac919f71_bW9kZWwvcmVzX3VzZXJzLnB5 100644 --- a/model/res_users.py +++ b/model/res_users.py @@ -28,6 +28,10 @@ password. """ + if self._allow_saml_uid_and_internal_password(cr, context): + # The constraint is a no-op in this case. + return True + users = self.browse(cr, uid, ids, context=context) for user in users: if user.password and user.saml_uid: @@ -201,8 +205,9 @@ """ if vals and vals.get('saml_uid'): - vals['password'] = False + if not self._allow_saml_uid_and_internal_password(cr, context): + vals['password'] = False return super(res_users, self).write( cr, uid, ids, vals, context=context ) @@ -205,4 +210,10 @@ return super(res_users, self).write( cr, uid, ids, vals, context=context ) + + def _allow_saml_uid_and_internal_password(self, cr, context): + setting_obj = self.pool['base.config.settings'] + return setting_obj.allow_saml_uid_and_internal_password( + cr, context=context + ) diff --git a/views/base_settings.xml b/views/base_settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..151a4edd9121e28e4df3f9436e2647eaac919f71_dmlld3MvYmFzZV9zZXR0aW5ncy54bWw= --- /dev/null +++ b/views/base_settings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + + <!-- Inherit from the configuration form to add a setting. --> + + <record id="auth_saml_base_settings_form" model="ir.ui.view"> + <field name="name">auth_saml_base_settings_form</field> + <field name="model">base.config.settings</field> + <field name="inherit_id" ref="base_setup.view_general_configuration" /> + <field name="arch" type="xml"> + + <xpath expr="//field[@name='module_auth_oauth']/.." + position="after"> + <div> + <field name="allow_saml_uid_and_internal_password" + class="oe_inline" /> + <label for="allow_saml_uid_and_internal_password" /> + </div> + </xpath> + + </field> + </record> + + </data> +</openerp>