def _get_visitor_from_request(self): if not request: return None visitor = self.env['website.visitor'] cookie_content = request.httprequest.cookies.get('visitor_id') if cookie_content and '-' in cookie_content: visitor_id, visitor_hash = cookie_content.split('-', 1) if _consteq(visitor_hash, self._get_visitor_hash(visitor_id)): return visitor.sudo().with_context(active_test=False).search([('id', '=', visitor_id)]) # search to avoid having to call exists() return visitor
def payload(self, payload, token): """ Webhook from Github: this is the server endpoint that will receive the webhook payload. """ db_secret = request.env['ir.config_parameter'].sudo().get_param( 'database.secret') db_uuid = request.env['ir.config_parameter'].sudo().get_param( 'database.uuid') computed_token = github_tokenize(db_secret, db_uuid) if not _consteq(str(token), str(computed_token)): return request.not_found() headers = request.httprequest.headers headers_data = { 'event_type': headers.get('X-GitHub-Event'), 'signature': headers.get('X-Hub-Signature'), 'delivery_id': headers.get('X-GitHub-Delivery') } payload_data = json.loads(payload) formated_payload = self._parse_github_payload(headers_data, payload_data) # Do nothing if the initial payload is not implemented if not formated_payload.get('payload'): return 'NO' # Do nothing when testing Webhook with a simple ping if headers_data.get('event_type') == 'ping': return 'TEST OK' # Get target repository repository_name = formated_payload['repository']['full_name'] repository_github_id = formated_payload['repository']['github_id'] repository_target = request.env['mail.channel.github'].sudo().search([ '|', ("name", "=", repository_name), ('github_repository_id', '=', repository_github_id) ]) # Check the signature of the incoming callback # Github apparently computes the body as URL-Escaped string (sweet !!) raw_body = "payload=" + urls.url_quote_plus( request.httprequest.form['payload'].encode("UTF-8")) if headers_data.get('signature'): repo_sign = "sha1=" + github_tokenize(repository_target.secret, raw_body) if not _consteq(repo_sign, str(headers_data.get('signature'))): _logger.info( "Gihbub webhook callback recieved request with invalid signature. (GH delivery_id = %s)", headers_data.get('delivery_id')) return False # Create or update target repository if not repository_target: repository_target = request.env['mail.channel.github'].sudo( ).create({ 'name': repository_name, 'github_repository_id': repository_github_id, }) if not repository_target.github_repository_id: repository_target.write( {'github_repository_id': repository_github_id}) # Search the partner author, corresponding to the gihhub login of the payload sender partner = request.env['res.users'].sudo().search( [("github_login", "=", formated_payload['sender']['login'])], limit=1).partner_id partner_email = partner.email if not partner: partner = request.env.ref('mail_github.res_partner_githbub_bot') partner_email = formated_payload['sender']['login'] + '@github.com' # If no channel on target repo, then do nothing channel_ids = repository_target.channel_ids.filtered( lambda channel: channel.github_enabled) if not channel_ids: _logger.warning('No channel is listening the github repository %s', repository_name) return 'NO' # Post the message with the template template_values = dict(formated_payload) template_values['repository_id'] = repository_target template_values['partner_id'] = partner rendered_template = request.env.ref( 'mail_github.message_github_notification').render(template_values) channels = repository_target.channel_ids.filtered( lambda channel: channel.github_enabled) repository_target.message_post( body=rendered_template, subtype="mail.mt_comment", # correct? author_id=partner.id, email_from=partner_email, channel_ids=channels.ids) return 'OK'