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()
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.with_user(uid).check_access_rights('read') record_sudo.with_user(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 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
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
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: # 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() record['__last_update'] except AccessError: return None, 403 return record, 200
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
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')
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))
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['mailing.mailing'].sudo().browse(mailing_id) return consteq(mailing._unsubscribe_token(res_id, email), token)