[IMP] mail: allow creating channels on first visit from token

This commit allows anyone to create a new mail.channel by visiting the
URL /chat/<token>[/<channel_name>], providing that the
mail.chat_from_token system parameter is set. This is useful in some
situations where new channels need to be created quickly as needed by
anyone without special permissions (eg, during the Odoo experience)

task-2648580

closes odoo/odoo#77010

X-original-commit: 56ddc073213a148579dd72f4a9336bc4d6a11f22
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
Signed-off-by: Samuel Degueldre <sdegueldre@users.noreply.github.com>
This commit is contained in:
Samuel Degueldre
2021-09-23 10:00:11 +00:00
parent 8221664804
commit 9efd9463eb
2 changed files with 32 additions and 1 deletions
+26
View File
@@ -4,6 +4,8 @@
import json
from collections import defaultdict
from datetime import datetime, timedelta
from psycopg2 import IntegrityError
from psycopg2.errorcodes import UNIQUE_VIOLATION
from odoo import http
from odoo.http import request
@@ -19,6 +21,30 @@ class DiscussController(http.Controller):
# Public Pages
# --------------------------------------------------------------------------
@http.route([
'/chat/<string:create_token>',
'/chat/<string:create_token>/<string:channel_name>',
], methods=['GET'], type='http', auth='public')
def discuss_channel_from_token(self, create_token, channel_name=None, **kwargs):
if not request.env['ir.config_parameter'].sudo().get_param('mail.chat_from_token'):
raise NotFound()
channel_sudo = request.env['mail.channel'].sudo().search([('uuid', '=', create_token)])
if not channel_sudo:
try:
channel_sudo = channel_sudo.create({
'uuid': create_token,
'name': channel_name or create_token,
'public': 'public',
})
except IntegrityError as e:
if e.pgcode != UNIQUE_VIOLATION:
raise
# concurrent insert attempt: another request created the channel.
# commit the current transaction and get the channel.
request.env.cr.commit()
channel_sudo = channel_sudo.search([('uuid', '=', create_token)])
return request.redirect(f'/chat/{channel_sudo.id}/{channel_sudo.uuid}')
@http.route('/chat/<int:channel_id>/<string:invitation_token>', methods=['GET'], type='http', auth='public')
def discuss_channel_invitation(self, channel_id, invitation_token, **kwargs):
channel_sudo = request.env['mail.channel'].browse(int(channel_id)).sudo().exists()
+6 -1
View File
@@ -79,7 +79,7 @@ class Channel(models.Model):
"Note that they will be able to manage their subscription manually "
"if necessary.")
# access
uuid = fields.Char('UUID', size=50, index=True, default=_generate_random_token, copy=False)
uuid = fields.Char('UUID', size=50, default=_generate_random_token, copy=False)
public = fields.Selection([
('public', 'Everyone'),
('private', 'Invited people only'),
@@ -88,6 +88,11 @@ class Channel(models.Model):
help='This group is visible by non members. Invisible groups can add members through the invite button.')
group_public_id = fields.Many2one('res.groups', string='Authorized Group',
default=lambda self: self.env.ref('base.group_user'))
_sql_constraints = [
('uuid_unique', 'UNIQUE(uuid)', 'The channel UUID must be unique'),
]
# COMPUTE / INVERSE
@api.depends('channel_type')