[IMP] mail_broker: Set webhook

pull/1305/head
Enric Tobella 2021-12-16 18:33:56 +01:00 committed by Enric Tobella
parent 1e5b8ad89c
commit fc541ba6bd
9 changed files with 196 additions and 14 deletions

View File

@ -1 +0,0 @@
from . import main

View File

@ -0,0 +1,2 @@
from . import main
from . import bot_controller

View File

@ -0,0 +1,41 @@
import logging
from odoo import http
import json
_logger = logging.getLogger(__name__)
class BrokerController(http.Controller):
@http.route(
"/broker/<string:bot_key>/update",
type="json",
auth="none",
method=["POST"],
csrf=False,
)
def post_bot_updates(self, bot_key, **kwargs):
print(kwargs)
json_request = http.request.jsonrequest
bot_id = http.request.env["mail.broker"]._get_broker_id(bot_key, **kwargs)
if not bot_id:
return {}
broker = http.request.env["mail.broker"].browse(bot_id)
broker.with_user(broker.webhook_user_id.id).with_context(
notify_broker=True
)._receive_update(json_request)
return {}
@http.route(
"/braaoker/<string:bot_key>/update",
type="http",
auth="none",
method=["GET"],
csrf=False,
)
def get_baaot_updates(self, bot_key, **kwargs):
# This might be used for verification
print(kwargs)
bot_id = http.request.env["mail.broker"]._get_broker_id(bot_key, **kwargs)
if not bot_id:
return ""
return http.request.env["mail.broker"].browse(bot_id)._verify_bot(**kwargs)

View File

@ -1,7 +1,7 @@
# Copyright 2020 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
from odoo import api, fields, models, tools
class MailBroker(models.Model):
@ -10,16 +10,68 @@ class MailBroker(models.Model):
name = fields.Char(required=True)
token = fields.Char(required=True)
_sql_constraints = [
("mail_broker_token", "unique(token)", "Token must be unique"),
]
broker_type = fields.Selection([], required=True)
show_on_app = fields.Boolean(default=True)
webhook_url = fields.Char()
webhook_key = fields.Char()
integrated_webhook = fields.Boolean(readonly=True)
can_set_webhook = fields.Boolean(compute="_compute_webhook_checks")
webhook_url = fields.Char(compute="_compute_webhook_url")
has_new_channel_security = fields.Boolean(
help="When checked, channels are not created automatically"
)
webhook_user_id = fields.Many2one(
"res.users", default=lambda self: self.env.user.id
)
_sql_constraints = [
("mail_broker_token", "unique(token)", "Token must be unique"),
(
"mail_broker_webhook_key",
"unique(webhook_key)",
"Webhook Key must be unique",
),
]
@api.depends("webhook_key")
def _compute_webhook_url(self):
for record in self:
record.webhook_url = record._get_webhook_url()
def _get_webhook_url(self):
return "%s/broker/%s/update" % (
self.webhook_url
or self.env["ir.config_parameter"].get_param("web.base.url"),
self.webhook_key,
)
def _can_set_webhook(self):
return self.webhook_key and self.webhook_user_id
@api.depends("broker_type")
def _compute_webhook_checks(self):
for record in self:
record.can_set_webhook = record._can_set_webhook()
def set_webhook(self):
self.ensure_one()
if self.can_set_webhook:
self._set_webhook()
def remove_webhook(self):
self.ensure_one()
self._remove_webhook()
def update_webhook(self):
self.ensure_one()
self.remove_webhook()
self.set_webhook()
def _set_webhook(self):
self.integrated_webhook = True
def _remove_webhook(self):
self.integrated_webhook = False
@api.model
def broker_fetch_slot(self):
result = []
@ -46,3 +98,65 @@ class MailBroker(models.Model):
if name:
domain += [("name", "ilike", "%" + name + "%")]
return self.env["mail.broker.channel"].search(domain).read(["name"])
def _receive_update(self, update):
return getattr(self, "_receive_update_%s" % self.broker_type)(update)
def write(self, vals):
res = super(MailBroker, self).write(vals)
if "webhook_key" in vals:
self.clear_caches()
return res
@api.model_create_single
def create(self, vals):
res = super(MailBroker, self).create(vals)
if "webhook_key" in vals:
self.clear_caches()
return res
@api.model
@tools.ormcache()
def _get_broker_map(self):
result = {}
for record in self.search([]):
result[record.webhook_key] = record.id
return result
@api.model
def _get_broker_id(self, key, **kwargs):
# We are using cache in order to avoid an exploit
if not key:
return False
return self._get_broker_map().get(key, False)
def _get_channel_id(self, chat_token):
return (
self.env["mail.broker.channel"]
.search(
[("token", "=", str(chat_token)), ("broker_id", "=", self.id)], limit=1
)
.id
)
def _get_channel(self, token, update, force_create=False):
chat_id = self._get_channel_id(token)
if chat_id:
return self.env["mail.broker.channel"].browse(chat_id)
if not force_create and self.has_new_channel_security:
return False
return self.env["mail.broker.channel"].create(
self._get_channel_vals(token, update)
)
def _get_channel_vals(self, token, update):
return {
"token": token,
"broker_id": self.id,
"show_on_app": self.show_on_app,
}
def _verify_bot(self, **kwargs):
self.ensure_one()
# TODO: PASS IT TO WHATSAPP
return kwargs.get("hub.challenge")

