示例#1
0
文件: ir_http.py 项目: Vauxoo/odoo
    def _get_record_and_check(self, xmlid=None, model=None, id=None, field='datas', access_token=None):
        # get object and content
        record = None
        if xmlid:
            record = self._xmlid_to_obj(self.env, xmlid)
        elif id and model in self.env:
            record = self.env[model].browse(int(id))

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

        if model == 'ir.attachment':
            record_sudo = record.sudo()
            if access_token and not consteq(record_sudo.access_token or '', access_token):
                return None, 403
            elif (access_token and consteq(record_sudo.access_token or '', access_token)):
                record = record_sudo
            elif record_sudo.public:
                record = record_sudo
            elif self.env.user.has_group('base.group_portal'):
                # Check the read access on the record linked to the attachment
                # eg: Allow to download an attachment on a task from /my/task/task_id 
                record.check('read')
                record = record_sudo

        # check read access
        try:
            record['__last_update']
        except AccessError:
            return None, 403

        return record, 200
示例#2
0
文件: mail.py 项目: fabianpc/odoo
def _check_special_access(res_model, res_id, token='', _hash='', pid=False):
    record = request.env[res_model].browse(res_id).sudo()
    if token:  # Token Case: token is the global one of the document
        token_field = request.env[res_model]._mail_post_token_field
        return (token and record and consteq(record[token_field], token))
    elif _hash and pid:  # Signed Token Case: hash implies token is signed by partner pid
        return consteq(_hash, record._sign_token(pid))
    else:
        raise Forbidden()
示例#3
0
    def _verify_stripe_signature(self):
        """
        :return: true if and only if signature matches hash of payload calculated with secret
        :raises ValidationError: if signature doesn't match
        """
        if not self.stripe_webhook_secret:
            raise ValidationError(
                'webhook event received but webhook secret is not configured')
        signature = request.httprequest.headers.get('Stripe-Signature')
        body = request.httprequest.data

        sign_data = {
            k: v
            for (k, v) in [s.split('=') for s in signature.split(',')]
        }
        event_timestamp = int(sign_data['t'])
        if datetime.utcnow().timestamp(
        ) - event_timestamp > STRIPE_SIGNATURE_AGE_TOLERANCE:
            _logger.error('stripe event is too old, event is discarded')
            raise ValidationError('event timestamp older than tolerance')

        signed_payload = "%s.%s" % (event_timestamp, body.decode('utf-8'))

        actual_signature = sign_data['v1']
        expected_signature = hmac.new(
            self.stripe_webhook_secret.encode('utf-8'),
            signed_payload.encode('utf-8'), sha256).hexdigest()

        if not consteq(expected_signature, actual_signature):
            _logger.error(
                'incorrect webhook signature from Stripe, check if the webhook signature '
                'in Odoo matches to one in the Stripe dashboard')
            raise ValidationError('incorrect webhook signature')

        return True
示例#4
0
 def _retrieve_api_key_id(self, key):
     if not self.env.user.has_group("base.group_system"):
         raise AccessError(_("User is not allowed"))
     for api_key in self.search([]):
         if consteq(key, api_key.key):
             return api_key.id
     raise ValidationError(_("The key %s is not allowed") % key)
示例#5
0
    def download_one(self,
                     id=None,
                     access_token=None,
                     share_id=None,
                     **kwargs):
        """
        used to download a single file from the portal multi-file page.

        :param id: id of the file
        :param access_token:  token of the share link
        :param share_id: id of the share link
        :return: a portal page to preview and download a single file.
        """
        env = request.env
        share = env['documents.share'].sudo().browse(share_id)
        if consteq(access_token, share.access_token):
            try:
                if share.action != 'upload' and share.state != 'expired':
                    return self._get_file_response(
                        id,
                        share_id=share_id,
                        share_token=share.access_token,
                        field='datas')
            except Exception:
                logger.exception("Failed to download attachment %s" % id)

        return request.not_found()
