示例#1
0
 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
示例#2
0
    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'