|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | +# Copyright 2017 LasLabs Inc. |
| 3 | +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). |
| 4 | + |
| 5 | +import random |
| 6 | +import string |
| 7 | + |
| 8 | +from odoo import api, fields, models |
| 9 | + |
| 10 | + |
| 11 | +class WebHookToken(models.Model): |
| 12 | + """This represents a generic token for use in a secure web hook exchange. |
| 13 | +
|
| 14 | + It serves as an interface for token adapters. No logic should need to be |
| 15 | + added to this model in inherited modules. |
| 16 | + """ |
| 17 | + |
| 18 | + _name = 'web.hook.token' |
| 19 | + _description = 'Web Hook Token' |
| 20 | + |
| 21 | + hook_id = fields.Many2one( |
| 22 | + string='Hook', |
| 23 | + comodel_name='web.hook', |
| 24 | + required=True, |
| 25 | + ondelete='cascade', |
| 26 | + ) |
| 27 | + token = fields.Reference( |
| 28 | + selection='_get_token_types', |
| 29 | + readonly=True, |
| 30 | + help='This is the token used for hook authentication. It is ' |
| 31 | + 'created automatically upon creation of the web hook, and ' |
| 32 | + 'is also deleted with it.', |
| 33 | + ) |
| 34 | + token_type = fields.Selection( |
| 35 | + selection='_get_token_types', |
| 36 | + required=True, |
| 37 | + ) |
| 38 | + secret = fields.Char( |
| 39 | + help='This is the secret that is configured for the token exchange. ' |
| 40 | + 'This configuration is typically performed when setting the ' |
| 41 | + 'token up in the remote system. For ease, a secure random value ' |
| 42 | + 'has been provided as a default.', |
| 43 | + default=lambda s: s._default_secret(), |
| 44 | + ) |
| 45 | + |
| 46 | + @api.model |
| 47 | + def _get_token_types(self): |
| 48 | + """Return the web hook token interface models that are installed.""" |
| 49 | + adapter = self.env['web.hook.token.adapter'] |
| 50 | + return [ |
| 51 | + (m, self.env[m]._description) for m in adapter._inherit_children |
| 52 | + ] |
| 53 | + |
| 54 | + @api.model |
| 55 | + def _default_secret(self, length=254): |
| 56 | + characters = string.printable.split()[0] |
| 57 | + return ''.join( |
| 58 | + random.choice(characters) for _ in range(length) |
| 59 | + ) |
| 60 | + |
| 61 | + @api.multi |
| 62 | + def validate(self, token, data=None, data_string=None): |
| 63 | + """This method is used to validate a web hook. |
| 64 | +
|
| 65 | + It simply passes the received data to the underlying token's |
| 66 | + ``validate`` method for processing, and returns the result. |
| 67 | +
|
| 68 | + Args: |
| 69 | + token (mixed): The "secure" token string that should be validated |
| 70 | + against the dataset. Typically a string. |
| 71 | + data (dict, optional): Parsed data that was received with the |
| 72 | + request. |
| 73 | + data_string (str, optional): Raw form data that was received in |
| 74 | + the request. This is useful for computation of hashes, because |
| 75 | + Python dictionaries do not maintain sort order and thus are |
| 76 | + useless for crypto. |
| 77 | +
|
| 78 | + Returns: |
| 79 | + bool: If the token is valid or not. |
| 80 | + """ |
| 81 | + self.ensure_one() |
| 82 | + return self.token.validate(token, data, data_string) |
0 commit comments