Ejemplo n.º 1
0
 def _check_token(cls, token):
     base_link = request.httprequest.path
     params = dict(request.params)
     params.pop('token', '')
     valid_token = request.env['mail.thread']._generate_notification_token(
         base_link, params)
     return consteq(valid_token, str(token))
Ejemplo n.º 2
0
    def execute_callback(self):
        res = None
        for transaction in self:
            # limited sudo env, only for checking callback presence, not for running it!
            # manual transactions have no callback, and can pass without being run by admin user
            tx_sudo = transaction.sudo()
            if not (tx_sudo.callback_model_id and tx_sudo.callback_res_id
                    and tx_sudo.callback_method):
                continue

            valid_token = transaction._generate_callback_hash()
            if not consteq(ustr(valid_token), transaction.callback_hash):
                _logger.warning(
                    "Invalid callback signature for transaction %d" %
                    (transaction.id))
                continue

            record = self.env[transaction.callback_model_id.model].browse(
                transaction.callback_res_id).exists()
            if record:
                res = getattr(record, transaction.callback_method)(transaction)
            else:
                _logger.warning(
                    "Did not found record %s.%s for callback of transaction %d"
                    % (transaction.callback_model_id.model,
                       transaction.callback_res_id, transaction.id))
        return res
Ejemplo n.º 3
0
 def _invoice_check_access(self, invoice_id, access_token=None):
     invoice = request.env['account.invoice'].browse([invoice_id])
     invoice_sudo = invoice.sudo()
     try:
         invoice.check_access_rights('read')
         invoice.check_access_rule('read')
     except AccessError:
         if not access_token or not consteq(invoice_sudo.access_token, access_token):
             raise
     return invoice_sudo
Ejemplo n.º 4
0
 def _order_check_access(self, order_id, access_token=None):
     order = request.env['sale.order'].browse([order_id])
     order_sudo = order.sudo()
     try:
         order.check_access_rights('read')
         order.check_access_rule('read')
     except AccessError:
         if not access_token or not consteq(order_sudo.access_token,
                                            access_token):
             raise
     return order_sudo
Ejemplo n.º 5
0
 def _stock_picking_check_access(self, picking_id, access_token=None):
     picking = request.env['stock.picking'].browse([picking_id])
     picking_sudo = picking.sudo()
     try:
         picking.check_access_rights('read')
         picking.check_access_rule('read')
     except exceptions.AccessError:
         if not access_token or not consteq(
                 picking_sudo.sale_id.access_token, access_token):
             raise
     return picking_sudo
Ejemplo n.º 6
0
    def mailing(self, mailing_id, email=None, res_id=None, token="", **post):
        mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id)
        if mailing.exists():
            res_id = res_id and int(res_id)
            res_ids = []
            if mailing.mailing_model_name == 'mail.mass_mailing.list':
                contacts = request.env['mail.mass_mailing.contact'].sudo().search([
                    ('email', '=', email),
                    ('list_ids', 'in', [mailing_list.id for mailing_list in mailing.contact_list_ids])
                ])
                res_ids = contacts.ids
            else:
                res_ids = [res_id]

            right_token = mailing._unsubscribe_token(res_id, email)
            if not consteq(str(token), right_token):
                raise exceptions.AccessDenied()
            mailing.update_opt_out(email, res_ids, True)
            return _('You have been unsubscribed successfully')
Ejemplo n.º 7
0
def _has_token_access(res_model, res_id, token=''):
    record = request.env[res_model].browse(res_id).sudo()
    token_field = request.env[res_model]._mail_post_token_field
    return (token and record and consteq(record[token_field], token))
