89 lines
3.7 KiB
Python
89 lines
3.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
import json
|
|
import logging as logger
|
|
|
|
from odoo import api, fields, models
|
|
from ..tools.jwt import generate_vapid_keys
|
|
|
|
_logger = logger.getLogger(__name__)
|
|
|
|
|
|
class InvalidVapidError(Exception):
|
|
pass
|
|
|
|
|
|
class PartnerDevice(models.Model):
|
|
_name = 'mail.partner.device'
|
|
_description = 'Partner Web Push Device'
|
|
|
|
partner_id = fields.Many2one('res.partner', string='Partner', index=True, required=True,
|
|
default=lambda self: self.env.user.partner_id)
|
|
endpoint = fields.Char(string='Browser endpoint', required=True)
|
|
keys = fields.Char(string='Browser keys', required=True,
|
|
help=("It's refer to browser keys used by the notification: \n"
|
|
"- p256dh: It's the subscription public key generated by the browser. The browser will \n"
|
|
" keep the private key secret and use it for decrypting the payload\n"
|
|
"- auth: The auth value should be treated as a secret and not shared outside of Odoo"))
|
|
expiration_time = fields.Datetime(string='Expiration Token Date')
|
|
|
|
_sql_constraints = [('endpoint_unique', 'unique(endpoint)', 'The endpoint must be unique !')]
|
|
|
|
@api.model
|
|
def get_web_push_vapid_public_key(self):
|
|
ir_params_sudo = self.env['ir.config_parameter'].sudo()
|
|
public_key = 'mail.web_push_vapid_public_key'
|
|
public_key_value = ir_params_sudo.get_param(public_key)
|
|
# Regenerate new Keys if public key not present
|
|
if not public_key_value:
|
|
self.sudo().search([]).unlink() # Reset all devices (ServiceWorker)
|
|
private_key_value, public_key_value = generate_vapid_keys()
|
|
ir_params_sudo.set_param('mail.web_push_vapid_private_key', private_key_value)
|
|
ir_params_sudo.set_param(public_key, public_key_value)
|
|
_logger.info("WebPush: missing public key, new VAPID keys generated")
|
|
return public_key_value
|
|
|
|
@api.model
|
|
def register_devices(self, **kw):
|
|
sw_vapid_public_key = kw.get('vapid_public_key')
|
|
valid_sub = self._verify_vapid_public_key(sw_vapid_public_key)
|
|
if not valid_sub:
|
|
raise InvalidVapidError("Invalid VAPID public key")
|
|
endpoint = kw.get('endpoint')
|
|
browser_keys = kw.get('keys')
|
|
if not endpoint or not browser_keys:
|
|
return
|
|
search_endpoint = kw.get('previousEndpoint', endpoint)
|
|
user_device = self.sudo().search([('endpoint', '=', search_endpoint)])
|
|
if user_device:
|
|
if user_device.partner_id is not self.env.user.partner_id:
|
|
user_device.write({
|
|
'endpoint': endpoint,
|
|
'expiration_time': kw.get('expirationTime'),
|
|
'keys': json.dumps(browser_keys),
|
|
'partner_id': self.env.user.partner_id,
|
|
})
|
|
else:
|
|
self.sudo().create([{
|
|
'endpoint': endpoint,
|
|
'expiration_time': kw.get('expirationTime'),
|
|
'keys': json.dumps(browser_keys),
|
|
'partner_id': self.env.user.partner_id.id,
|
|
}])
|
|
|
|
@api.model
|
|
def unregister_devices(self, **kw):
|
|
endpoint = kw.get('endpoint')
|
|
if not endpoint:
|
|
return
|
|
user_device = self.sudo().search([
|
|
('endpoint', '=', endpoint)
|
|
])
|
|
if user_device:
|
|
user_device.unlink()
|
|
|
|
def _verify_vapid_public_key(self, sw_public_key):
|
|
ir_params_sudo = self.env['ir.config_parameter'].sudo()
|
|
db_public_key = ir_params_sudo.get_param('mail.web_push_vapid_public_key')
|
|
return db_public_key == sw_public_key
|