示例#6
0
文件: mail.py 项目: EdyKend/odoo
    def _redirect_to_record(cls, model, res_id, access_token=None, **kwargs):
        """ If the current user doesn't have access to the document, but provided
        a valid access token, redirect him to the front-end view.
        If the partner_id and hash parameters are given, add those parameters to the redirect url
        to authentify the recipient in the chatter, if any.

        :param model: the model name of the record that will be visualized
        :param res_id: the id of the record
        :param access_token: token that gives access to the record
            bypassing the rights and rules restriction of the user.
        :param kwargs: Typically, it can receive a partner_id and a hash (sign_token).
            If so, those two parameters are used to authentify the recipient in the chatter, if any.
        :return:
        """
        if issubclass(type(request.env[model]), request.env.registry['portal.mixin']):
            uid = request.session.uid or request.env.ref('base.public_user').id
            record_sudo = request.env[model].sudo().browse(res_id).exists()
            try:
                record_sudo.sudo(uid).check_access_rights('read')
                record_sudo.sudo(uid).check_access_rule('read')
            except AccessError:
                if record_sudo.access_token and access_token and consteq(record_sudo.access_token, access_token):
                    record_action = record_sudo.with_context(force_website=True).get_access_action()
                    if record_action['type'] == 'ir.actions.act_url':
                        pid = kwargs.get('pid')
                        hash = kwargs.get('hash')
                        url = record_action['url']
                        if pid and hash:
                            url = urls.url_parse(url)
                            url_params = url.decode_query()
                            url_params.update([("pid", pid), ("hash", hash)])
                            url = url.replace(query=urls.url_encode(url_params)).to_url()
                        return werkzeug.utils.redirect(url)
        return super(MailController, cls)._redirect_to_record(model, res_id, access_token=access_token)
示例#7
0
 def share_download_all(self, access_token=None, share_id=None, **kwargs):
     """
     :param share_id: id of the share, the name of the share will be the name of the zip file share.
     :param access_token: share access token
     :returns the http response for a zip file if the token and the ID are valid.
     """
     env = request.env
     try:
         share = env['documents.share'].sudo().browse(share_id)
         if share.state == 'expired':
             return request.not_found()
         if consteq(access_token, share.access_token):
             if share.action != 'upload':
                 attachments = False
                 if share.type == 'domain':
                     domain = []
                     if share.domain:
                         domain = literal_eval(share.domain)
                     domain = expression.AND(
                         [domain, [['folder_id', '=', share.folder_id.id]]])
                     attachments = http.request.env['ir.attachment'].sudo(
                     ).search(domain)
                 elif share.type == 'ids':
                     attachments = share.attachment_ids
                 return self._make_zip(
                     (share.name or 'unnamed-link') + '.zip', attachments)
     except Exception:
         logger.exception("Failed to zip share link id: %s" % share_id)
     return request.not_found()
 def check_token(self, access_token, partner_id, amount, currency_id):
     secret = self.env['ir.config_parameter'].sudo().get_param('database.secret')
     token_str = '%s%s%s' % (partner_id, amount, currency_id)
     correct_token = hmac.new(secret.encode('utf-8'), token_str.encode('utf-8'), hashlib.sha256).hexdigest()
     if consteq(ustr(access_token), correct_token):
         return True
     return False
示例#9
0
文件: discuss.py 项目: mejerome/odoo
 def discuss_channel_invitation(self, channel_id, invitation_token, **kwargs):
     channel_sudo = request.env['mail.channel'].browse(int(channel_id)).sudo().exists()
     if not channel_sudo or not channel_sudo.uuid or not consteq(channel_sudo.uuid, invitation_token):
         raise NotFound()
     if channel_sudo.env['mail.channel.partner']._get_as_sudo_from_request(request=request, channel_id=int(channel_id)):
         return request.redirect(f'/discuss/channel/{channel_sudo.id}')
     if channel_sudo.channel_type == 'chat':
         raise NotFound()
     response = request.redirect(f'/discuss/channel/{channel_sudo.id}/welcome')
     if not channel_sudo.env.user._is_public():
         channel_sudo.add_members([channel_sudo.env.user.partner_id.id])
         return response
     guest = channel_sudo.env['mail.guest']._get_guest_from_request(request)
     if not guest:
         guest = channel_sudo.env['mail.guest'].create({
             'country_id': channel_sudo.env['res.country'].search([('code', '=', request.session.get('geoip', {}).get('country_code'))], limit=1).id,
             'lang': get_lang(channel_sudo.env).code,
             'name': _("Guest"),
             'timezone': channel_sudo.env['mail.guest']._get_timezone_from_request(request),
         })
         # Discuss Guest ID: every route in this file will make use of it to authenticate
         # the guest through `_get_as_sudo_from_request` or `_get_as_sudo_from_request_or_raise`.
         expiration_date = datetime.now() + timedelta(days=365)
         response.set_cookie(guest._cookie_name, f"{guest.id}{guest._cookie_separator}{guest.access_token}", httponly=True, expires=expiration_date)
     channel_sudo.add_members(guest_ids=[guest.id])
     return response