View File

@ -15,7 +15,9 @@ class MailMessage(models.Model):
store=True,
)
broker_unread = fields.Boolean(default=False)
broker_type = fields.Selection([("telegram", "Telegram")], required=True)
broker_type = fields.Selection(
selection=lambda r: r.env["mail.broker"]._fields["broker_type"].selection
)
broker_notification_ids = fields.One2many(
"mail.message.broker", inverse_name="mail_message_id"
)

View File

@ -51,7 +51,7 @@ class MailMessageBroker(models.Model):
@api.model_create_multi
def create(self, vals_list):
messages = super().create(vals_list)
if self.env.context.get("notify_broker", True):
if self.env.context.get("notify_broker", False):
notifications = []
for message in messages:
notifications.append(

View File

@ -9,17 +9,42 @@
<form>
<header />
<sheet>
<div class="oe_button_box" name="button_box" />
<div class="oe_button_box" name="button_box">
<button
type="object"
string="Integrate Webhook"
icon="fa-plug"
name="set_webhook"
attrs="{'invisible': ['|', ('can_set_webhook', '=', False), ('integrated_webhook', '=', True)]}"
/>
<button
type="object"
string="Update Webhook"
name="update_webhook"
icon="fa-refresh"
attrs="{'invisible': ['|', ('can_set_webhook', '=', False), ('integrated_webhook', '=', False)]}"
/>
<button
type="object"
string="Remove Webhook"
name="remove_webhook"
icon="fa-remove"
attrs="{'invisible': [('integrated_webhook', '=', False)]}"
/>
</div>
<field name="can_set_webhook" invisible="1" />
<field name="integrated_webhook" invisible="1" />
<group>
<field name="name" />
<field name="show_on_app" />
<field name="token" />
<field name="broker_type" />
<field name="webhook_url" />
<field name="webhook_url" groups="base.group_no_one" />
<field name="webhook_key" />
<field name="webhook_user_id" />
<field name="has_new_channel_security" />
</group>
</sheet>
<div class="oe_chatter" />
</form>
</field>
</record>

View File

@ -31,7 +31,6 @@
<field name="show_on_app" />
<field name="token" />
</field>
<xpath expr="//div[@name='button_box']" position="inside" />
</field>
</record>
<record model="ir.ui.view" id="mail_broker_channel_search_view">
@ -53,14 +52,14 @@
</field>
</record>
<record model="ir.actions.act_window" id="mail_broker_channel_act_window">
<field name="name">Mail Broken Channel</field>
<field name="name">Mail Broker Channel</field>
<field name="res_model">mail.broker.channel</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
<record model="ir.ui.menu" id="mail_broker_channel_menu">
<field name="name">Mail Broken Channel</field>
<field name="name">Mail Broker Channel</field>
<field name="parent_id" ref="base.menu_email" />
<field name="action" ref="mail_broker_channel_act_window" />
<field name="sequence" eval="16" />