Friday, 12 January 2018

Groups and Access rights in Odoo

The most significant area in Odoo/OpenERP is how to deal or manage users. Managing users and assigning groups or role is the key point in every business. In Odoo/OpenERP assigning role or group to the single user is made through Administrator. And its not a good practice to do so using login through admin and do some setting stuff like assigning groups to employee or users.

If you let users change their role (in dot NET applications) or groups (mostly used in ERP Systems) them selves, than you will no direct control over your system. You should have some policy to try to maintain a level of security.

Why we need role or groups?

The answer is you need to put everything significant to your business. As you have seen that their are couple of things in an ERP system which you don't want to show every user, most of your staff members needs to see only part of the given system. That's why we need groups or user role that will be assigned to each user. In Odoo/ERP the management of users is very flexible, and each user can belong to one or more groups.

To manage users and configure access rights you should start by defining the groups.

How to create / define groups

1- Open "security_group.xml" file under your "module_name" >> "security" folder/directory
2- If you do not have such file than create one in above mentioned folder.
To create groups use below code snippet in your XML file.

<openerp>
     <data>
 <record id="your_group_id_goes_here_1" model="res.groups">
            <field name="name">Your Group Name 1</field>
        </record>
        <record id="your_group_id_goes_here_2" model="res.groups">
            <field name="name">Your Group Name 2</field>
        </record>
     </data>
 </openerp>     
 

Now upgrade your module and login through admin to see your changes. If you have no errors than you will see your created groups in "Setting >> Groups" menu.


How to assign groups to users.

To assign groups login from admin and click on "Settings >> Users", here you will see user profile, Now click on Create button to create new record or existing record click on Edit, your created group exists on under "Other" section. To assign group to particular user check that group.



After assigning groups to individual users you may need to set access controls. Defining access control is what your users have right to do with your data. Remember access control belongs to your object. There are four type of Access Control List (ACL) in Odoo/ERP.
  1. Read access: members of the group can read the data in the object,
  2. Create access: members of the group can create a new record in the object,
  3. Write access: members of the group can modify the contents of records in the object,
  4. Delete access: members of the group can delete records from the object. 
"access_controll_list_id","title/name of your ACL","model_your_model_name_goes_here","module_name.group_name_goes_here",1,1,1,1       
 

In above code snippet append "model_" as a prefix to your model name. Here all one's mean we have assigning each right (read,write,create,delete) to mentioned group of users.

The main purpose of this article is to assigning groups at the time of employee or staff creation, because we don't want to give administrator rights to our users. For example we have a form from which we creates employee or faculty. After creating employees we need to login through administrator and than assign groups to created employee, that's not a good practice to assign groups that way. To overcome this issue we are going to override create and write method of  (employee,faculty) class. Before overriding these functions first we need to create a Many2many field in our employee or faculty/staff table.

res_group_id=fields.Many2many('res.groups','rel_faculty_group', string="Assign Group",required=True)       
 

The above code will create a Many2many field in our employee/faculty table. The relation of this field is with Odoo groups (res.groups) table. That's why all the groups shown in this field. If you want to show only your company groups than put a domain on that field.



Now that we have shown all the groups related to our business/company in employee/faculty form. Now its time to override create and write method to handle these changes. Here the need for overriding is that on the time of creation of employee/faculty we want to add their groups in res.groups table. The logic for create method is very simple.

Override Create Method

 
        @api.model
 def create(self,values):
  is_active=values.get('is_active',False)
  if is_active:
   values['is_active']=True
  else:
   values['is_active']=True
  group_id=values.get('res_group_id',False)

  login=values.get('login',False)
  if login: 
   values['login']=login.lower()
   values['email'] = values['login']
   user = self.env['res.users'].search([('login','=',values['login'])])   
   if user:
    raise ValidationError('User already exist.')
   else:
    user = self.env['res.users'].create({'login':values['login'],'name':values['name'],'department_id':values['department_id']})
  employeeUser=super(employee_table, self).create(values)
  user.write({'faculty_id':employeeUser.id})

  if user:
   partner = self.env['res.partner'].search([('id','=',user.partner_id.id)])
   if partner:
    partner.write({'email':values['login']})

  # group logic
  if(group_id) and group_id[0][2]:
   g_list=[]
   for g in group_id:
    g_list=g[2]
   for g in g_list:
    self.env.cr.execute("""insert into res_groups_users_rel(gid,uid) values("""+str(g)+""","""+str(user.id)+""")""")
    self.env.cr.commit()
  return employeeUser      
 

Code Description
In above code snippet we have override create method of employee table. On the time of faculty/employee creation we also creating user (res.users) and partner (res.partner). After creating employee,user and partner now we are inserting data in "res_groups_users_rel" table to assign groups to newly created user.