示例#10
0
文件: portal.py 项目: enmingc/odoo
    def _document_check_access(self,
                               model_name,
                               document_id,
                               access_token=None):
        """Check if current user is allowed to access the specified record.

        :param str model_name: model of the requested record
        :param int document_id: id of the requested record
        :param str access_token: record token to check if user isn't allowed to read requested record
        :return: expected record, SUDOED, with SUPERUSER context
        :raise MissingError: record not found in database, might have been deleted
        :raise AccessError: current user isn't allowed to read requested document (and no valid token was given)
        """
        document = request.env[model_name].browse([document_id])
        document_sudo = document.with_user(SUPERUSER_ID).exists()
        if not document_sudo:
            raise MissingError(_("This document does not exist."))
        try:
            document.check_access_rights('read')
            document.check_access_rule('read')
        except AccessError:
            if not access_token or not document_sudo.access_token or not consteq(
                    document_sudo.access_token, access_token):
                raise
        return document_sudo
示例#11
0
文件: ir_http.py 项目: Tecnativa/odoo
    def _get_record_and_check(self, xmlid=None, model=None, id=None, field='datas', access_token=None):
        # get object and content
        record = None
        if xmlid:
            record = self._xmlid_to_obj(self.env, xmlid)
        elif id and model in self.env:
            record = self.env[model].browse(int(id))

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

        # access token grant access
        if model == 'ir.attachment' and access_token:
            record = record.sudo()
            if not consteq(record.access_token or '', access_token):
                return None, 403

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

        return record, 200
示例#12
0
    def article_invite(self, member_id, invitation_hash):
        """ This route will check if the given parameter allows the client to access the article via the invite token.
        Then, if the partner has not registered yet, we will redirect the client to the signup page to finally redirect
        them to the article.
        If the partner already has registrered, we redirect them directly to the article.
        """
        member = request.env['knowledge.article.member'].sudo().browse(member_id).exists()
        correct_token = member._get_invitation_hash() if member else False
        if not correct_token or not tools.consteq(correct_token, invitation_hash):
            raise werkzeug.exceptions.NotFound()

        partner = member.partner_id
        article = member.article_id

        if not partner.user_ids:
            # Force the signup even if not enabled (as we explicitly invited the member).
            # They should still be able to create a user.
            signup_allowed = request.env['res.users']._get_signup_invitation_scope() == 'b2c'
            if not signup_allowed:
                partner.signup_prepare()
            partner.signup_get_auth_param()
            signup_url = partner._get_signup_url_for_action(url='/knowledge/article/%s' % article.id)[partner.id]
            return request.redirect(signup_url)

        return request.redirect('/web/login?redirect=/knowledge/article/%s' % article.id)
示例#13
0
 def _check_token(self, access_token):
     if not access_token:
         return False
     try:
         return consteq(access_token, self.access_token)
     except:
         return False
示例#14
0
文件: portal.py 项目: MRHalcyIT/OCB
 def confirm(self, **kw):
     tx_id = int(kw.get('tx_id', 0))
     access_token = kw.get('access_token')
     if tx_id:
         if access_token:
             tx = request.env['payment.transaction'].sudo().browse(tx_id)
             secret = request.env['ir.config_parameter'].sudo().get_param('database.secret')
             valid_token_str = '%s%s%s' % (tx.id, tx.reference, float_repr(tx.amount, precision_digits=tx.currency_id.decimal_places))
             valid_token = hmac.new(secret.encode('utf-8'), valid_token_str.encode('utf-8'), hashlib.sha256).hexdigest()
             if not consteq(ustr(valid_token), access_token):
                 raise werkzeug.exceptions.NotFound
         else:
             tx = request.env['payment.transaction'].browse(tx_id)
         if tx.state in ['done', 'authorized']:
             status = 'success'
             message = tx.acquirer_id.done_msg
         elif tx.state == 'pending':
             status = 'warning'
             message = tx.acquirer_id.pending_msg
         else:
             status = 'danger'
             message = tx.state_message or _('An error occured during the processing of this payment')
         PaymentProcessing.remove_payment_transaction(tx)
         return request.render('payment.confirm', {'tx': tx, 'status': status, 'message': message})
     else:
         return request.redirect('/my/home')
