diff options
| author | jem-odoo <jem@openerp.com> | 2019-01-31 08:43:57 +0000 |
|---|---|---|
| committer | jem-odoo <jem@openerp.com> | 2019-02-06 09:55:13 +0000 |
| commit | 17ac041bfa2d92a11339e63016bce4696362b333 (patch) | |
| tree | cdf5fd4273de8b04e6ad7906ef079c4e6d242913 /addons/portal/controllers | |
| parent | 4cb228d823e0346e6052091d397249b8e39d576b (diff) | |
[REF] portal: posting message with signed token
Before this commit, it was possible to post a message on a document
the user has no access, thanks to a token. In addition to this token,
if a hash (signed token with a partner id), the author_id of the message
was forced.
This commit change a little bit that logic by distinguish 2 cases:
1/ Token only: anyone with the token can post a message on the document. If
the user is not logged (public with token), the author_id will be the
customer of the document (or the public user). This case is moslty used
for business document, through the portal or with the "share link" for
instance.
2/ Signed token: user has no write access to the document, but can post a
message on it. The user have to be logged, as the token is signed with its
identifier. The goal here is to avoid leaking the access token's document
to all visitors. This case is mostly used for public content, such as blog
posts, slides, ...
The token case was already existing. The second is now working with this
commit. To do so, it was required to
- move `_sign_token` from the portal mixin to mail.thread.
- transfering 'pid' and 'hash' parameters from the controller to template
to js widgets.
This commit also change the `_message_post_helper` signature by making
the 3 first parameters required, as to post a message you need at lease
res_model, res_id and the message body. The optional argurments and kwargs
are here to check the bypassing access rights mecanism.
Task-1902304
Diffstat (limited to 'addons/portal/controllers')
| -rw-r--r-- | addons/portal/controllers/mail.py | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/addons/portal/controllers/mail.py b/addons/portal/controllers/mail.py index dcccbb61fa1..49719c7568b 100644 --- a/addons/portal/controllers/mail.py +++ b/addons/portal/controllers/mail.py @@ -19,43 +19,59 @@ def _has_token_access(res_model, res_id, token=''): return (token and record and consteq(record[token_field], token)) -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). - +def _message_post_helper(res_model, res_id, message, token='', nosubscribe=True, **kw): + """ Generic chatter function, allowing to write on *any* object that inherits mail.thread. We + distinguish 2 cases: + 1/ 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). + + 2/ If a signed token is specified (`hash`) and also a partner_id (`pid`), all post message will + be done under the name of the partner_id (as it is signed). This should be used to avoid leaking + token to all users. + + Required parameters :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: + 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 string hash: signed token by a partner if model uses some token field to bypass access right + post messages. + :param string pid: identifier of the res.partner used to sign the hash :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 + # Token Case: token required to post message as document customer (if not logged) or as itself even if user has not the access 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 + # 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() + # Signed Token Case: hash implies token is signed by partner. So author_id is forced + elif kw.get('hash') and kw.get('pid'): + if consteq(kw['hash'], record._sign_token(int(kw['pid']))): + record = record.sudo() + author_id = kw.get('pid') + else: + raise Forbidden() kw.pop('csrf_token', None) kw.pop('attachment_ids', None) + kw.pop('hash', None) + kw.pop('pid', 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"), |