Ejemplo n.º 8
0
    def binary_content(cls, xmlid=None, model='ir.attachment', id=None, field='datas',
                       unique=False, filename=None, filename_field='datas_fname', download=False,
                       mimetype=None, default_mimetype='application/octet-stream',
                       access_token=None, env=None):
        """ Get file, attachment or downloadable content

        If the ``xmlid`` and ``id`` parameter is omitted, fetches the default value for the
        binary field (via ``default_get``), otherwise fetches the field for
        that precise record.

        :param str xmlid: xmlid of the record
        :param str model: name of the model to fetch the binary from
        :param int id: id of the record from which to fetch the binary
        :param str field: binary field
        :param bool unique: add a max-age for the cache control
        :param str filename: choose a filename
        :param str filename_field: if not create an filename with model-id-field
        :param bool download: apply headers to download the file
        :param str mimetype: mintype of the field (for headers)
        :param str default_mimetype: default mintype if no mintype found
        :param str access_token: optional token for unauthenticated access
                                 only available  for ir.attachment
        :param Environment env: by default use request.env
        :returns: (status, headers, content)
        """
        env = env or request.env
        # get object and content
        obj = None
        if xmlid:
            obj = env.ref(xmlid, False)
        elif id and model == 'ir.attachment' and access_token:
            obj = env[model].sudo().browse(int(id))
            if not consteq(obj.access_token, access_token):
                return (403, [], None)
        elif id and model in env.registry:
            obj = env[model].browse(int(id))

        # obj exists
        if not obj or not obj.exists() or field not in obj:
            return (404, [], None)

        # check read access
        try:
            last_update = obj['__last_update']
        except AccessError:
            return (403, [], None)

        status, headers, content = None, [], None

        # attachment by url check
        module_resource_path = None
        if model == 'ir.attachment' and obj.type == 'url' and obj.url:
            url_match = re.match("^/(\w+)/(.+)$", obj.url)
            if url_match:
                module = url_match.group(1)
                module_path = get_module_path(module)
                module_resource_path = get_resource_path(module, url_match.group(2))
                if module_path and module_resource_path:
                    module_path = os.path.join(os.path.normpath(module_path), '')  # join ensures the path ends with '/'
                    module_resource_path = os.path.normpath(module_resource_path)
                    if module_resource_path.startswith(module_path):
                        with open(module_resource_path, 'rb') as f:
                            content = base64.b64encode(f.read())
                        last_update = pycompat.text_type(os.path.getmtime(module_resource_path))

            if not module_resource_path:
                module_resource_path = obj.url

            if not content:
                status = 301
                content = module_resource_path
        else:
            content = obj[field] or ''

        # filename
        if not filename:
            if filename_field in obj:
                filename = obj[filename_field]
            elif module_resource_path:
                filename = os.path.basename(module_resource_path)
            else:
                filename = "%s-%s-%s" % (obj._name, obj.id, field)

        # mimetype
        mimetype = 'mimetype' in obj and obj.mimetype or False
        if not mimetype:
            if filename:
                mimetype = mimetypes.guess_type(filename)[0]
            if not mimetype and getattr(env[model]._fields[field], 'attachment', False):
                # for binary fields, fetch the ir_attachement for mimetype check
                attach_mimetype = env['ir.attachment'].search_read(domain=[('res_model', '=', model), ('res_id', '=', id), ('res_field', '=', field)], fields=['mimetype'], limit=1)
                mimetype = attach_mimetype and attach_mimetype[0]['mimetype']
            if not mimetype:
                mimetype = guess_mimetype(base64.b64decode(content), default=default_mimetype)

        headers += [('Content-Type', mimetype), ('X-Content-Type-Options', 'nosniff')]

        # cache
        etag = bool(request) and request.httprequest.headers.get('If-None-Match')
        retag = '"%s"' % hashlib.md5(pycompat.to_text(content).encode('utf-8')).hexdigest()
        status = status or (304 if etag == retag else 200)
        headers.append(('ETag', retag))
        headers.append(('Cache-Control', 'max-age=%s' % (STATIC_CACHE if unique else 0)))

        # content-disposition default name
        if download:
            headers.append(('Content-Disposition', cls.content_disposition(filename)))
        return (status, headers, content)