Override Write Method
 
 @api.multi
 def write(self,values):

  def sync_lists(db_list, ui_list):  

   same_ui_list=[l for l in db_list if l in ui_list]
   remove_ui_list=[l for l in db_list if l not in ui_list]
   new_ui_list=[l for l in ui_list if l not in db_list]
   if new_ui_list != []:
    result=set(new_ui_list)
   else:
    result=set(same_ui_list)-set(remove_ui_list)
   return result, remove_ui_list


  faculty_user= self.env['res.users'].search([('faculty_id','=',self.id)])  
   partner = self.env['res.partner'].search([('id','=',faculty_user.partner_id.id)])
  group_id=values.get('res_group_id',False)
  is_active=values.get('is_active')
  login=values.get('login',False)
  if login: 
   values['login']=login.lower()
   values['email'] = values['login']
   partner.write({'email':values['login']})


  # Below code is for add/delete groups in employee form -->Start
  if(group_id) and group_id[0][2]:
   ui_list=group_id[0][2]

   db_list=[]
   self.env.cr.execute("""select gid from res_groups_users_rel where uid = """+str(faculty_user.id))
   db_list = group_list = self.env.cr.fetchall()
   if group_list:
    group_list =[x[0] for x in group_list]
   temp_group=self.env['res.groups'].search([('id','in',group_list), ('is_lms_group','=',True)])  
   if temp_group:
    db_list =temp_group.ids
    group_list=temp_group.ids 
   
   result, remove_ui_list=sync_lists(group_list,ui_list)
   for each in result:
    if each in db_list:
     pass
    else:
     self.env.cr.execute("""insert into res_groups_users_rel(gid,uid) values("""+str(each)+""","""+str(faculty_user.id)+""")""")
     self.env.cr.commit()
   for each in remove_ui_list:
    self.env.cr.execute("""delete from res_groups_users_rel where uid="""+str(faculty_user.id)+ """ and gid = """ + str(each))
    self.env.cr.commit()
  # Above code is for add/delete groups in employee form -->End

  if is_active:
   self.env.cr.execute("""select id from res_users where faculty_id = """+str(self.id))
   uid=self.env.cr.fetchone()
   if uid:
    self.env.cr.execute("""update res_users set active=True where id = """+str(uid[0]))
    self.env.cr.commit()
   if self.res_group_id:
    for g in self.res_group_id.ids:
     self.env.cr.execute("""insert into res_groups_users_rel(gid,uid) values("""+str(g)+""","""+str(faculty_user.id)+""")""")
     self.env.cr.commit()
  elif is_active == False:
   faculty_user.write({'active':False})
  result= super(faculty, self).write(values)
  return result        
 

Code Description
Above code is the write method of employee table/model. In this method we have a function named "sync_lists". This function takes two parameter the first one is "db_list" and the second is "ui_list". Here "db_list" is the list of groups ids that a employee/faculty has assigned, and "ui_list" is the selected group which we have selected in employee form from (Many2many) field.


The idea behind the function is we are checking here the group ids from database and user interface. Below three line are the key point here.

 same_ui_list=[l for l in db_list if l in ui_list]
 remove_ui_list=[l for l in db_list if l not in ui_list]
 new_ui_list=[l for l in ui_list if l not in db_list]      
 

  • In line no 1 we are creating a list of group ids which are exists on database as well user interface or form in simple words in our (Many2many) field. This list shows no change in record.

  • In line no 2 we are creating a list of group ids which are exists on database but removed from user interface or Odoo form. Its mean we have deleted some records from Many2many field.

  • In line no 3 we are creating a list of group ids which are not in database but in form view or in Many2many field. This mean we are adding some group.

And at the end we are creating a final list which takes the ids of res.group record.

  # Below code is for add/delete groups in employee form -->Start
  if(group_id) and group_id[0][2]:
   ui_list=group_id[0][2]

   db_list=[]
   self.env.cr.execute("""select gid from res_groups_users_rel where uid = """+str(faculty_user.id))
   db_list = group_list = self.env.cr.fetchall()
   if group_list:
    group_list =[x[0] for x in group_list]
   temp_group=self.env['res.groups'].search([('id','in',group_list), ('is_lms_group','=',True)])  
   if temp_group:
    db_list =temp_group.ids
    group_list=temp_group.ids 
   
   result, remove_ui_list=sync_lists(group_list,ui_list)
   for each in result:
    if each in db_list:
     pass
    else:
     self.env.cr.execute("""insert into res_groups_users_rel(gid,uid) values("""+str(each)+""","""+str(faculty_user.id)+""")""")
     self.env.cr.commit()
   for each in remove_ui_list:
    self.env.cr.execute("""delete from res_groups_users_rel where uid="""+str(faculty_user.id)+ """ and gid = """ + str(each))
    self.env.cr.commit()
  # Above code is for add/delete groups in employee form -->End       
 

In above code we are just inserting or deleting record from relational table "res_groups_users_rel" on the basis of our function which we have already discussed.

No comments:

Post a Comment