示例#15
0
 def mail_attachment_delete(self,
                            attachment_id,
                            access_token=None,
                            **kwargs):
     attachment_sudo = request.env['ir.attachment'].browse(
         int(attachment_id)).sudo().exists()
     if not attachment_sudo:
         raise NotFound()
     if not request.env.user.share:
         # Check through standard access rights/rules for internal users.
         return attachment_sudo.sudo(False).unlink()
     # For non-internal users 2 cases are supported:
     #   - Either the attachment is linked to a message: verify the request is made by the author of the message (portal user or guest).
     #   - Either a valid access token is given: also verify the message is pending (because unfortunately in portal a token is also provided to guest for viewing others' attachments).
     message_sudo = request.env['mail.message'].sudo().search(
         [('attachment_ids', 'in', attachment_sudo.ids)], limit=1)
     if message_sudo:
         if request.session.uid and (
                 not message_sudo.author_id
                 or message_sudo.author_id != request.env.user.partner_id):
             raise NotFound()
         if not request.session.uid and (
                 not message_sudo.author_guest_id
                 or message_sudo.author_guest_id != request.
                 env['mail.guest']._get_guest_from_request(request)):
             raise NotFound()
     else:
         if not access_token or not attachment_sudo.access_token or not consteq(
                 access_token, attachment_sudo.access_token):
             raise NotFound()
         if attachment_sudo.res_model != 'mail.compose.message' or attachment_sudo.res_id != 0:
             raise NotFound()
     return attachment_sudo.unlink()
示例#16
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
示例#17
0
 def _check_token(cls, token):
     base_link = request.httprequest.path
     params = dict(request.params)
     params.pop('token', '')
     valid_token = request.env['mail.thread']._notify_encode_link(
         base_link, params)
     return consteq(valid_token, str(token))
示例#18
0
    def _redirect_to_record(cls, model, res_id, access_token=None, **kwargs):
        """ If the current user doesn't have access to the document, but provided
        a valid access token, redirect him to the front-end view.
        If the partner_id and hash parameters are given, add those parameters to the redirect url
        to authentify the recipient in the chatter, if any.

        :param model: the model name of the record that will be visualized
        :param res_id: the id of the record
        :param access_token: token that gives access to the record
            bypassing the rights and rules restriction of the user.
        :param kwargs: Typically, it can receive a partner_id and a hash (sign_token).
            If so, those two parameters are used to authentify the recipient in the chatter, if any.
        :return:
        """
        if issubclass(type(request.env[model]), request.env.registry['portal.mixin']):
            uid = request.session.uid or request.env.ref('base.public_user').id
            record_sudo = request.env[model].sudo().browse(res_id).exists()
            try:
                record_sudo.sudo(uid).check_access_rights('read')
                record_sudo.sudo(uid).check_access_rule('read')
            except AccessError:
                if record_sudo.access_token and access_token and consteq(record_sudo.access_token, access_token):
                    record_action = record_sudo.with_context(force_website=True).get_access_action()
                    if record_action['type'] == 'ir.actions.act_url':
                        pid = kwargs.get('pid')
                        hash = kwargs.get('hash')
                        url = record_action['url']
                        if pid and hash:
                            url = urls.url_parse(url)
                            url_params = url.decode_query()
                            url_params.update([("pid", pid), ("hash", hash)])
                            url = url.replace(query=urls.url_encode(url_params)).to_url()
                        return werkzeug.utils.redirect(url)
        return super(MailController, cls)._redirect_to_record(model, res_id, access_token=access_token)
 def _get_api_key_name(cls, auth_api_key):
     for section in serv_config.sections():
         if section.startswith("api_key_") and serv_config.has_option(
                 section, "key"):
             if tools.consteq(auth_api_key, serv_config.get(section,
                                                            "key")):
                 return section
     return None
