diff --git a/addons/hr_holidays/tests/test_out_of_office.py b/addons/hr_holidays/tests/test_out_of_office.py
index 6828acd6721..567ceabff66 100644
--- a/addons/hr_holidays/tests/test_out_of_office.py
+++ b/addons/hr_holidays/tests/test_out_of_office.py
@@ -46,7 +46,6 @@ class TestOutOfOffice(TestHrHolidaysCommon):
'mail_create_nosubscribe': True,
}).create({
'channel_partner_ids': [(4, partner.id), (4, partner2.id)],
- 'public': 'private',
'channel_type': 'chat',
'name': 'test'
})
diff --git a/addons/im_livechat/models/im_livechat_channel.py b/addons/im_livechat/models/im_livechat_channel.py
index b3f99054ce9..1d88f924fa6 100644
--- a/addons/im_livechat/models/im_livechat_channel.py
+++ b/addons/im_livechat/models/im_livechat_channel.py
@@ -159,7 +159,6 @@ class ImLivechatChannel(models.Model):
'country_id': country_id,
'channel_type': 'livechat',
'name': name,
- 'public': 'private',
}
def _open_livechat_mail_channel(self, anonymous_name, previous_operator_id=None, chatbot_script=None, user_id=None, country_id=None):
diff --git a/addons/im_livechat/static/tests/helpers/mock_server.js b/addons/im_livechat/static/tests/helpers/mock_server.js
index e8ea9cbb6d7..e7109d2ccbf 100644
--- a/addons/im_livechat/static/tests/helpers/mock_server.js
+++ b/addons/im_livechat/static/tests/helpers/mock_server.js
@@ -136,7 +136,6 @@ patch(MockServer.prototype, 'im_livechat', {
'country_id': country_id,
'channel_type': 'livechat',
'name': membersName.join(' '),
- 'public': 'private',
};
},
/**
diff --git a/addons/mail/controllers/discuss.py b/addons/mail/controllers/discuss.py
index b3e96cd452b..5adbbe1b001 100644
--- a/addons/mail/controllers/discuss.py
+++ b/addons/mail/controllers/discuss.py
@@ -54,9 +54,9 @@ class DiscussController(http.Controller):
if not channel_sudo:
try:
channel_sudo = channel_sudo.create({
+ 'channel_type': 'channel',
'default_display_mode': default_display_mode,
'name': channel_name or create_token,
- 'public': 'public',
'uuid': create_token,
})
except IntegrityError as e:
@@ -93,7 +93,7 @@ class DiscussController(http.Controller):
except UserError:
raise NotFound()
else:
- if channel_sudo.public == 'groups':
+ if channel_sudo.group_public_id:
raise NotFound()
guest = channel_sudo.env['mail.guest'].create({
'country_id': channel_sudo.env['res.country'].search([('code', '=', request.geoip.get('country_code'))], limit=1).id,
diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py
index ff0e3f8edd1..4ffd8d345a9 100644
--- a/addons/mail/models/mail_channel.py
+++ b/addons/mail/models/mail_channel.py
@@ -75,12 +75,6 @@ class Channel(models.Model):
"if necessary.")
# access
uuid = fields.Char('UUID', size=50, default=_generate_random_token, copy=False)
- public = fields.Selection([
- ('public', 'Everyone'),
- ('private', 'Invited people only'),
- ('groups', 'Selected group of users')], string='Privacy',
- required=True, default='groups',
- 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', compute='_compute_group_public_id', readonly=False, store=True)
invitation_url = fields.Char('Invitation URL', compute='_compute_invitation_url')
@@ -216,9 +210,6 @@ class Channel(models.Model):
@api.model_create_multi
def create(self, vals_list):
- defaults = self.default_get(['public'])
-
- access_types = []
for vals in vals_list:
# find partners to add from partner_ids
partner_ids_cmd = vals.get('channel_partner_ids') or []
@@ -241,21 +232,11 @@ class Channel(models.Model):
for pid in partner_ids_to_add if pid not in membership_pids
]
- # save visibility, apply public visibility for create then set back after creation
- # to avoid ACLS issue
- access_type = vals.pop('public', defaults['public'])
- access_types.append(access_type)
- vals['public'] = 'public'
-
# clean vals
vals.pop('channel_partner_ids', False)
# Create channel and alias
- channels = super(Channel, self.with_context(mail_create_nolog=True, mail_create_nosubscribe=True)).create(vals_list)
-
- for access_type, channel in zip(access_types, channels):
- if access_type != 'public':
- channel.sudo().public = access_type
+ channels = super(Channel, self.with_context(mail_create_bypass_create_check=self.env['mail.channel.member']._bypass_create_check, mail_create_nolog=True, mail_create_nosubscribe=True)).create(vals_list)
channels._subscribe_users_automatically()
@@ -355,7 +336,7 @@ class Channel(models.Model):
notifications = []
for channel in self:
members_to_create = []
- if channel.public == 'groups':
+ if channel.group_public_id:
invalid_partners = partners.filtered(lambda partner: channel.group_public_id not in partner.user_ids.groups_id)
if invalid_partners:
raise UserError(_(
@@ -438,17 +419,17 @@ class Channel(models.Model):
def _can_invite(self, partner_id):
"""Return True if the current user can invite the partner to the channel.
- * public: ok;
- * private: must be member;
- * group: both current user and target must have group;
+ * channel -- public channel: ok;
+ * -- group restricted channel: both current user and target must in the group;
+ * chat/group: current user must be member;
:return boolean: whether inviting is ok"""
partner = self.env['res.partner'].browse(partner_id)
for channel in self.sudo():
- if channel.public == 'private' and not channel.is_member:
+ if channel.channel_type != 'channel' and not channel.is_member:
return False
- if channel.public == 'groups':
+ if channel.group_public_id:
if not partner.user_ids or channel.group_public_id not in partner.user_ids.groups_id:
return False
if channel.group_public_id not in self.env.user.groups_id:
@@ -792,7 +773,6 @@ class Channel(models.Model):
'uuid': channel.uuid,
'state': 'open',
'is_minimized': False,
- 'public': channel.public,
'group_based_subscription': bool(channel.group_ids),
'create_uid': channel.create_uid.id,
'authorizedGroupFullName': channel.group_public_id.full_name,
@@ -883,7 +863,6 @@ class Channel(models.Model):
SELECT M.channel_id
FROM mail_channel C, mail_channel_member M
WHERE M.channel_id = C.id
- AND C.public LIKE 'private'
AND M.partner_id IN %s
AND C.channel_type LIKE 'chat'
AND NOT EXISTS (
@@ -911,7 +890,6 @@ class Channel(models.Model):
# create a new one
channel = self.create({
'channel_partner_ids': [Command.link(partner_id) for partner_id in partners_to],
- 'public': 'private',
'channel_type': 'chat',
'name': ', '.join(self.env['res.partner'].sudo().browse(partners_to).mapped('name')),
})
@@ -1051,25 +1029,6 @@ class Channel(models.Model):
'model': 'mail.channel',
})
- @api.model
- def channel_search_to_join(self, name=None, domain=None):
- """ Return the channel info of the channel the current partner can join
- :param name : the name of the researched channels
- :param domain : the base domain of the research
- :returns dict : channel dict
- """
- if not domain:
- domain = []
- domain = expression.AND([
- [('channel_type', '=', 'channel')],
- [('channel_partner_ids', 'not in', [self.env.user.partner_id.id])],
- [('public', '!=', 'private')],
- domain
- ])
- if name:
- domain = expression.AND([domain, [('name', 'ilike', '%'+name+'%')]])
- return self.search(domain).read(['name', 'public', 'uuid', 'channel_type'])
-
def channel_join(self):
""" Shortcut to add the current user as member of self channels.
Prefer calling add_members() directly when possible.
@@ -1077,11 +1036,10 @@ class Channel(models.Model):
self.add_members(self.env.user.partner_id.ids)
@api.model
- def channel_create(self, name, group_id, privacy='groups'):
+ def channel_create(self, name, group_id):
""" Create a channel and add the current partner, broadcast it (to make the user directly
listen to it when polling)
:param name : the name of the channel to create
- :param privacy : privacy of the channel. Should be 'public', 'private' or 'groups'.
:param group_id : the group allowed to join the channel.
:return dict : channel header
"""
@@ -1089,7 +1047,6 @@ class Channel(models.Model):
vals = {
'channel_type': 'channel',
'name': name,
- 'public': privacy,
}
new_channel = self.create(vals)
group = self.env['res.groups'].search([('id', '=', group_id)]) if group_id else None
@@ -1115,33 +1072,29 @@ class Channel(models.Model):
'channel_type': 'group',
'default_display_mode': default_display_mode,
'name': name,
- 'public': 'private',
})
channel._broadcast(partners_to)
return channel.channel_info()[0]
@api.model
def get_mention_suggestions(self, search, limit=8):
- """ Return 'limit'-first channels' id, name and public fields such that the name matches a
- 'search' string. Exclude channels of type chat (DM), and private channels the current
- user isn't registered to. """
+ """ Return 'limit'-first channels' id, name, channel_type and authorizedGroupFullName fields such that the
+ name matches a 'search' string. Exclude channels of type chat (DM) and group.
+ """
domain = expression.AND([
[('name', 'ilike', search)],
[('channel_type', '=', 'channel')],
- expression.OR([
- [('public', '!=', 'private')],
- [('channel_partner_ids', 'in', [self.env.user.partner_id.id])]
- ])
+ [('channel_partner_ids', 'in', [self.env.user.partner_id.id])]
])
channels = self.search(domain, limit=limit)
return [{
+ 'authorizedGroupFullName': channel.group_public_id.full_name,
'channel': {
'channel_type': channel.channel_type,
'id': channel.id,
},
'id': channel.id,
'name': channel.name,
- 'public': channel.public,
} for channel in channels]
def channel_fetch_preview(self):
@@ -1208,8 +1161,6 @@ class Channel(models.Model):
partner = self.env.user.partner_id
if self.channel_type == 'channel':
msg = _("You are in channel #%s.", self.name)
- if self.public == 'private':
- msg += _(" This channel is private. People must be invited to join it.")
else:
all_channel_members = self.env['mail.channel.member'].with_context(active_test=False)
channel_members = all_channel_members.search([('partner_id', '!=', partner.id), ('channel_id', '=', self.id)])
diff --git a/addons/mail/models/mail_channel_member.py b/addons/mail/models/mail_channel_member.py
index 842f40246ac..3df2841f661 100644
--- a/addons/mail/models/mail_channel_member.py
+++ b/addons/mail/models/mail_channel_member.py
@@ -12,6 +12,7 @@ class ChannelMember(models.Model):
_description = 'Listeners of a Channel'
_table = 'mail_channel_member'
_rec_names_search = ['partner_id', 'guest_id']
+ _bypass_create_check = {}
# identity
partner_id = fields.Many2one('res.partner', string='Recipient', ondelete='cascade', index=True)
@@ -75,7 +76,7 @@ class ChannelMember(models.Model):
partner will be added in the channel and the security rule will always authorize
the creation.
"""
- if not self.env.is_admin():
+ if not self.env.is_admin() and not self.env.context.get('mail_create_bypass_create_check') is self._bypass_create_check:
for vals in vals_list:
if 'channel_id' in vals:
channel_id = self.env['mail.channel'].browse(vals['channel_id'])
diff --git a/addons/mail/models/res_partner.py b/addons/mail/models/res_partner.py
index ab16d9093b9..8791059b145 100644
--- a/addons/mail/models/res_partner.py
+++ b/addons/mail/models/res_partner.py
@@ -186,7 +186,7 @@ class Partner(models.Model):
if channel_id:
channel = self.env['mail.channel'].search([('id', '=', int(channel_id))])
domain = expression.AND([domain, [('channel_ids', 'not in', channel.id)]])
- if channel.public == 'groups':
+ if channel.group_public_id:
domain = expression.AND([domain, [('user_ids.groups_id', 'in', channel.group_public_id.id)]])
query = self.env['res.partner']._search(domain, order='name, id')
query.order = 'LOWER("res_partner"."name"), "res_partner"."id"' # bypass lack of support for case insensitive order in search()
diff --git a/addons/mail/models/res_users.py b/addons/mail/models/res_users.py
index 714c5c5de20..1d460df266b 100644
--- a/addons/mail/models/res_users.py
+++ b/addons/mail/models/res_users.py
@@ -128,8 +128,8 @@ class Users(models.Model):
return super().unlink()
def _unsubscribe_from_non_public_channels(self):
- """ This method un-subscribes users from private mail channels. Main purpose of this
- method is to prevent sending internal communication to archived / deleted users.
+ """ This method un-subscribes users from group restricted channels. Main purpose
+ of this method is to prevent sending internal communication to archived / deleted users.
We do not un-subscribes users from public channels because in most common cases,
public channels are mailing list (e-mail based) and so users should always receive
updates from public channels until they manually un-subscribe themselves.
@@ -138,7 +138,7 @@ class Users(models.Model):
('partner_id', 'in', self.partner_id.ids),
])
current_cm.filtered(
- lambda cm: cm.channel_id.public != 'public' and cm.channel_id.channel_type == 'channel'
+ lambda cm: (cm.channel_id.channel_type == 'channel' and cm.channel_id.group_public_id)
).unlink()
def _get_portal_access_update_body(self, access_granted):
diff --git a/addons/mail/security/mail_security.xml b/addons/mail/security/mail_security.xml
index 8a47ad2b406..d924f1aa0e1 100644
--- a/addons/mail/security/mail_security.xml
+++ b/addons/mail/security/mail_security.xml
@@ -6,10 +6,17 @@
Mail.channel: access only public and joined groups
- ['|', '|',
-('public', '=', 'public'),
-'&', ('public', '=', 'private'), ('is_member', '=', True),
-'&', ('public', '=', 'groups'), ('group_public_id', 'in', [g.id for g in user.groups_id])]
+ [
+ '|',
+ '&',
+ ('channel_type', '!=', 'channel'),
+ ('is_member', '=', True),
+ '&',
+ ('channel_type', '=', 'channel'),
+ '|',
+ ('group_public_id', '=', False),
+ ('group_public_id', 'in', [g.id for g in user.groups_id])]
+
@@ -24,10 +31,17 @@
mail.channel.member: write its own entries
- ['|', '|',
-('channel_id.public', '=', 'public'),
-'&', ('channel_id.public', '=', 'private'), ('channel_id.is_member', '=', True),
-'&', ('channel_id.public', '=', 'groups'), ('channel_id.group_public_id', 'in', [g.id for g in user.groups_id])]
+ [
+ '|',
+ '&',
+ ('channel_id.channel_type', '!=', 'channel'),
+ ('channel_id.is_member', '=', True),
+ '&',
+ ('channel_id.channel_type', '=', 'channel'),
+ '|',
+ ('channel_id.group_public_id', '=', False),
+ ('channel_id.group_public_id', 'in', [g.id for g in user.groups_id])]
+
diff --git a/addons/mail/static/src/components/thread_icon/thread_icon.xml b/addons/mail/static/src/components/thread_icon/thread_icon.xml
index 0a395c29992..b67fc0296cb 100644
--- a/addons/mail/static/src/components/thread_icon/thread_icon.xml
+++ b/addons/mail/static/src/components/thread_icon/thread_icon.xml
@@ -5,14 +5,11 @@
-
-
+
+
-
-
-
-
-
+
+
diff --git a/addons/mail/static/src/models/channel_invitation_form.js b/addons/mail/static/src/models/channel_invitation_form.js
index 76171838701..9cd2f57be3e 100644
--- a/addons/mail/static/src/models/channel_invitation_form.js
+++ b/addons/mail/static/src/models/channel_invitation_form.js
@@ -166,10 +166,7 @@ registerModel({
if (!this.thread) {
return clear();
}
- if (
- !this.thread.authorizedGroupFullName ||
- this.thread.public !== 'groups'
- ) {
+ if (!this.thread.authorizedGroupFullName) {
return clear();
}
return sprintf(
diff --git a/addons/mail/static/src/models/discuss.js b/addons/mail/static/src/models/discuss.js
index 715eaa16215..eb92377c87f 100644
--- a/addons/mail/static/src/models/discuss.js
+++ b/addons/mail/static/src/models/discuss.js
@@ -38,11 +38,10 @@ registerModel({
ev.preventDefault();
const name = this.addingChannelValue;
this.clearIsAddingItem();
- if (ui.item.special) {
+ if (ui.item.create) {
const channel = await this.messaging.models['Thread'].performRpcCreateChannel({
name,
- group_id: ui.item.special === 'private' ? false : this.messaging.internalUserGroupId,
- privacy: ui.item.special === 'private' ? 'private' : 'groups',
+ group_id: this.messaging.internalUserGroupId,
});
channel.open();
} else {
@@ -77,19 +76,12 @@ registerModel({
// XDU FIXME could use a component but be careful with owl's
// renderToString https://github.com/odoo/owl/issues/708
items.push({
+ create: true,
+ escapedValue,
label: sprintf(
`${this.env._t('Create %s')}`,
`${escapedValue}`,
),
- escapedValue,
- special: 'public'
- }, {
- label: sprintf(
- `${this.env._t('Create %s')}`,
- `${escapedValue}`,
- ),
- escapedValue,
- special: 'private'
});
res(items);
},
diff --git a/addons/mail/static/src/models/discuss_sidebar_category.js b/addons/mail/static/src/models/discuss_sidebar_category.js
index 825c4b411d4..bf1ef6fd58c 100644
--- a/addons/mail/static/src/models/discuss_sidebar_category.js
+++ b/addons/mail/static/src/models/discuss_sidebar_category.js
@@ -314,7 +314,7 @@ registerModel({
type: 'ir.actions.act_window',
res_model: 'mail.channel',
views: [[false, 'kanban'], [false, 'form']],
- domain: [['public', '!=', 'private']],
+ domain: [['channel_type', '=', 'channel']],
});
},
/**
diff --git a/addons/mail/static/src/models/discuss_sidebar_category_item.js b/addons/mail/static/src/models/discuss_sidebar_category_item.js
index 918d7b33e6c..01b8147458c 100644
--- a/addons/mail/static/src/models/discuss_sidebar_category_item.js
+++ b/addons/mail/static/src/models/discuss_sidebar_category_item.js
@@ -109,7 +109,7 @@ registerModel({
}
switch (this.channel.channel_type) {
case 'channel':
- return ['private', 'public'].includes(this.thread.public);
+ return !Boolean(this.thread.authorizedGroupFullName);
case 'chat':
return true;
case 'group':
diff --git a/addons/mail/static/src/models/partner.js b/addons/mail/static/src/models/partner.js
index 3d680c99c7c..990b7186bee 100644
--- a/addons/mail/static/src/models/partner.js
+++ b/addons/mail/static/src/models/partner.js
@@ -19,7 +19,7 @@ registerModel({
*/
async fetchSuggestions(searchTerm, { thread } = {}) {
const kwargs = { search: searchTerm };
- const isNonPublicChannel = thread && thread.model === 'mail.channel' && thread.public !== 'public';
+ const isNonPublicChannel = thread && thread.model === 'mail.channel' && (thread.authorizedGroupFullName || thread.channel.channel_type !== 'channel');
if (isNonPublicChannel) {
kwargs.channel_id = thread.id;
}
@@ -153,10 +153,10 @@ registerModel({
*/
searchSuggestions(searchTerm, { thread } = {}) {
let partners;
- const isNonPublicChannel = thread && thread.channel && thread.public !== 'public';
+ const isNonPublicChannel = thread && thread.channel && (thread.authorizedGroupFullName || thread.channel.channel_type !== 'channel');
if (isNonPublicChannel) {
// Only return the channel members when in the context of a
- // non-public channel. Indeed, the message with the mention
+ // group restricted channel. Indeed, the message with the mention
// would be notified to the mentioned partner, so this prevents
// from inadvertently leaking the private message to the
// mentioned partner.
diff --git a/addons/mail/static/src/models/thread.js b/addons/mail/static/src/models/thread.js
index d4c4b0a4a91..16423bfe20c 100644
--- a/addons/mail/static/src/models/thread.js
+++ b/addons/mail/static/src/models/thread.js
@@ -96,9 +96,6 @@ registerModel({
if ('name' in data) {
data2.name = data.name;
}
- if ('public' in data) {
- data2.public = data.public;
- }
if ('seen_message_id' in data) {
data2.rawLastSeenByCurrentPartnerMessageId = data.seen_message_id;
}
@@ -206,12 +203,12 @@ registerModel({
getSuggestionSortFunction(searchTerm, { thread } = {}) {
const cleanedSearchTerm = cleanSearchTerm(searchTerm);
return (a, b) => {
- const isAPublic = a.model === 'mail.channel' && a.public === 'public';
- const isBPublic = b.model === 'mail.channel' && b.public === 'public';
- if (isAPublic && !isBPublic) {
+ const isAPublicChannel = a.model === 'mail.channel' && a.channel.channel_type === 'channel' && (!a.authorizedGroupFullName);
+ const isBPublicChannel = b.model === 'mail.channel' && b.channel.channel_type === 'channel' && (!b.authorizedGroupFullName);
+ if (isAPublicChannel && !isBPublicChannel) {
return -1;
}
- if (!isAPublic && isBPublic) {
+ if (!isAPublicChannel && isBPublicChannel) {
return 1;
}
const isMemberOfA = a.channel && a.channel.memberOfCurrentUser;
@@ -336,14 +333,14 @@ registerModel({
*
* @param {Object} param0
* @param {string} param0.name
- * @param {string} [param0.privacy]
+ * @param {integer} param0.group_id
* @returns {Thread} the created channel
*/
- async performRpcCreateChannel({ name, group_id, privacy }) {
+ async performRpcCreateChannel({ name, group_id }) {
const data = await this.messaging.rpc({
model: 'mail.channel',
method: 'channel_create',
- args: [name, group_id, privacy],
+ args: [name, group_id],
});
return this.messaging.models['Thread'].insert(
this.messaging.models['Thread'].convertData(data)
@@ -396,9 +393,9 @@ registerModel({
*/
searchSuggestions(searchTerm, { thread } = {}) {
let threads;
- if (thread && thread.model === 'mail.channel' && thread.public !== 'public') {
+ if (thread && thread.model === 'mail.channel' && (thread.channel.channel_type !== 'channel' || (thread.channel.channel_type === 'channel' && thread.authorizedGroupFullName))) {
// Only return the current channel when in the context of a
- // non-public channel. Indeed, the message with the mention
+ // group restricted channel or group or chat. Indeed, the message with the mention
// would appear in the target channel, so this prevents from
// inadvertently leaking the private message into the mentioned
// channel.
@@ -974,6 +971,19 @@ registerModel({
this.messaging.chatWindowManager.closeThread(this);
this.unpin();
},
+ /**
+ * @private
+ * @returns {string|FieldCommand}
+ */
+ _computeAccessRestrictedToGroupText() {
+ if (!this.authorizedGroupFullName) {
+ return clear();
+ }
+ return sprintf(
+ this.env._t('Access restricted to group "%(groupFullName)s"'),
+ { 'groupFullName': this.authorizedGroupFullName }
+ );
+ },
/**
* @private
* @returns {Attachment[]}
@@ -1547,6 +1557,10 @@ registerModel({
},
},
fields: {
+ accessRestrictedToGroupText: attr({
+ compute: '_computeAccessRestrictedToGroupText',
+ default: '',
+ }),
/**
* Determines the `mail.activity` that belong to `this`, assuming `this`
* has activities (@see hasActivities).
@@ -1993,7 +2007,6 @@ registerModel({
* server.
*/
pendingSeenMessageId: attr(),
- public: attr(),
rawLastSeenByCurrentPartnerMessageId: attr({
default: 0,
}),
diff --git a/addons/mail/static/tests/helpers/mock_server.js b/addons/mail/static/tests/helpers/mock_server.js
index bc671b6485c..744990ab00f 100644
--- a/addons/mail/static/tests/helpers/mock_server.js
+++ b/addons/mail/static/tests/helpers/mock_server.js
@@ -989,7 +989,6 @@ patch(MockServer.prototype, 'mail', {
}]),
channel_type: 'chat',
name: partners.map(partner => partner.name).join(", "),
- public: 'private',
});
return this._mockMailChannelChannelInfo([id])[0];
},
@@ -1174,7 +1173,6 @@ patch(MockServer.prototype, 'mail', {
channel_type: 'group',
channel_member_ids: partners.map(partner => [0, 0, { partner_id: partner.id }]),
name: '',
- public: 'private',
});
this._mockMailChannel_broadcast(id, partners.map(partner => partner.id));
return this._mockMailChannelChannelInfo([id])[0];
@@ -1251,13 +1249,13 @@ patch(MockServer.prototype, 'mail', {
}).map(channel => {
// expected format
return {
+ authorizedGroupFullName: channel.group_public_id ? channel.group_public_id.name : false,
channel: {
channel_type: channel.channel_type,
id: channel.id,
},
id: channel.id,
name: channel.name,
- public: channel.public,
};
});
// reduce results to max limit
diff --git a/addons/mail/static/tests/qunit_suite_tests/components/channel_invitation_form_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/channel_invitation_form_tests.js
index 9abc0f2c5b7..82a53e06923 100644
--- a/addons/mail/static/tests/qunit_suite_tests/components/channel_invitation_form_tests.js
+++ b/addons/mail/static/tests/qunit_suite_tests/components/channel_invitation_form_tests.js
@@ -24,7 +24,6 @@ QUnit.test('should display the channel invitation form after clicking on the inv
[0, 0, { partner_id: resPartnerId1 }],
],
channel_type: 'chat',
- public: 'private',
});
const { click, openDiscuss } = await start({
discuss: {
@@ -62,7 +61,6 @@ QUnit.test('should be able to search for a new user to invite from an existing c
[0, 0, { partner_id: resPartnerId1 }],
],
channel_type: 'chat',
- public: 'private',
});
const { click, insertText, openDiscuss } = await start({
discuss: {
@@ -101,7 +99,6 @@ QUnit.test('should be able to create a new group chat from an existing chat', as
[0, 0, { partner_id: resPartnerId1 }],
],
channel_type: 'chat',
- public: 'private',
});
const { click, insertText, openDiscuss } = await start({
discuss: {
@@ -140,7 +137,6 @@ QUnit.test('Invitation form should display channel group restriction', async fun
[0, 0, { partner_id: pyEnv.currentPartnerId }],
],
channel_type: 'channel',
- public: 'groups',
group_public_id: resGroupId1,
});
const { click, openDiscuss } = await start({
diff --git a/addons/mail/static/tests/qunit_suite_tests/components/channel_member_list_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/channel_member_list_tests.js
index 0b068c79e8c..fc818ca05dd 100644
--- a/addons/mail/static/tests/qunit_suite_tests/components/channel_member_list_tests.js
+++ b/addons/mail/static/tests/qunit_suite_tests/components/channel_member_list_tests.js
@@ -20,7 +20,6 @@ QUnit.test('there should be a button to show member list in the thread view topb
[0, 0, { partner_id: resPartnerId1 }],
],
channel_type: 'group',
- public: 'private',
});
const { openDiscuss } = await start({
discuss: {
@@ -48,7 +47,6 @@ QUnit.test('should show member list when clicking on show member list button in
[0, 0, { partner_id: resPartnerId1 }],
],
channel_type: 'group',
- public: 'private',
});
const { click, openDiscuss } = await start({
discuss: {
@@ -77,7 +75,6 @@ QUnit.test('should have correct members in member list', async function (assert)
[0, 0, { partner_id: resPartnerId1 }],
],
channel_type: 'group',
- public: 'private',
});
const { click, openDiscuss } = await start({
discuss: {
@@ -117,7 +114,6 @@ QUnit.test('there should be a button to hide member list in the thread view topb
[0, 0, { partner_id: resPartnerId1 }],
],
channel_type: 'group',
- public: 'private',
});
const { click, openDiscuss } = await start({
discuss: {
diff --git a/addons/mail/static/tests/qunit_suite_tests/components/chat_window_manager_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/chat_window_manager_tests.js
index 3ee17f98183..5881011f51c 100644
--- a/addons/mail/static/tests/qunit_suite_tests/components/chat_window_manager_tests.js
+++ b/addons/mail/static/tests/qunit_suite_tests/components/chat_window_manager_tests.js
@@ -335,7 +335,6 @@ QUnit.test('new message chat window should close on selecting the user if chat w
],
channel_type: "chat",
name: "Partner 131",
- public: 'private',
});
const { afterEvent, click } = await start();
diff --git a/addons/mail/static/tests/qunit_suite_tests/components/composer_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/composer_tests.js
index 7fa7300d568..d726142d6f2 100644
--- a/addons/mail/static/tests/qunit_suite_tests/components/composer_tests.js
+++ b/addons/mail/static/tests/qunit_suite_tests/components/composer_tests.js
@@ -403,7 +403,7 @@ QUnit.test('display channel mention suggestions on typing "#"', async function (
assert.expect(2);
const pyEnv = await startServer();
- const mailChanelId1 = pyEnv['mail.channel'].create({ name: "General", public: "groups" });
+ const mailChanelId1 = pyEnv['mail.channel'].create({ name: "General", channel_type: 'channel' });
const { insertText, openDiscuss } = await start({
discuss: {
context: { active_id: mailChanelId1 },
@@ -428,7 +428,7 @@ QUnit.test('mention a channel', async function (assert) {
assert.expect(4);
const pyEnv = await startServer();
- const mailChanelId1 = pyEnv['mail.channel'].create({ name: "General", public: "groups" });
+ const mailChanelId1 = pyEnv['mail.channel'].create({ name: "General", channel_type: 'channel' });
const { click, insertText, openDiscuss } = await start({
discuss: {
context: { active_id: mailChanelId1 },
@@ -464,7 +464,7 @@ QUnit.test('mention a channel after some text', async function (assert) {
assert.expect(5);
const pyEnv = await startServer();
- const mailChanelId1 = pyEnv['mail.channel'].create({ name: "General", public: "groups" });
+ const mailChanelId1 = pyEnv['mail.channel'].create({ name: "General", channel_type: 'channel' });
const { click, insertText, openDiscuss } = await start({
discuss: {
context: { active_id: mailChanelId1 },
@@ -506,7 +506,7 @@ QUnit.test('add an emoji after a channel mention', async function (assert) {
assert.expect(5);
const pyEnv = await startServer();
- const mailChanelId1 = pyEnv['mail.channel'].create({ name: "General", public: "groups" });
+ const mailChanelId1 = pyEnv['mail.channel'].create({ name: "General", channel_type: 'channel' });
const { click, insertText, openDiscuss } = await start({
discuss: {
context: { active_id: mailChanelId1 },
diff --git a/addons/mail/static/tests/qunit_suite_tests/components/discuss_pinned_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/discuss_pinned_tests.js
index 08f285ef8ca..d19808872f7 100644
--- a/addons/mail/static/tests/qunit_suite_tests/components/discuss_pinned_tests.js
+++ b/addons/mail/static/tests/qunit_suite_tests/components/discuss_pinned_tests.js
@@ -120,11 +120,7 @@ QUnit.test('sidebar: unpin channel from bus', async function (assert) {
// (e.g. from user interaction from another device or browser tab)
await afterNextRender(() => {
pyEnv['bus.bus']._sendone(pyEnv.currentPartner, 'mail.channel/unpin', {
- 'channel_type': 'channel',
'id': mailChannelId1,
- 'name': "General",
- 'public': 'public',
- 'state': 'open',
});
});
assert.containsOnce(
diff --git a/addons/mail/static/tests/qunit_suite_tests/components/discuss_sidebar_category_item_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/discuss_sidebar_category_item_tests.js
index a3cf39cb226..b7c6a5a4f20 100644
--- a/addons/mail/static/tests/qunit_suite_tests/components/discuss_sidebar_category_item_tests.js
+++ b/addons/mail/static/tests/qunit_suite_tests/components/discuss_sidebar_category_item_tests.js
@@ -82,7 +82,6 @@ QUnit.test('chat - avatar: should have correct avatar', async function (assert)
[0, 0, { partner_id: resPartnerId1 }],
],
channel_type: 'chat',
- public: 'private',
});
const { openDiscuss } = await start();
await openDiscuss();
@@ -114,7 +113,6 @@ QUnit.test('chat - sorting: should be sorted by last activity time', async funct
partner_id: pyEnv.currentPartnerId,
}]],
channel_type: 'chat',
- public: 'private',
},
{
channel_member_ids: [[0, 0, {
@@ -122,7 +120,6 @@ QUnit.test('chat - sorting: should be sorted by last activity time', async funct
partner_id: pyEnv.currentPartnerId,
}]],
channel_type: 'chat',
- public: 'private',
},
]);
const { click, openDiscuss } = await start();
diff --git a/addons/mail/static/tests/qunit_suite_tests/components/discuss_sidebar_category_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/discuss_sidebar_category_tests.js
index d4dc0fed57e..7ea799643e1 100644
--- a/addons/mail/static/tests/qunit_suite_tests/components/discuss_sidebar_category_tests.js
+++ b/addons/mail/static/tests/qunit_suite_tests/components/discuss_sidebar_category_tests.js
@@ -401,7 +401,6 @@ QUnit.test('chat - counter: should not have a counter if the category is unfolde
}],
],
channel_type: 'chat',
- public: 'private',
});
const { openDiscuss } = await start();
@@ -425,7 +424,6 @@ QUnit.test('chat - counter: should not have a counter if the category is unfolde
}],
],
channel_type: 'chat',
- public: 'private',
});
const { openDiscuss } = await start();
await openDiscuss();
@@ -448,7 +446,6 @@ QUnit.test('chat - counter: should not have a counter if category is folded and
}],
],
channel_type: 'chat',
- public: 'private',
});
const { click, openDiscuss } = await start();
await openDiscuss();
@@ -473,7 +470,6 @@ QUnit.test('chat - counter: should have correct value of unread threads if categ
}],
],
channel_type: 'chat',
- public: 'private',
},
{
channel_member_ids: [
@@ -483,7 +479,6 @@ QUnit.test('chat - counter: should have correct value of unread threads if categ
}],
],
channel_type: 'chat',
- public: 'private',
},
]);
const { click, openDiscuss } = await start();
@@ -532,7 +527,6 @@ QUnit.test('chat - states: close manually by clicking the title', async function
const pyEnv = await startServer();
const mailChannelId1 = pyEnv['mail.channel'].create({
channel_type: 'chat',
- public: 'private',
});
pyEnv['res.users.settings'].create({
user_id: pyEnv.currentUserId,
@@ -554,7 +548,6 @@ QUnit.test('chat - states: open manually by clicking the title', async function
const pyEnv = await startServer();
const mailChannelId1 = pyEnv['mail.channel'].create({
channel_type: 'chat',
- public: 'private',
});
pyEnv['res.users.settings'].create({
user_id: pyEnv.currentUserId,
@@ -649,7 +642,6 @@ QUnit.test('chat - states: close from the bus', async function (assert) {
const pyEnv = await startServer();
const mailChannelId1 = pyEnv['mail.channel'].create({
channel_type: 'chat',
- public: 'private',
});
const resUsersSettingsId1 = pyEnv['res.users.settings'].create({
user_id: pyEnv.currentUserId,
@@ -677,7 +669,6 @@ QUnit.test('chat - states: open from the bus', async function (assert) {
const pyEnv = await startServer();
const mailChannelId1 = pyEnv['mail.channel'].create({
channel_type: 'chat',
- public: 'private',
});
const resUsersSettingsId1 = pyEnv['res.users.settings'].create({
user_id: pyEnv.currentUserId,
@@ -705,7 +696,6 @@ QUnit.test('chat - states: the active category item should be visible even if th
const pyEnv = await startServer();
const mailChannelId1 = pyEnv['mail.channel'].create({
channel_type: 'chat',
- public: 'private',
});
const { click, messaging, openDiscuss } = await start();
await openDiscuss();
diff --git a/addons/mail/static/tests/qunit_suite_tests/components/discuss_sidebar_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/discuss_sidebar_tests.js
index da15ec803fb..21ab78fd686 100644
--- a/addons/mail/static/tests/qunit_suite_tests/components/discuss_sidebar_tests.js
+++ b/addons/mail/static/tests/qunit_suite_tests/components/discuss_sidebar_tests.js
@@ -18,8 +18,8 @@ QUnit.test('sidebar find shows channels matching search term', async function (a
pyEnv['mail.channel'].create({
channel_member_ids: [],
channel_type: 'channel',
+ group_public_id: false,
name: 'test',
- public: 'public',
});
const searchReadDef = makeDeferred();
const { click, openDiscuss } = await start({
@@ -47,11 +47,10 @@ QUnit.test('sidebar find shows channels matching search term', async function (a
);
assert.strictEqual(
results.length,
- // When searching for a single existing channel, the results list will have at least 3 lines:
+ // When searching for a single existing channel, the results list will have at least 2 lines:
// One for the existing channel itself
- // One for creating a public channel with the search term
- // One for creating a private channel with the search term
- 3
+ // One for creating a channel with the search term
+ 2
);
assert.strictEqual(
results[0].textContent,
@@ -69,8 +68,8 @@ QUnit.test('sidebar find shows channels matching search term even when user is m
[0, 0, { partner_id: pyEnv.currentPartnerId }],
],
channel_type: 'channel',
+ group_public_id: false,
name: 'test',
- public: 'public',
});
const searchReadDef = makeDeferred();
const { click, openDiscuss } = await start({
@@ -98,11 +97,10 @@ QUnit.test('sidebar find shows channels matching search term even when user is m
);
assert.strictEqual(
results.length,
- // When searching for a single existing channel, the results list will have at least 3 lines:
+ // When searching for a single existing channel, the results list will have at least 2 lines:
// One for the existing channel itself
- // One for creating a public channel with the search term
- // One for creating a private channel with the search term
- 3
+ // One for creating a channel with the search term
+ 2
);
assert.strictEqual(
results[0].textContent,
diff --git a/addons/mail/static/tests/qunit_suite_tests/components/discuss_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/discuss_tests.js
index e47387529a0..8916485236f 100644
--- a/addons/mail/static/tests/qunit_suite_tests/components/discuss_tests.js
+++ b/addons/mail/static/tests/qunit_suite_tests/components/discuss_tests.js
@@ -535,20 +535,19 @@ QUnit.test('sidebar: channel rendering with needaction counter', async function
);
});
-QUnit.test('sidebar: public/private channel rendering', async function (assert) {
- assert.expect(5);
+QUnit.test('sidebar: public channel rendering', async function (assert) {
+ assert.expect(3);
const pyEnv = await startServer();
- const [mailChannelId1, mailChannelId2] = pyEnv['mail.channel'].create([
- { name: "channel1", public: 'public' },
- { name: "channel2", public: 'private' },
+ const mailChannelId1 = pyEnv['mail.channel'].create([
+ { name: "channel1", channel_type: 'channel', group_public_id: false},
]);
const { openDiscuss } = await start();
await openDiscuss();
assert.strictEqual(
document.querySelectorAll(`.o_DiscussSidebar_categoryChannel .o_DiscussSidebarCategory_item`).length,
- 2,
- "should have 2 channel items"
+ 1,
+ "should have 1 channel items"
);
assert.strictEqual(
document.querySelectorAll(`
@@ -558,31 +557,14 @@ QUnit.test('sidebar: public/private channel rendering', async function (assert)
1,
"should have channel 1"
);
- assert.strictEqual(
- document.querySelectorAll(`
- .o_DiscussSidebar_categoryChannel
- .o_DiscussSidebarCategory_item[data-channel-id="${mailChannelId2}"]
- `).length,
- 1,
- "should have channel 2"
- );
const channel1 = document.querySelector(`
.o_DiscussSidebar_categoryChannel
.o_DiscussSidebarCategory_item[data-channel-id="${mailChannelId1}"]
`);
- const channel2 = document.querySelector(`
- .o_DiscussSidebar_categoryChannel
- .o_DiscussSidebarCategory_item[data-channel-id="${mailChannelId2}"]
- `);
assert.ok(
- channel1.querySelectorAll(`:scope .o_ThreadIcon_channelPublic`).length,
+ channel1.querySelectorAll(`:scope .o_ThreadIcon_publicChannel`).length,
"channel1 (public) should have globe icon"
);
- assert.strictEqual(
- channel2.querySelectorAll(`:scope .o_ThreadIcon_channelPrivate`).length,
- 1,
- "channel2 (private) has lock icon"
- );
});
QUnit.test('sidebar: basic chat rendering', async function (assert) {
@@ -596,7 +578,6 @@ QUnit.test('sidebar: basic chat rendering', async function (assert) {
[0, 0, { partner_id: resPartnerId1 }],
],
channel_type: 'chat', // testing a chat is the goal of the test
- public: 'private', // expected value for testing a chat
});
const { openDiscuss } = await start();
await openDiscuss();
@@ -658,7 +639,6 @@ QUnit.test('sidebar: chat rendering with unread counter', async function (assert
}],
],
channel_type: 'chat',
- public: 'private',
});
const { openDiscuss } = await start();
await openDiscuss();
@@ -701,7 +681,6 @@ QUnit.test('sidebar: chat im_status rendering', async function (assert) {
[0, 0, { partner_id: resPartnerId1 }],
],
channel_type: 'chat',
- public: 'private',
},
{
channel_member_ids: [
@@ -709,7 +688,6 @@ QUnit.test('sidebar: chat im_status rendering', async function (assert) {
[0, 0, { partner_id: resPartnerId2 }],
],
channel_type: 'chat',
- public: 'private',
},
{
channel_member_ids: [
@@ -717,7 +695,6 @@ QUnit.test('sidebar: chat im_status rendering', async function (assert) {
[0, 0, { partner_id: resPartnerId3 }],
],
channel_type: 'chat',
- public: 'private',
}
]);
const { openDiscuss } = await start();
@@ -794,7 +771,6 @@ QUnit.test('sidebar: chat custom name', async function (assert) {
[0, 0, { partner_id: resPartnerId1 }],
],
channel_type: 'chat',
- public: 'private',
});
const { openDiscuss } = await start();
await openDiscuss();
@@ -1947,7 +1923,6 @@ QUnit.test('redirect to author (open chat)', async function (assert) {
[0, 0, { partner_id: resPartnerId1 }],
],
channel_type: 'chat',
- public: 'private',
}
]);
const mailMessageId1 = pyEnv['mail.message'].create(
@@ -3445,8 +3420,8 @@ QUnit.test('receive new chat messages: out of odoo focus (tab title)', async fun
let step = 0;
const pyEnv = await startServer();
const [mailChannelId1, mailChannelId2] = pyEnv['mail.channel'].create([
- { channel_type: 'chat', public: 'private' },
- { channel_type: 'chat', public: 'private' },
+ { channel_type: 'chat' },
+ { channel_type: 'chat' },
]);
const { env, openDiscuss } = await start({
services: {
@@ -3524,7 +3499,6 @@ QUnit.test('auto-focus composer on opening thread', async function (assert) {
[0, 0, { partner_id: resPartnerId1 }],
],
channel_type: 'chat',
- public: 'private',
}
]);
const { click, openDiscuss } = await start();
diff --git a/addons/mail/static/tests/qunit_suite_tests/components/message_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/message_tests.js
index ba623813aa7..2887d980ce5 100644
--- a/addons/mail/static/tests/qunit_suite_tests/components/message_tests.js
+++ b/addons/mail/static/tests/qunit_suite_tests/components/message_tests.js
@@ -943,7 +943,6 @@ QUnit.test('open chat with author on avatar click should be disabled when curren
[0, 0, { partner_id: resPartnerId }],
],
channel_type: 'chat',
- public: 'private',
});
pyEnv['mail.message'].create({
author_id: resPartnerId,
diff --git a/addons/mail/static/tests/qunit_suite_tests/components/thread_view_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/thread_view_tests.js
index 19679bb0f96..99b5b503a6e 100644
--- a/addons/mail/static/tests/qunit_suite_tests/components/thread_view_tests.js
+++ b/addons/mail/static/tests/qunit_suite_tests/components/thread_view_tests.js
@@ -18,8 +18,8 @@ QUnit.test('dragover files on thread with composer', async function (assert) {
const pyEnv = await startServer();
const mailChannelId1 = pyEnv['mail.channel'].create({
channel_type: 'channel',
+ group_public_id: false,
name: "General",
- public: 'public',
});
const { openDiscuss } = await start({
discuss: {
@@ -42,8 +42,8 @@ QUnit.test('message list asc order', async function (assert) {
const pyEnv = await startServer();
const mailChannelId1 = pyEnv['mail.channel'].create({
channel_type: 'channel',
+ group_public_id: false,
name: "General",
- public: 'public',
});
for (let i = 0; i <= 60; i++) {
pyEnv['mail.message'].create({
@@ -258,8 +258,8 @@ QUnit.test('show message subject when subject is not the same as the thread name
const pyEnv = await startServer();
const mailChannelId1 = pyEnv['mail.channel'].create({
channel_type: 'channel',
+ group_public_id: false,
name: "General",
- public: 'public',
});
pyEnv['mail.message'].create({
body: "not empty",
@@ -296,8 +296,8 @@ QUnit.test('do not show message subject when subject is the same as the thread n
const pyEnv = await startServer();
const mailChannelId1 = pyEnv['mail.channel'].create({
channel_type: 'channel',
+ group_public_id: false,
name: "Salutations, voyageur",
- public: 'public',
});
pyEnv['mail.message'].create({
body: "not empty",
@@ -1089,10 +1089,12 @@ QUnit.test('mention 2 different channels that have the same name', async functio
const pyEnv = await startServer();
const [mailChannelId1, mailChannelId2] = pyEnv['mail.channel'].create([
{
+ channel_type: 'channel',
+ group_public_id: false,
name: "my channel",
- public: 'public', // mentioning another channel is possible only from a public channel
},
{
+ channel_type: 'channel',
name: "my channel",
},
]);
diff --git a/addons/mail/static/tests/qunit_suite_tests/models/messaging_tests.js b/addons/mail/static/tests/qunit_suite_tests/models/messaging_tests.js
index d4015c16d31..4e33bd00b75 100644
--- a/addons/mail/static/tests/qunit_suite_tests/models/messaging_tests.js
+++ b/addons/mail/static/tests/qunit_suite_tests/models/messaging_tests.js
@@ -87,7 +87,6 @@ QUnit.test('openChat: open existing chat for user', async function (assert) {
[0, 0, { partner_id: resPartnerId1 }],
],
channel_type: "chat",
- public: 'private',
});
const { messaging } = await start();
const existingChat = messaging.models['Partner'].findFromIdentifyingData({ id: resPartnerId1 }).dmChatWithCurrentPartner;
diff --git a/addons/mail/tests/test_link_preview.py b/addons/mail/tests/test_link_preview.py
index d45697a4df3..7342afc43f9 100644
--- a/addons/mail/tests/test_link_preview.py
+++ b/addons/mail/tests/test_link_preview.py
@@ -43,7 +43,6 @@ class TestLinkPreview(MailCommon):
cls.public_channel = cls.env['mail.channel'].create({
'name': 'Public channel of user 1',
- 'public': 'public',
'channel_type': 'channel',
})
cls.public_channel.channel_member_ids.unlink()
diff --git a/addons/mail/tests/test_mail_channel.py b/addons/mail/tests/test_mail_channel.py
index 8b8a7214e7c..7a364163d03 100644
--- a/addons/mail/tests/test_mail_channel.py
+++ b/addons/mail/tests/test_mail_channel.py
@@ -28,9 +28,9 @@ class TestChannelAccessRights(MailCommon):
cls.user_portal = mail_new_test_user(cls.env, login='user_portal', groups='base.group_portal', name='Chell Gladys')
# Channel for certain group
- cls.group_restricted_channel = cls.env['mail.channel'].browse(cls.env['mail.channel'].channel_create(name='Channel for Groups', privacy='groups', group_id=cls.env.ref('base.group_user').id)['id'])
+ cls.group_restricted_channel = cls.env['mail.channel'].browse(cls.env['mail.channel'].channel_create(name='Channel for Groups', group_id=cls.env.ref('base.group_user').id)['id'])
# Public Channel
- cls.public_channel = cls.env['mail.channel'].browse(cls.env['mail.channel'].channel_create(name='Public Channel', privacy='public', group_id=None)['id'])
+ cls.public_channel = cls.env['mail.channel'].browse(cls.env['mail.channel'].channel_create(name='Public Channel', group_id=None)['id'])
# Group
cls.private_group = cls.env['mail.channel'].browse(cls.env['mail.channel'].create_group(partners_to=cls.user_employee.partner_id.ids, name="Group")['id'])
# Chat
@@ -220,11 +220,7 @@ class TestChannelInternals(MailCommon):
@classmethod
def setUpClass(cls):
super(TestChannelInternals, cls).setUpClass()
- cls.test_channel = cls.env['mail.channel'].with_context(cls._test_context).create({
- 'channel_type': 'channel',
- 'name': 'Channel',
- 'public': 'public',
- })
+ cls.test_channel = cls.env['mail.channel'].browse(cls.env['mail.channel'].with_context(cls._test_context).channel_create(name='Channel', group_id=None)['id'])
cls.test_partner = cls.env['res.partner'].with_context(cls._test_context).create({
'name': 'Test Partner',
'email': 'test_customer@example.com',
@@ -240,15 +236,6 @@ class TestChannelInternals(MailCommon):
)
cls.partner_employee_nomail = cls.user_employee_nomail.partner_id
- @users('employee')
- def test_channel_form(self):
- """A user that create a private channel should be able to read it."""
- channel_form = Form(self.env['mail.channel'].with_user(self.user_employee))
- channel_form.name = 'Test private channel'
- channel_form.public = 'private'
- channel = channel_form.save()
- self.assertEqual(channel.name, 'Test private channel', 'Must be able to read the created channel')
-
@users('employee')
def test_channel_members(self):
channel = self.env['mail.channel'].browse(self.test_channel.ids)
@@ -331,27 +318,19 @@ class TestChannelInternals(MailCommon):
@mute_logger('odoo.models.unlink')
def test_channel_user_synchronize(self):
- """Archiving / deleting a user should automatically unsubscribe related partner from private channels"""
- test_channel_private = self.env['mail.channel'].with_context(self._test_context).create({
- 'name': 'Winden caves',
- 'description': 'Channel to travel through time',
- 'public': 'private',
- })
- group_restricted_channel = self.env['mail.channel'].browse(self.env['mail.channel'].channel_create(name='Sic Mundus', privacy='groups', group_id=self.env.ref('base.group_user').id)['id'])
+ """Archiving / deleting a user should automatically unsubscribe related partner from group restricted channels"""
+ group_restricted_channel = self.env['mail.channel'].browse(self.env['mail.channel'].channel_create(name='Sic Mundus', group_id=self.env.ref('base.group_user').id)['id'])
self.test_channel.add_members((self.partner_employee | self.partner_employee_nomail).ids)
- test_channel_private.add_members((self.partner_employee | self.partner_employee_nomail).ids)
group_restricted_channel.add_members((self.partner_employee | self.partner_employee_nomail).ids)
# Unsubscribe archived user from the private channels, but not from public channels
self.user_employee.active = False
- self.assertEqual(test_channel_private.channel_partner_ids, self.partner_employee_nomail)
self.assertEqual(group_restricted_channel.channel_partner_ids, self.partner_employee_nomail)
self.assertEqual(self.test_channel.channel_partner_ids, self.user_employee.partner_id | self.partner_employee_nomail)
# Unsubscribe deleted user from the private channels, but not from public channels
self.user_employee_nomail.unlink()
- self.assertEqual(test_channel_private.channel_partner_ids, self.env['res.partner'])
self.assertEqual(group_restricted_channel.channel_partner_ids, self.env['res.partner'])
self.assertEqual(self.test_channel.channel_partner_ids, self.user_employee.partner_id | self.partner_employee_nomail)
@@ -433,15 +412,8 @@ class TestChannelInternals(MailCommon):
"name": "Jonas",
})
test_partner = test_user.partner_id
- test_channel_private = self.env['mail.channel'].with_context(self._test_context).create({
- 'name': 'Winden caves',
- 'description': 'Channel to travel through time',
- 'public': 'private',
- 'channel_partner_ids': [Command.link(self.user_employee.partner_id.id), Command.link(test_partner.id)],
- })
group_restricted_channel = self.env['mail.channel'].with_context(self._test_context).create({
'name': 'Sic Mundus',
- 'public': 'groups',
'group_public_id': self.env.ref('base.group_user').id,
'channel_partner_ids': [Command.link(self.user_employee.partner_id.id), Command.link(test_partner.id)],
})
@@ -451,21 +423,18 @@ class TestChannelInternals(MailCommon):
private_group = self.env['mail.channel'].with_user(self.user_employee).with_context(self._test_context).create({
'name': 'test',
'channel_type': 'group',
- 'public': 'private',
'channel_partner_ids': [Command.link(self.user_employee.partner_id.id), Command.link(test_partner.id)],
})
# Unsubscribe archived user from the private channels, but not from public channels and not from group
self.user_employee.active = False
(private_group | self.test_channel).invalidate_recordset(['channel_partner_ids'])
- self.assertEqual(test_channel_private.channel_partner_ids, test_partner)
self.assertEqual(group_restricted_channel.channel_partner_ids, test_partner)
self.assertEqual(self.test_channel.channel_partner_ids, self.user_employee.partner_id | test_partner)
self.assertEqual(private_group.channel_partner_ids, self.user_employee.partner_id | test_partner)
# Unsubscribe deleted user from the private channels, but not from public channels and not from group
test_user.unlink()
- self.assertEqual(test_channel_private.channel_partner_ids, self.env['res.partner'])
self.assertEqual(group_restricted_channel.channel_partner_ids, self.env['res.partner'])
self.assertEqual(self.test_channel.channel_partner_ids, self.user_employee.partner_id | test_partner)
self.assertEqual(private_group.channel_partner_ids, self.user_employee.partner_id | test_partner)
@@ -474,8 +443,8 @@ class TestChannelInternals(MailCommon):
@mute_logger('odoo.models.unlink')
def test_channel_private_unfollow(self):
""" Test that a partner can leave (unfollow) a channel/group/chat. """
- group_restricted_channel = self.env['mail.channel'].browse(self.env['mail.channel'].channel_create(name='Channel for Groups', privacy='groups', group_id=self.env.ref('base.group_user').id)['id'])
- public_channel = self.env['mail.channel'].browse(self.env['mail.channel'].channel_create(name='Channel for Everyone', privacy='public', group_id=None)['id'])
+ group_restricted_channel = self.env['mail.channel'].browse(self.env['mail.channel'].channel_create(name='Channel for Groups', group_id=self.env.ref('base.group_user').id)['id'])
+ public_channel = self.env['mail.channel'].browse(self.env['mail.channel'].channel_create(name='Channel for Everyone', group_id=None)['id'])
private_group = self.env['mail.channel'].browse(self.env['mail.channel'].create_group(partners_to=self.user_employee.partner_id.ids, name="Group")['id'])
chat_user_current = self.env['mail.channel'].browse(self.env['mail.channel'].channel_get(self.env.user.partner_id.ids)['id'])
@@ -566,28 +535,28 @@ class TestChannelInternals(MailCommon):
):
channel.image_128 = base64.b64encode(("").encode())
- def test_mail_message_starred_private_channel(self):
- """ Test starred message computation for a private channel. A starred
- message in a private channel should be considered only if:
+ def test_mail_message_starred_group(self):
+ """ Test starred message computation for a group. A starred
+ message in a group should be considered only if:
- It's our message
- OR we have access to the channel
"""
self.assertEqual(self.user_employee._init_messaging()['starred_counter'], 0)
- private_channel = self.env['mail.channel'].create({
+ test_group = self.env['mail.channel'].create({
'name': 'Private Channel',
- 'public': 'private',
+ 'channel_type': 'group',
'channel_partner_ids': [(6, 0, self.partner_employee.id)]
})
- private_channel_own_message = private_channel.with_user(self.user_employee.id).message_post(body='TestingMessage')
- private_channel_own_message.write({'starred_partner_ids': [(6, 0, self.partner_employee.ids)]})
+ test_group_own_message = test_group.with_user(self.user_employee.id).message_post(body='TestingMessage')
+ test_group_own_message.write({'starred_partner_ids': [(6, 0, self.partner_employee.ids)]})
self.assertEqual(self.user_employee.with_user(self.user_employee)._init_messaging()['starred_counter'], 1)
- private_channel_message = private_channel.message_post(body='TestingMessage')
- private_channel_message.write({'starred_partner_ids': [(6, 0, self.partner_employee.ids)]})
+ test_group_message = test_group.message_post(body='TestingMessage')
+ test_group_message.write({'starred_partner_ids': [(6, 0, self.partner_employee.ids)]})
self.assertEqual(self.user_employee.with_user(self.user_employee)._init_messaging()['starred_counter'], 2)
- private_channel.write({'channel_partner_ids': False})
+ test_group.write({'channel_partner_ids': False})
self.assertEqual(self.user_employee.with_user(self.user_employee)._init_messaging()['starred_counter'], 1)
def test_multi_company_chat(self):
diff --git a/addons/mail/tests/test_mail_channel_as_guest.py b/addons/mail/tests/test_mail_channel_as_guest.py
index 66bab902d46..2f242e8fdc1 100644
--- a/addons/mail/tests/test_mail_channel_as_guest.py
+++ b/addons/mail/tests/test_mail_channel_as_guest.py
@@ -12,10 +12,7 @@ class TestMailPublicPage(HttpCase):
def setUp(self):
super().setUp()
- self.channel = self.env['mail.channel'].create({
- 'name': 'Test channel',
- 'public': 'public',
- })
+ self.channel = self.env['mail.channel'].browse(self.env['mail.channel'].channel_create(group_id=None, name='Test channel')['id'])
self.tour = "mail/static/tests/tours/discuss_public_tour.js"
def _open_channel_page_as_user(self, login):
diff --git a/addons/mail/tests/test_mail_channel_member.py b/addons/mail/tests/test_mail_channel_member.py
index 623dde5dd68..017a57451fd 100644
--- a/addons/mail/tests/test_mail_channel_member.py
+++ b/addons/mail/tests/test_mail_channel_member.py
@@ -47,63 +47,57 @@ class TestMailChannelMembers(MailCommon):
name='User Public',
groups='base.group_public')
- cls.private_channel = cls.env['mail.channel'].create({
- 'name': 'Secret channel',
- 'public': 'private',
- 'channel_type': 'channel',
+ cls.group = cls.env['mail.channel'].create({
+ 'name': 'Group',
+ 'channel_type': 'group',
})
- cls.group_channel = cls.env['mail.channel'].create({
- 'name': 'Group channel',
- 'public': 'groups',
+ cls.group_restricted_channel = cls.env['mail.channel'].create({
+ 'name': 'Group restricted channel',
'channel_type': 'channel',
'group_public_id': cls.secret_group.id,
})
- cls.public_channel = cls.env['mail.channel'].create({
- 'name': 'Public channel of user 1',
- 'public': 'public',
- 'channel_type': 'channel',
- })
- (cls.private_channel | cls.group_channel | cls.public_channel).channel_member_ids.unlink()
+ cls.public_channel = cls.env['mail.channel'].browse(cls.env['mail.channel'].channel_create(group_id=None, name='Public channel of user 1')['id'])
+ (cls.group | cls.group_restricted_channel | cls.public_channel).channel_member_ids.unlink()
# ------------------------------------------------------------
- # PRIVATE CHANNELS
+ # GROUP
# ------------------------------------------------------------
- def test_channel_private_01(self):
- """Test access on private channel."""
- res = self.env['mail.channel.member'].search([('channel_id', '=', self.private_channel.id)])
+ def test_group_01(self):
+ """Test access on group."""
+ res = self.env['mail.channel.member'].search([('channel_id', '=', self.group.id)])
self.assertFalse(res)
- # User 1 can join private channel with SUDO
- self.private_channel.with_user(self.user_1).sudo().add_members(self.user_1.partner_id.ids)
- res = self.env['mail.channel.member'].search([('channel_id', '=', self.private_channel.id)])
+ # User 1 can join group with SUDO
+ self.group.with_user(self.user_1).sudo().add_members(self.user_1.partner_id.ids)
+ res = self.env['mail.channel.member'].search([('channel_id', '=', self.group.id)])
self.assertEqual(res.partner_id, self.user_1.partner_id)
- # User 2 can not join private channel
+ # User 2 can not join group
with self.assertRaises(AccessError):
- self.private_channel.with_user(self.user_2).add_members(self.user_2.partner_id.ids)
+ self.group.with_user(self.user_2).add_members(self.user_2.partner_id.ids)
- # User 2 can not create a `mail.channel.member` to join the private channel
+ # User 2 can not create a `mail.channel.member` to join the group
with self.assertRaises(AccessError):
self.env['mail.channel.member'].with_user(self.user_2).create({
'partner_id': self.user_2.partner_id.id,
- 'channel_id': self.private_channel.id,
+ 'channel_id': self.group.id,
})
- # User 2 can not write on `mail.channel.member` to join the private channel
+ # User 2 can not write on `mail.channel.member` to join the group
channel_member = self.env['mail.channel.member'].with_user(self.user_2).search([('partner_id', '=', self.user_2.partner_id.id)])[0]
with self.assertRaises(AccessError):
- channel_member.channel_id = self.private_channel.id
+ channel_member.channel_id = self.group.id
with self.assertRaises(AccessError):
- channel_member.write({'channel_id': self.private_channel.id})
+ channel_member.write({'channel_id': self.group.id})
# Even with SUDO, channel_id of channel.member should not be changed.
with self.assertRaises(AccessError):
- channel_member.sudo().channel_id = self.private_channel.id
+ channel_member.sudo().channel_id = self.group.id
# User 2 can not write on the `partner_id` of `mail.channel.member`
- # of an other partner to join a private channel
- channel_member_1 = self.env['mail.channel.member'].search([('channel_id', '=', self.private_channel.id), ('partner_id', '=', self.user_1.partner_id.id)])
+ # of an other partner to join a group
+ channel_member_1 = self.env['mail.channel.member'].search([('channel_id', '=', self.group.id), ('partner_id', '=', self.user_1.partner_id.id)])
with self.assertRaises(AccessError):
channel_member_1.with_user(self.user_2).partner_id = self.user_2.partner_id
self.assertEqual(channel_member_1.partner_id, self.user_1.partner_id)
@@ -112,64 +106,64 @@ class TestMailChannelMembers(MailCommon):
with self.assertRaises(AccessError):
channel_member_1.with_user(self.user_2).sudo().partner_id = self.user_2.partner_id
- def test_channel_private_members(self):
- """Test invitation in private channel part 1 (invite using crud methods)."""
- self.private_channel.with_user(self.user_1).sudo().add_members(self.user_1.partner_id.ids)
- channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.private_channel.id)])
+ def test_group_members(self):
+ """Test invitation in group part 1 (invite using crud methods)."""
+ self.group.with_user(self.user_1).sudo().add_members(self.user_1.partner_id.ids)
+ channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group.id)])
self.assertEqual(len(channel_members), 1)
- # User 2 is not in the private channel, they can not invite user 3
+ # User 2 is not in the group, they can not invite user 3
with self.assertRaises(AccessError):
self.env['mail.channel.member'].with_user(self.user_2).create({
'partner_id': self.user_portal.partner_id.id,
- 'channel_id': self.private_channel.id,
+ 'channel_id': self.group.id,
})
- # User 1 is in the private channel, they can invite other users
+ # User 1 is in the group, they can invite other users
self.env['mail.channel.member'].with_user(self.user_1).create({
'partner_id': self.user_portal.partner_id.id,
- 'channel_id': self.private_channel.id,
+ 'channel_id': self.group.id,
})
- channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.private_channel.id)])
+ channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group.id)])
self.assertEqual(channel_members.mapped('partner_id'), self.user_1.partner_id | self.user_portal.partner_id)
# But User 3 can not write on the `mail.channel.member` of other user
- channel_member_1 = self.env['mail.channel.member'].search([('channel_id', '=', self.private_channel.id), ('partner_id', '=', self.user_1.partner_id.id)])
- channel_member_3 = self.env['mail.channel.member'].search([('channel_id', '=', self.private_channel.id), ('partner_id', '=', self.user_portal.partner_id.id)])
+ channel_member_1 = self.env['mail.channel.member'].search([('channel_id', '=', self.group.id), ('partner_id', '=', self.user_1.partner_id.id)])
+ channel_member_3 = self.env['mail.channel.member'].search([('channel_id', '=', self.group.id), ('partner_id', '=', self.user_portal.partner_id.id)])
channel_member_3.with_user(self.user_portal).custom_channel_name = 'Test'
with self.assertRaises(AccessError):
channel_member_1.with_user(self.user_2).custom_channel_name = 'Blabla'
self.assertNotEqual(channel_member_1.custom_channel_name, 'Blabla')
- def test_channel_private_invite(self):
- """Test invitation in private channel part 2 (use `invite` action)."""
- self.private_channel.with_user(self.user_1).sudo().add_members(self.user_1.partner_id.ids)
- channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.private_channel.id)])
+ def test_group_invite(self):
+ """Test invitation in group part 2 (use `invite` action)."""
+ self.group.with_user(self.user_1).sudo().add_members(self.user_1.partner_id.ids)
+ channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group.id)])
self.assertEqual(channel_members.mapped('partner_id'), self.user_1.partner_id)
- # User 2 is not in the channel, they can not invite user_portal
+ # User 2 is not in the group, they can not invite user_portal
with self.assertRaises(AccessError):
- self.private_channel.with_user(self.user_2).add_members(self.user_portal.partner_id.ids)
- channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.private_channel.id)])
+ self.group.with_user(self.user_2).add_members(self.user_portal.partner_id.ids)
+ channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group.id)])
self.assertEqual(channel_members.mapped('partner_id'), self.user_1.partner_id)
- # User 1 is in the channel, they can invite user_portal
- self.private_channel.with_user(self.user_1).add_members(self.user_portal.partner_id.ids)
- channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.private_channel.id)])
+ # User 1 is in the group, they can invite user_portal
+ self.group.with_user(self.user_1).add_members(self.user_portal.partner_id.ids)
+ channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group.id)])
self.assertEqual(channel_members.mapped('partner_id'), self.user_1.partner_id | self.user_portal.partner_id)
- def test_channel_private_leave(self):
+ def test_group_leave(self):
"""Test kick/leave channel."""
- self.private_channel.with_user(self.user_1).sudo().add_members(self.user_1.partner_id.ids)
- self.private_channel.with_user(self.user_portal).sudo().add_members(self.user_portal.partner_id.ids)
- channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.private_channel.id)])
+ self.group.with_user(self.user_1).sudo().add_members(self.user_1.partner_id.ids)
+ self.group.with_user(self.user_portal).sudo().add_members(self.user_portal.partner_id.ids)
+ channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group.id)])
self.assertEqual(len(channel_members), 2)
- # User 2 is not in the channel, they can not kick user 1
+ # User 2 is not in the group, they can not kick user 1
with self.assertRaises(AccessError):
channel_members.with_user(self.user_2).unlink()
- # User 3 is in the channel, they can kick user 1
+ # User 3 is in the group, they can kick user 1
channel_members.with_user(self.user_portal).unlink()
# ------------------------------------------------------------
@@ -178,34 +172,34 @@ class TestMailChannelMembers(MailCommon):
def test_group_restricted_channel(self):
"""Test basics on group channel."""
- channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group_channel.id)])
+ channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group_restricted_channel.id)])
self.assertFalse(channel_members)
- # user 1 is in the group, they can join the channel
- self.group_channel.with_user(self.user_1).add_members(self.user_1.partner_id.ids)
- channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group_channel.id)])
+ # user 1 is in the channel, they can join the channel
+ self.group_restricted_channel.with_user(self.user_1).add_members(self.user_1.partner_id.ids)
+ channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group_restricted_channel.id)])
self.assertEqual(channel_members.mapped('partner_id'), self.user_1.partner_id)
- # user 3 is not in the group, they can not join
+ # user 3 is not in the channel, they can not join
with self.assertRaises(AccessError):
- self.group_channel.with_user(self.user_portal).add_members(self.user_portal.partner_id.ids)
+ self.group_restricted_channel.with_user(self.user_portal).add_members(self.user_portal.partner_id.ids)
- channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group_channel.id)])
+ channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group_restricted_channel.id)])
with self.assertRaises(AccessError):
channel_members.with_user(self.user_portal).partner_id = self.user_portal.partner_id
- channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group_channel.id)])
+ channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group_restricted_channel.id)])
self.assertEqual(channel_members.mapped('partner_id'), self.user_1.partner_id)
- # user 1 can not invite user 3 because they are not in the group
+ # user 1 can not invite user 3 because they are not in the channel
with self.assertRaises(UserError):
- self.group_channel.with_user(self.user_1).add_members(self.user_portal.partner_id.ids)
- channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group_channel.id)])
+ self.group_restricted_channel.with_user(self.user_1).add_members(self.user_portal.partner_id.ids)
+ channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group_restricted_channel.id)])
self.assertEqual(channel_members.mapped('partner_id'), self.user_1.partner_id)
- # but user 2 is in the group and can be invited by user 1
- self.group_channel.with_user(self.user_1).add_members(self.user_2.partner_id.ids)
- channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group_channel.id)])
+ # but user 2 is in the channel and can be invited by user 1
+ self.group_restricted_channel.with_user(self.user_1).add_members(self.user_2.partner_id.ids)
+ channel_members = self.env['mail.channel.member'].search([('channel_id', '=', self.group_restricted_channel.id)])
self.assertEqual(channel_members.mapped('partner_id'), self.user_1.partner_id | self.user_2.partner_id)
# ------------------------------------------------------------
@@ -249,11 +243,7 @@ class TestMailChannelMembers(MailCommon):
# ------------------------------------------------------------
def test_unread_counter_with_message_post(self):
- channel_as_user_1 = self.env['mail.channel'].with_user(self.user_1).create({
- 'name': 'Secret channel',
- 'public': 'public',
- 'channel_type': 'channel',
- })
+ channel_as_user_1 = self.env['mail.channel'].browse(self.env['mail.channel'].with_user(self.user_1).channel_create(group_id=None, name='Public channel')['id'])
channel_as_user_1.with_user(self.user_1).add_members(self.user_1.partner_id.ids)
channel_as_user_1.with_user(self.user_1).add_members(self.user_2.partner_id.ids)
channel_1_rel_user_2 = self.env['mail.channel.member'].search([
@@ -270,16 +260,8 @@ class TestMailChannelMembers(MailCommon):
self.assertEqual(channel_1_rel_user_2.message_unread_counter, 1, "should have 1 unread message after someone else posted a message")
def test_unread_counter_with_message_post_multi_channel(self):
- channel_1_as_user_1 = self.env['mail.channel'].with_user(self.user_1).create({
- 'name': 'wololo channel',
- 'public': 'public',
- 'channel_type': 'channel',
- })
- channel_2_as_user_2 = self.env['mail.channel'].with_user(self.user_2).create({
- 'name': 'walala channel',
- 'public': 'public',
- 'channel_type': 'channel',
- })
+ channel_1_as_user_1 = self.env['mail.channel'].with_user(self.user_1).browse(self.env['mail.channel'].with_user(self.user_1).channel_create(group_id=None, name='wololo channel')['id'])
+ channel_2_as_user_2 = self.env['mail.channel'].with_user(self.user_2).browse(self.env['mail.channel'].with_user(self.user_2).channel_create(group_id=None, name='walala channel')['id'])
channel_1_as_user_1.add_members(self.user_2.partner_id.ids)
channel_2_as_user_2.add_members(self.user_1.partner_id.ids)
channel_2_as_user_2.add_members(self.user_3.partner_id.ids)
diff --git a/addons/mail/views/mail_channel_views.xml b/addons/mail/views/mail_channel_views.xml
index c7489539206..5644424713b 100644
--- a/addons/mail/views/mail_channel_views.xml
+++ b/addons/mail/views/mail_channel_views.xml
@@ -12,7 +12,6 @@
-