[IMP] mail: display channel invite group restriction

Before this PR, nothing warned the user that the invitation link was restricted to
a user group.

task-2818094

closes odoo/odoo#88562

Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit is contained in:
Didier (did)
2022-05-23 17:31:45 +02:00
committed by Sébastien Theys
parent 659c61219f
commit 0b1846bb46
8 changed files with 100 additions and 12 deletions
+1
View File
@@ -819,6 +819,7 @@ class Channel(models.Model):
'public': channel.public,
'group_based_subscription': bool(channel.group_ids),
'create_uid': channel.create_uid.id,
'authorizedGroupFullName': channel.group_public_id.full_name,
}
# add last message preview (only used in mobile)
info['last_message_id'] = channel_last_message_ids.get(channel.id, False)
@@ -40,7 +40,7 @@
</t>
<t t-if="channelInvitationForm.thread and channelInvitationForm.thread.invitationLink">
<h4 class="mx-3 mt-3 mb-2">Invitation Link</h4>
<div class="mx-3 my-2">
<div class="mx-3 mt-2 mb-3">
<div class="input-group">
<input class="form-control" type="text" t-att-value="channelInvitationForm.thread.invitationLink" readonly="" t-on-focus="channelInvitationForm.onFocusInvitationLinkInput" />
<div class="input-group-append">
@@ -49,6 +49,9 @@
</button>
</div>
</div>
<t t-if="channelInvitationForm.accessRestrictedToGroupText">
<div class="o_ChannelInvitationForm_accessRestrictedToGroup mt-2" t-esc="channelInvitationForm.accessRestrictedToGroupText"/>
</t>
</div>
</t>
</div>
@@ -5,6 +5,8 @@ import { attr, many, one } from '@mail/model/model_field';
import { clear, insertAndReplace, link, replace, unlink } from '@mail/model/model_field_command';
import { cleanSearchTerm } from '@mail/utils/utils';
import { sprintf } from '@web/core/utils/strings';
registerModel({
name: 'ChannelInvitationForm',
identifyingFields: [['chatWindow', 'popoverViewOwner']],
@@ -156,6 +158,25 @@ registerModel({
}
}
},
/**
* @private
* @returns {string|FieldCommand}
*/
_computeAccessRestrictedToGroupText() {
if (!this.thread) {
return clear();
}
if (
!this.thread.authorizedGroupFullName ||
this.thread.public !== 'groups'
) {
return clear();
}
return sprintf(
this.env._t('Access restricted to group "%(groupFullName)s"'),
{ 'groupFullName': this.thread.authorizedGroupFullName }
);
},
/**
* @private
* @returns {string}
@@ -211,6 +232,9 @@ registerModel({
},
},
fields: {
accessRestrictedToGroupText: attr({
compute: '_computeAccessRestrictedToGroupText',
}),
chatWindow: one('ChatWindow', {
inverse: 'channelInvitationForm',
readonly: true,
+4
View File
@@ -41,6 +41,9 @@ registerModel({
*/
convertData(data) {
const data2 = {};
if ('authorizedGroupFullName' in data) {
data2.authorizedGroupFullName = data.authorizedGroupFullName;
}
if ('avatarCacheKey' in data) {
data2.avatarCacheKey = data.avatarCacheKey;
}
@@ -1814,6 +1817,7 @@ registerModel({
attachments: many('Attachment', {
inverse: 'threads',
}),
authorizedGroupFullName: attr(),
/**
* Cache key to force a reload of the avatar when avatar is changed.
* It only makes sense for channels.
@@ -789,7 +789,7 @@ MockServer.include({
channel_last_seen_partner_ids: [[2, channelMember.id]],
},
);
this.pyEnv['bus.bus']._sendone(this.currentPartner, 'mail.channel/leave', {
this.pyEnv['bus.bus']._sendone(this.currentPartner, 'mail.channel/leave', {
'id': channel.id,
});
/**
@@ -1004,6 +1004,9 @@ MockServer.include({
['model', '=', 'mail.channel'],
['res_id', '=', channel.id],
]);
const [group_public_id] = this.getRecords('res.groups', [
['id', '=', channel.group_public_id],
]);
const lastMessageId = messages.reduce((lastMessageId, message) => {
if (!lastMessageId || message.id > lastMessageId) {
return message.id;
@@ -1019,6 +1022,7 @@ MockServer.include({
last_message_id: lastMessageId,
members: [...this._mockResPartnerMailPartnerFormat(partnerIds).values()],
message_needaction_counter: messageNeedactionCounter,
authorizedGroupFullName: group_public_id ? group_public_id.name : false,
});
if (channel.channel_type === 'channel') {
delete res.members;
@@ -1065,8 +1069,8 @@ MockServer.include({
);
}
if (!pinned) {
this.pyEnv['bus.bus']._sendone(this.currentPartner, 'mail.channel/unpin', {
'id': channel.id,
this.pyEnv['bus.bus']._sendone(this.currentPartner, 'mail.channel/unpin', {
'id': channel.id,
});
} else {
this.pyEnv['bus.bus']._sendone(this.currentPartner, 'mail.channel/legacy_insert', this._mockMailChannelChannelInfo([channel.id])[0]);
@@ -1260,9 +1264,9 @@ MockServer.include({
},
);
const channel = this.pyEnv['mail.channel'].searchRead([['id', '=', id]])[0];
this.pyEnv['bus.bus']._sendone(channel, 'mail.channel/insert', {
'id': id,
'avatarCacheKey': channel.avatarCacheKey
this.pyEnv['bus.bus']._sendone(channel, 'mail.channel/insert', {
'id': id,
'avatarCacheKey': channel.avatarCacheKey
});
},
/**
@@ -16,7 +16,7 @@ addModelNamesToFetch([
'ir.attachment', 'ir.model', 'ir.model.fields', 'mail.activity', 'mail.activity.type',
'mail.channel', 'mail.channel.partner', 'mail.followers', 'mail.message', 'mail.message.subtype',
'mail.notification', 'mail.shortcode', 'mail.template', 'mail.tracking.value',
'res.company', 'res.country', 'res.partner', 'res.users', 'res.users.settings',
'res.company', 'res.country', 'res.partner', 'res.users', 'res.users.settings', 'res.groups'
]);
addFakeModel('res.fake', {
@@ -123,5 +123,42 @@ QUnit.test('should be able to create a new group chat from an existing chat', as
);
});
QUnit.test('Invitation form should display channel group restriction', async function (assert) {
assert.expect(1);
const pyEnv = await startServer();
const resPartnerId1 = pyEnv['res.partner'].create({
email: "testpartner@odoo.com",
name: "TestPartner",
});
pyEnv['res.users'].create({ partner_id: resPartnerId1 });
const resGroupId1 = pyEnv['res.groups'].create({
name: "testGroup",
});
const mailChannelId1 = pyEnv['mail.channel'].create({
channel_last_seen_partner_ids: [
[0, 0, { partner_id: pyEnv.currentPartnerId }],
],
channel_type: 'channel',
public: 'groups',
group_public_id: resGroupId1,
});
const { click, openDiscuss } = await start({
discuss: {
context: {
active_id: mailChannelId1,
},
},
});
await openDiscuss();
await click(`.o_ThreadViewTopbar_inviteButton`);
assert.containsOnce(
document.body,
'.o_ChannelInvitationForm_accessRestrictedToGroup',
"should display the channel restriction warning"
);
});
});
});
@@ -6,17 +6,18 @@ from dateutil.relativedelta import relativedelta
from odoo import Command
from odoo.tests.common import users, tagged, TransactionCase, warmup
from odoo.tools.misc import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
@tagged('post_install', '-at_install')
class TestDiscussFullPerformance(TransactionCase):
def setUp(self):
super().setUp()
self.group_user = self.env.ref('base.group_user')
self.users = self.env['res.users'].create([
{
'email': 'e.e@example.com',
'groups_id': [Command.link(self.env.ref('base.group_user').id)],
'groups_id': [Command.link(self.group_user.id)],
'login': 'emp',
'name': 'Ernest Employee',
'notification_type': 'inbox',
@@ -100,7 +101,7 @@ class TestDiscussFullPerformance(TransactionCase):
self.maxDiff = None
self.users[0].flush()
self.users[0].invalidate_cache()
with self.assertQueryCount(emp=82):
with self.assertQueryCount(emp=83):
init_messaging = self.users[0].with_user(self.users[0])._init_messaging()
self.assertEqual(init_messaging, {
@@ -108,6 +109,7 @@ class TestDiscussFullPerformance(TransactionCase):
'starred_counter': 1,
'channels': [
{
'authorizedGroupFullName': self.group_user.full_name,
'avatarCacheKey': channel_general._get_avatar_cache_key(),
'channel_type': 'channel',
'create_uid': user_root.id,
@@ -122,7 +124,7 @@ class TestDiscussFullPerformance(TransactionCase):
'is_pinned': True,
'last_interest_dt': channel_general.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
'last_message_id': next(res['message_id'] for res in channel_general._channel_last_message_ids()),
'memberCount': len(self.env.ref('base.group_user').users | user_root),
'memberCount': len(self.group_user.users | user_root),
'message_needaction_counter': 0,
'message_unread_counter': 5,
'name': 'general',
@@ -133,6 +135,7 @@ class TestDiscussFullPerformance(TransactionCase):
'uuid': channel_general.uuid,
},
{
'authorizedGroupFullName': self.group_user.full_name,
'avatarCacheKey': channel_channel_public_1._get_avatar_cache_key(),
'channel_type': 'channel',
'create_uid': self.env.user.id,
@@ -158,6 +161,7 @@ class TestDiscussFullPerformance(TransactionCase):
'uuid': channel_channel_public_1.uuid,
},
{
'authorizedGroupFullName': self.group_user.full_name,
'avatarCacheKey': channel_channel_public_2._get_avatar_cache_key(),
'channel_type': 'channel',
'create_uid': self.env.user.id,
@@ -183,6 +187,7 @@ class TestDiscussFullPerformance(TransactionCase):
'uuid': channel_channel_public_2.uuid,
},
{
'authorizedGroupFullName': self.group_user.full_name,
'avatarCacheKey': channel_channel_group_1._get_avatar_cache_key(),
'channel_type': 'channel',
'create_uid': self.env.user.id,
@@ -208,6 +213,7 @@ class TestDiscussFullPerformance(TransactionCase):
'uuid': channel_channel_group_1.uuid,
},
{
'authorizedGroupFullName': self.group_user.full_name,
'avatarCacheKey': channel_channel_group_2._get_avatar_cache_key(),
'channel_type': 'channel',
'create_uid': self.env.user.id,
@@ -233,6 +239,7 @@ class TestDiscussFullPerformance(TransactionCase):
'uuid': channel_channel_group_2.uuid,
},
{
'authorizedGroupFullName': self.group_user.full_name,
'avatarCacheKey': channel_channel_private_1._get_avatar_cache_key(),
'channel_type': 'channel',
'create_uid': self.env.user.id,
@@ -258,6 +265,7 @@ class TestDiscussFullPerformance(TransactionCase):
'uuid': channel_channel_private_1.uuid,
},
{
'authorizedGroupFullName': self.group_user.full_name,
'avatarCacheKey': channel_channel_private_2._get_avatar_cache_key(),
'channel_type': 'channel',
'create_uid': self.env.user.id,
@@ -283,6 +291,7 @@ class TestDiscussFullPerformance(TransactionCase):
'uuid': channel_channel_private_2.uuid,
},
{
'authorizedGroupFullName': False,
'avatarCacheKey': channel_group_1._get_avatar_cache_key(),
'channel_type': 'group',
'create_uid': self.env.user.id,
@@ -347,6 +356,7 @@ class TestDiscussFullPerformance(TransactionCase):
'uuid': channel_group_1.uuid,
},
{
'authorizedGroupFullName': False,
'avatarCacheKey': channel_chat_1._get_avatar_cache_key(),
'channel_type': 'chat',
'create_uid': self.env.user.id,
@@ -411,6 +421,7 @@ class TestDiscussFullPerformance(TransactionCase):
'uuid': channel_chat_1.uuid,
},
{
'authorizedGroupFullName': False,
'avatarCacheKey': channel_chat_2._get_avatar_cache_key(),
'channel_type': 'chat',
'create_uid': self.env.user.id,
@@ -475,6 +486,7 @@ class TestDiscussFullPerformance(TransactionCase):
'uuid': channel_chat_2.uuid,
},
{
'authorizedGroupFullName': False,
'avatarCacheKey': channel_chat_3._get_avatar_cache_key(),
'channel_type': 'chat',
'create_uid': self.env.user.id,
@@ -539,6 +551,7 @@ class TestDiscussFullPerformance(TransactionCase):
'uuid': channel_chat_3.uuid,
},
{
'authorizedGroupFullName': False,
'avatarCacheKey': channel_chat_4._get_avatar_cache_key(),
'channel_type': 'chat',
'create_uid': self.env.user.id,
@@ -603,6 +616,7 @@ class TestDiscussFullPerformance(TransactionCase):
'uuid': channel_chat_4.uuid,
},
{
'authorizedGroupFullName': False,
'avatarCacheKey': channel_livechat_1._get_avatar_cache_key(),
'channel_type': 'livechat',
'create_uid': self.env.user.id,
@@ -667,6 +681,7 @@ class TestDiscussFullPerformance(TransactionCase):
'uuid': channel_livechat_1.uuid,
},
{
'authorizedGroupFullName': False,
'avatarCacheKey': channel_livechat_2._get_avatar_cache_key(),
'channel_type': 'livechat',
'create_uid': self.env.ref('base.public_user').id,