示例#20
0
    def share_portal(self, share_id=None, token=None):
        """
        Leads to a public portal displaying downloadable files for anyone with the token.

        :param share_id: id of the share link
        :param token: share access token
        """
        try:
            share = http.request.env['documents.share'].sudo().search([
                ('id', '=', share_id)
            ])
            if share.state == 'expired':
                expired_options = {
                    'expiration_date': share.date_deadline,
                    'author': share.create_uid.name,
                }
                return request.render('documents.not_available',
                                      expired_options)
            if not consteq(token, share.access_token):
                return request.not_found()

            if share.type == 'domain':
                domain = []
                if share.domain:
                    domain = literal_eval(share.domain)
                domain += [['folder_id', '=', share.folder_id.id]]
                attachments = http.request.env['ir.attachment'].sudo().search(
                    domain)
            elif share.type == 'ids':
                attachments = share.attachment_ids
            else:
                return request.not_found()

            options = {
                'base_url':
                http.request.env["ir.config_parameter"].sudo().get_param(
                    "web.base.url"),
                'token':
                str(token),
                'upload':
                share.action == 'downloadupload',
                'share_id':
                str(share.id),
                'author':
                share.create_uid.name,
            }
            if len(attachments) == 1 and share.type == 'ids':
                options.update(attachment=attachments[0])
                return request.render('documents.share_single', options)
            else:
                options.update(all_button='binary' in [
                    attachment.type for attachment in attachments
                ],
                               attachment_ids=attachments)
                return request.render('documents.share_page', options)
        except Exception:
            logger.exception("Failed to generate the multi file share portal")
        return request.not_found()
示例#21
0
文件: discuss.py 项目: GSLabIt/odoo
 def discuss_channel_invitation(self, channel_id, invitation_token,
                                **kwargs):
     channel_sudo = request.env['mail.channel'].browse(
         channel_id).sudo().exists()
     if not channel_sudo or not channel_sudo.uuid or not consteq(
             channel_sudo.uuid, invitation_token):
         raise NotFound()
     return self._response_discuss_channel_invitation(
         channel_sudo=channel_sudo)
示例#22
0
    def _get_record_and_check(self,
                              xmlid=None,
                              model=None,
                              id=None,
                              field='datas',
                              access_token=None):
        # get object and content
        record = None
        if xmlid:
            record = self._xmlid_to_obj(self.env, xmlid)
        elif id and model in self.env:
            record = self.env[model].browse(int(id))

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

        if model == 'ir.attachment':
            record_sudo = record.sudo()
            if access_token and not consteq(record_sudo.access_token or '',
                                            access_token):
                return None, 403
            elif (access_token
                  and consteq(record_sudo.access_token or '', access_token)):
                record = record_sudo
            elif record_sudo.public:
                record = record_sudo
            elif self.env.user.has_group('base.group_portal'):
                # Check the read access on the record linked to the attachment
                # eg: Allow to download an attachment on a task from /my/task/task_id
                record.check('read')
                record = record_sudo
            # We have prefetched some fields of record, among which the field
            # 'write_date' used by '__last_update' below. In order to check
            # access on record, we have to invalidate its cache first.
            record._cache.clear()

        # check read access
        try:
            record['__last_update']
        except AccessError:
            return None, 403

        return record, 200
示例#23
0
 def _contact_check_access(self, contact_id, access_token=None):
     contact = request.env['hr.employee'].browse([contact_id])
     contact_sudo = contact.sudo()
     try:
         contact.check_access_rights('read')
         contact.check_access_rule('read')
     except AccessError:
         if not access_token or not consteq(contact_sudo.access_token, access_token):
             raise
     return contact_sudo
示例#24
0
文件: portal.py 项目: 10537/odoo
 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
示例#25
0
文件: portal.py 项目: yanchunLiu/odoo
 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
示例#26
0
文件: portal.py 项目: 10537/odoo
 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
示例#27
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
示例#28
0
文件: portal.py 项目: CRITEAN/Odoo
 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
示例#29
0
 def _picking_check_access(self, rma_id, picking_id, access_token=None):
     rma = request.env['rma'].browse([rma_id])
     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(rma.access_token, access_token):
             raise
     return picking_sudo
示例#30
0
    def track_mail_open(self, mail_id, token, **post):
        """ Email tracking. """
        if not consteq(token, tools.hmac(request.env(su=True), 'mass_mailing-mail_mail-open', mail_id)):
            raise BadRequest()

        request.env['mailing.trace'].sudo().set_opened(mail_mail_ids=[mail_id])
        response = werkzeug.wrappers.Response()
        response.mimetype = 'image/gif'
        response.data = base64.b64decode(b'R0lGODlhAQABAIAAANvf7wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==')

        return response
示例#31
0
 def _ad_blocks_check_access(self, ad_block_id, access_token=None):
     ad_blocks = request.env['sale.order.line'].browse([ad_block_id])
     ad_blocks_sudo = ad_blocks.sudo()
     try:
         ad_blocks.check_access_rights('read')
         ad_blocks.check_access_rule('read')
     except AccessError:
         if not access_token or not consteq(ad_blocks_sudo.access_token,
                                            access_token):
             raise
     return ad_blocks
