You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
3.9 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2016 SYLEAM
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  4. import datetime
  5. import dateutil
  6. import time
  7. from collections import defaultdict
  8. from openerp import models, api, fields
  9. from openerp.tools.safe_eval import safe_eval
  10. class OAuthProviderScope(models.Model):
  11. _name = 'oauth.provider.scope'
  12. _description = 'OAuth Provider Scope'
  13. name = fields.Char(
  14. required=True, translate=True,
  15. help='Name of the scope, displayed to the user.')
  16. code = fields.Char(
  17. required=True, help='Code of the scope, used in OAuth requests.')
  18. description = fields.Text(
  19. required=True, translate=True,
  20. help='Description of the scope, displayed to the user.')
  21. model_id = fields.Many2one(
  22. comodel_name='ir.model', string='Model', required=True,
  23. help='Model allowed to be accessed by this scope.')
  24. model = fields.Char(
  25. related='model_id.model', string='Model Name', readonly=True,
  26. help='Name of the model allowed to be accessed by this scope.')
  27. filter_id = fields.Many2one(
  28. comodel_name='ir.filters', string='Filter',
  29. domain="[('model_id', '=', model)]",
  30. help='Filter applied to retrieve records allowed by this scope.')
  31. field_ids = fields.Many2many(
  32. comodel_name='ir.model.fields', string='Fields',
  33. domain="[('model_id', '=', model_id)]",
  34. help='Fields allowed by this scope.')
  35. _sql_constraints = [
  36. ('code_unique', 'UNIQUE (code)',
  37. 'The code of the scopes must be unique !'),
  38. ]
  39. @api.model
  40. def _get_ir_filter_eval_context(self):
  41. """ Returns the base eval context for ir.filter domains evaluation """
  42. return {
  43. 'datetime': datetime,
  44. 'dateutil': dateutil,
  45. 'time': time,
  46. 'uid': self.env.uid,
  47. 'user': self.env.user,
  48. }
  49. @api.multi
  50. def get_data_for_model(self, model, res_id=None, all_scopes_match=False):
  51. """ Return the data matching the scopes from the requested model """
  52. data = defaultdict(dict)
  53. eval_context = self._get_ir_filter_eval_context()
  54. all_scopes_records = self.env[model]
  55. for scope in self.filtered(lambda record: record.model == model):
  56. # Retrieve the scope's domain
  57. filter_domain = [(1, '=', 1)]
  58. if scope.filter_id:
  59. filter_domain = safe_eval(
  60. scope.filter_id.sudo().domain, eval_context)
  61. if res_id is not None:
  62. filter_domain.append(('id', '=', res_id))
  63. # Retrieve data of the matching records, depending on the scope's
  64. # fields
  65. records = self.env[model].search(filter_domain)
  66. for record_data in records.read(scope.field_ids.mapped('name')):
  67. for field, value in record_data.items():
  68. if isinstance(value, tuple):
  69. # Return only the name for a many2one
  70. data[record_data['id']][field] = value[1]
  71. else:
  72. data[record_data['id']][field] = value
  73. # Keep a list of records that match all scopes
  74. if not all_scopes_records:
  75. all_scopes_records = records
  76. else:
  77. all_scopes_records &= records
  78. # If all scopes are required to match, filter the results to keep only
  79. # those mathing all scopes
  80. if all_scopes_match:
  81. data = dict(filter(
  82. lambda record_data: record_data[0] in all_scopes_records.ids,
  83. data.items()))
  84. # If a single record was requested, return only data coming from this
  85. # record
  86. # Return an empty dictionnary if this record didn't recieve data to
  87. # return
  88. if res_id is not None:
  89. data = data.get(res_id, {})
  90. return data