示例#32
0
 def _appointments_check_access(self, appoint_id, access_token=None):
     appointments = request.env['appointment'].browse([appoint_id])
     appointments_sudo = appointments.sudo()
     try:
         appointments.check_access_rights('read')
         appointments.check_access_rule('read')
     except AccessError:
         if not access_token or not consteq(appointments_sudo.access_token,
                                            access_token):
             raise
     return appointments_sudo
示例#33
0
 def _br_check_access(self, br_id, access_token=None):
     br = request.env['business.requirement'].browse([br_id])
     br_sudo = br.sudo()
     try:
         br.check_access_rights('read')
         br.check_access_rule('read')
     except AccessError:
         if not access_token or not consteq(br_sudo.access_token,
                                            access_token):
             raise
     return br_sudo
示例#34
0
 def _document_check_access(self, model_name, document_id, access_token=None):
     document = request.env[model_name].browse([document_id])
     document_sudo = document.with_user(SUPERUSER_ID).exists()
     if not document_sudo:
         raise MissingError(_("This document does not exist."))
     try:
         document.check_access_rights('read')
         document.check_access_rule('read')
     except AccessError:
         if not access_token or not document_sudo.access_token or not consteq(document_sudo.access_token, access_token):
             raise
     return document_sudo
示例#35
0
文件: portal.py 项目: bitctrl/odoo
 def _document_check_access(self, model_name, document_id, access_token=None):
     document = request.env[model_name].browse([document_id])
     document_sudo = document.sudo().exists()
     if not document_sudo:
         raise MissingError("This document does not exist.")
     try:
         document.check_access_rights('read')
         document.check_access_rule('read')
     except AccessError:
         if not access_token or not consteq(document_sudo.access_token, access_token):
             raise
     return document_sudo
示例#36
0
def _message_post_helper(res_model='',
                         res_id=None,
                         message='',
                         token='',
                         nosubscribe=True,
                         **kw):
    """ Generic chatter function, allowing to write on *any* object that inherits mail.thread.
        If a token is specified, all logged in users will be able to write a message regardless
        of access rights; if the user is the public user, the message will be posted under the name
        of the partner_id of the object (or the public user if there is no partner_id on the object).

        :param string res_model: model name of the object
        :param int res_id: id of the object
        :param string message: content of the message

        optional keywords arguments:
        :param string token: access token if the object's model uses some kind of public access
                             using tokens (usually a uuid4) to bypass access rules
        :param bool nosubscribe: set False if you want the partner to be set as follower of the object when posting (default to True)

        The rest of the kwargs are passed on to message_post()
    """
    record = request.env[res_model].browse(res_id)
    author_id = request.env.user.partner_id.id if request.env.user.partner_id else False
    if token:
        access_as_sudo = _has_token_access(res_model, res_id, token=token)
        if access_as_sudo:
            record = record.sudo()
            if request.env.user._is_public():
                if kw.get('pid') and consteq(
                        kw.get('hash'), record._sign_token(int(
                            kw.get('pid')))):
                    author_id = kw.get('pid')
                else:
                    # TODO : After adding the pid and sign_token in access_url when send invoice by email, remove this line
                    # TODO : Author must be Public User (to rename to 'Anonymous')
                    author_id = record.partner_id.id if hasattr(
                        record,
                        'partner_id') and record.partner_id.id else author_id
            else:
                if not author_id:
                    raise NotFound()
        else:
            raise Forbidden()
    kw.pop('csrf_token', None)
    kw.pop('attachment_ids', None)
    return record.with_context(
        mail_create_nosubscribe=nosubscribe).message_post(
            body=message,
            message_type=kw.pop('message_type', "comment"),
            subtype=kw.pop('subtype', "mt_comment"),
            author_id=author_id,
            **kw)
示例#37
0
文件: utils.py 项目: GSLabIt/odoo
def check_access_token(access_token, *values):
    """ Check the validity of the access token for the provided values.

    The values must be provided in the exact same order as they were to `generate_access_token`.
    All values must be convertible to a string.

    :param str access_token: The access token used to verify the provided values
    :param list values: The values to verify against the token
    :return: True if the check is successful
    :rtype: bool
    """
    authentic_token = generate_access_token(*values)
    return access_token and consteq(ustr(access_token), authentic_token)
示例#38
0
 def _get_guest_from_request(self, request):
     guest_id = request.httprequest.cookies.get('mail.guest_id')
     guest_access_token = request.httprequest.cookies.get('mail.guest_access_token')
     if not guest_id or not guest_access_token:
         return self.env['mail.guest']
     guest = self.env['mail.guest'].browse(int(guest_id)).sudo().exists()
     if not guest or not guest.access_token or not consteq(guest.access_token, guest_access_token):
         return self.env['mail.guest']
     if not guest.timezone:
         timezone = self._get_timezone_from_request(request)
         if timezone:
             guest._update_timezone(timezone)
     return guest.sudo(False).with_context(guest=guest)
示例#39
0
    def execute_callback(self):
        res = None
        for transaction in self.filtered(lambda tx: tx.callback_model_id and tx.callback_res_id and tx.callback_method):
            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
示例#40
0
文件: portal.py 项目: ATHENATECH/odoo
    def portal_my_invoice_detail(self, invoice_id, access_token=None, **kw):
        invoice = request.env['account.invoice'].browse(invoice_id)
        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):
                return request.redirect('/my')

        values = {
            'page_name': 'invoice',
            'invoice': invoice.sudo(),
        }
        return request.render("account.portal_invoice_page", values)
示例#41
0
文件: main.py 项目: astirpe/odoo
    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)
            right_token = mailing._unsubscribe_token(res_id, email)
            if not consteq(str(token), right_token):
                raise exceptions.AccessDenied()

            if mailing.mailing_model_real == 'mail.mass_mailing.contact':
                # Unsubscribe directly + Let the user choose his subscriptions
                mailing.update_opt_out(email, mailing.contact_list_ids.ids, True)

                contacts = request.env['mail.mass_mailing.contact'].sudo().search([('email', '=', email)])
                subscription_list_ids = contacts.mapped('subscription_list_ids')
                # In many user are found : if user is opt_out on the list with contact_id 1 but not with contact_id 2,
                # assume that the user is not opt_out on both
                # TODO DBE Fixme : Optimise the following to get real opt_out and opt_in
                opt_out_list_ids = subscription_list_ids.filtered(lambda rel: rel.opt_out).mapped('list_id')
                opt_in_list_ids = subscription_list_ids.filtered(lambda rel: not rel.opt_out).mapped('list_id')
                opt_out_list_ids = set([list.id for list in opt_out_list_ids if list not in opt_in_list_ids])

                unique_list_ids = set([list.list_id.id for list in subscription_list_ids])
                list_ids = request.env['mail.mass_mailing.list'].sudo().browse(unique_list_ids)
                unsubscribed_list = ', '.join(str(list.name) for list in mailing.contact_list_ids if list.is_public)
                return request.render('mass_mailing.page_unsubscribe', {
                    'contacts': contacts,
                    'list_ids': list_ids,
                    'opt_out_list_ids': opt_out_list_ids,
                    'unsubscribed_list': unsubscribed_list,
                    'email': email,
                    'mailing_id': mailing_id,
                    'res_id': res_id,
                    'show_blacklist_button': request.env['ir.config_parameter'].sudo().get_param('mass_mailing.show_blacklist_buttons'),
                    })
            else:
                blacklist_rec = request.env['mail.blacklist'].sudo()._add(email)
                blacklist_rec._message_log(_("""The %s asked to not be contacted anymore 
                using an unsubscribe link.""" % request.env['ir.model']._get(mailing.mailing_model_real).display_name))
                return request.render('mass_mailing.page_unsubscribed', {
                    'email': email,
                    'mailing_id': mailing_id,
                    'res_id': res_id,
                    'show_blacklist_button': request.env['ir.config_parameter'].sudo().get_param(
                        'mass_mailing.show_blacklist_buttons'),
                    })
        return request.redirect('/web')
示例#42
0
文件: portal.py 项目: ATHENATECH/odoo
    def portal_my_invoice_report(self, invoice_id, access_token=None, **kw):
        invoice = request.env['account.invoice'].browse(invoice_id)
        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):
                return request.redirect('/my')

        # print report as sudo, since it require access to taxes, payment term, ... and portal
        # does not have those access rights.
        pdf = request.env.ref('account.account_invoices').sudo().render_qweb_pdf([invoice_id])[0]
        pdfhttpheaders = [
            ('Content-Type', 'application/pdf'),
            ('Content-Length', len(pdf)),
        ]
        return request.make_response(pdf, headers=pdfhttpheaders)
示例#43
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_ids = []
            if mailing.mailing_model == 'mail.mass_mailing.contact':
                contacts = request.env['mail.mass_mailing.contact'].sudo().search([
                    ('email', '=', email),
                    ('list_id', '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(token, right_token):
                raise exceptions.AccessDenied()
            mailing.update_opt_out(email, res_ids, True)
            return _('You have been unsubscribed successfully')
示例#44
0
文件: mail.py 项目: EdyKend/odoo
def _message_post_helper(res_model='', res_id=None, message='', token='', nosubscribe=True, **kw):
    """ Generic chatter function, allowing to write on *any* object that inherits mail.thread.
        If a token is specified, all logged in users will be able to write a message regardless
        of access rights; if the user is the public user, the message will be posted under the name
        of the partner_id of the object (or the public user if there is no partner_id on the object).

        :param string res_model: model name of the object
        :param int res_id: id of the object
        :param string message: content of the message

        optional keywords arguments:
        :param string token: access token if the object's model uses some kind of public access
                             using tokens (usually a uuid4) to bypass access rules
        :param bool nosubscribe: set False if you want the partner to be set as follower of the object when posting (default to True)

        The rest of the kwargs are passed on to message_post()
    """
    record = request.env[res_model].browse(res_id)
    author_id = request.env.user.partner_id.id if request.env.user.partner_id else False
    if token:
        access_as_sudo = _has_token_access(res_model, res_id, token=token)
        if access_as_sudo:
            record = record.sudo()
            if request.env.user._is_public():
                if kw.get('pid') and consteq(kw.get('hash'), record._sign_token(int(kw.get('pid')))):
                    author_id = kw.get('pid')
                else:
                    # TODO : After adding the pid and sign_token in access_url when send invoice by email, remove this line
                    # TODO : Author must be Public User (to rename to 'Anonymous')
                    author_id = record.partner_id.id if hasattr(record, 'partner_id') and record.partner_id.id else author_id
            else:
                if not author_id:
                    raise NotFound()
        else:
            raise Forbidden()
    kw.pop('csrf_token', None)
    kw.pop('attachment_ids', None)
    return record.with_context(mail_create_nosubscribe=nosubscribe).message_post(body=message,
                                                                                   message_type=kw.pop('message_type', "comment"),
                                                                                   subtype=kw.pop('subtype', "mt_comment"),
                                                                                   author_id=author_id,
                                                                                   **kw)
示例#45
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
示例#46
0
文件: main.py 项目: rossigee/odoo
    def orders_followup(self, order=None, access_token=None, **kw):
        order = request.env['sale.order'].browse([order])
        order_sudo = order.sudo()
        values = {}
        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):
                return request.render("website.403")
            values.update({'no_breadcrumbs': True})

        order_invoice_lines = {il.product_id.id: il.invoice_id for il in order_sudo.invoice_ids.mapped('invoice_line_ids')}
        history = request.session.get('my_orders_history', [])

        values.update({
            'order': order_sudo,
            'order_invoice_lines': order_invoice_lines,
        })
        values.update(get_records_pager(history, order_sudo))
        return request.render("website_portal_sale.orders_followup", values)
示例#47
0
文件: mail.py 项目: EdyKend/odoo
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))
示例#48
0
文件: main.py 项目: bud-e/odoo
 def _valid_unsubscribe_token(self, mailing_id, res_id, email, token):
     if not (mailing_id and res_id and email and token):
         return False
     mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id)
     return consteq(mailing._unsubscribe_token(res_id, email), token)
示例#49
0
文件: ir_http.py 项目: bud-e/odoo
    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, related_id=None, access_mode=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 related_id: the id of another record used for custom_check
        :param  access_mode: if truthy, will call custom_check to fetch the object that contains the binary.
        :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 = cls._xmlid_to_obj(env, xmlid)
        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)

        # access token grant access
        if model == 'ir.attachment' and access_token:
            obj = obj.sudo()
            if access_mode:
                if not cls._check_access_mode(env, id, access_mode, model, access_token=access_token,
                                             related_id=related_id):
                    return (403, [], None)
            elif not consteq(obj.access_token or u'', access_token):
                return (403, [], 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)
示例#50
0
文件: mail.py 项目: ATHENATECH/odoo
def _special_access_object(res_model, res_id, token='', token_field=''):
    record = request.env[res_model].browse(res_id).sudo()
    if token and record and getattr(record, token_field, None) and consteq(getattr(record, token_field), token):
        return True
    return False
示例#51
0
文件: main.py 项目: ATHENATECH/odoo
 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))