mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-20 05:32:00 +02:00
272 lines
11 KiB
Python
272 lines
11 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from datetime import datetime, timedelta
|
|
from freezegun import freeze_time
|
|
from psycopg2 import IntegrityError
|
|
from unittest import skip
|
|
from unittest.mock import patch
|
|
|
|
from odoo.addons.base.models.res_users import ResUsersPatchedInTest
|
|
from odoo.addons.mail.tests.common import MailCommon, mail_new_test_user
|
|
from odoo.addons.base.tests.common import HttpCaseWithUserDemo
|
|
from odoo.tests import RecordCapturer, tagged, users
|
|
from odoo.tools import mute_logger
|
|
|
|
|
|
@tagged('-at_install', 'post_install', 'mail_tools', 'res_users')
|
|
class TestNotifySecurityUpdate(MailCommon):
|
|
|
|
@users('employee')
|
|
def test_security_update_email(self):
|
|
""" User should be notified on old email address when the email changes """
|
|
with self.mock_mail_gateway():
|
|
self.env.user.write({'email': 'new@example.com'})
|
|
|
|
self.assertSentEmail(
|
|
'"YourTestCompany" <your.company@example.com>',
|
|
['e.e@example.com'],
|
|
subject='Security Update: Email Changed',
|
|
)
|
|
|
|
@users('employee')
|
|
def test_security_update_login(self):
|
|
with self.mock_mail_gateway():
|
|
self.env.user.write({'login': 'newlogin'})
|
|
|
|
self.assertSentEmail(
|
|
'"YourTestCompany" <your.company@example.com>',
|
|
[self.env.user.email_formatted],
|
|
subject='Security Update: Login Changed',
|
|
)
|
|
|
|
@users('employee')
|
|
def test_security_update_password(self):
|
|
with self.mock_mail_gateway():
|
|
self.env.user.write({'password': 'newpassword'})
|
|
|
|
self.assertSentEmail(
|
|
'"YourTestCompany" <your.company@example.com>',
|
|
[self.env.user.email_formatted],
|
|
subject='Security Update: Password Changed',
|
|
)
|
|
|
|
@tagged('-at_install', 'post_install', 'mail_tools', 'res_users')
|
|
class TestUser(MailCommon):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls.portal_user = cls._create_portal_user()
|
|
|
|
@mute_logger('odoo.sql_db')
|
|
def test_notification_type_constraint(self):
|
|
with self.assertRaises(IntegrityError, msg='Portal user can not receive notification in Odoo'):
|
|
mail_new_test_user(
|
|
self.env,
|
|
login='user_test_constraint_2',
|
|
name='Test User 2',
|
|
email='user_test_constraint_2@test.example.com',
|
|
notification_type='inbox',
|
|
groups='base.group_portal',
|
|
)
|
|
|
|
def test_notification_type_convert_internal_inbox_to_portal(self):
|
|
"""Tests an internal user using inbox notifications converted to portal
|
|
is automatically set to email notifications"""
|
|
user = mail_new_test_user(
|
|
self.env,
|
|
login='user_test_constraint_3',
|
|
name='Test User 3',
|
|
email='user_test_constraint_3@test.example.com',
|
|
notification_type='inbox',
|
|
groups='base.group_user',
|
|
)
|
|
|
|
# Ensure the internal user has well the inbox notification type
|
|
self.assertEqual(user.notification_type, 'inbox')
|
|
self.assertIn(self.env.ref('mail.group_mail_notification_type_inbox'), user.group_ids)
|
|
|
|
# Change the internal user to portal, and make sure it automatically converts from inbox to email notifications
|
|
user.write({'group_ids': [
|
|
(3, self.env.ref('base.group_user').id),
|
|
(4, self.env.ref('base.group_portal').id),
|
|
]})
|
|
self.assertEqual(user.notification_type, 'email')
|
|
self.assertNotIn(self.env.ref('mail.group_mail_notification_type_inbox'), user.group_ids)
|
|
|
|
admin = mail_new_test_user(
|
|
self.env,
|
|
login="user_test_constraint_4",
|
|
name="Test User 4",
|
|
email="user_test_constraint_3@test.example.com",
|
|
notification_type='inbox',
|
|
groups='base.group_erp_manager',
|
|
)
|
|
# Re-check that no error occurs when we have overlapping writes on admin user
|
|
admin.write({
|
|
'notification_type': 'email',
|
|
'group_ids': [
|
|
(3, self.env.ref('base.group_user').id),
|
|
(3, self.env.ref('base.group_erp_manager').id),
|
|
(4, self.env.ref('base.group_portal').id),
|
|
],
|
|
})
|
|
self.assertFalse(admin._is_admin())
|
|
self.assertTrue(admin._is_portal())
|
|
self.assertEqual(admin.notification_type, 'email')
|
|
self.assertNotIn(self.env.ref('mail.group_mail_notification_type_inbox'), admin.group_ids)
|
|
|
|
@freeze_time("2025-06-18 08:45:12")
|
|
def test_out_of_office(self):
|
|
""" Test Out-of-Office computation, defined on user itself. """
|
|
test_user = self.user_employee.with_user(self.user_employee)
|
|
portal_user = self.portal_user
|
|
now = datetime(2025, 6, 8, 8, 45, 12)
|
|
for ooo_from, ooo_to, exp_ooo in [
|
|
(False, False, False),
|
|
(now - timedelta(hours=1), False, True), # only a from is ok
|
|
(False, now + timedelta(hours=1), False), # invalid interval
|
|
(now - timedelta(hours=1), now + timedelta(hours=1), True),
|
|
(now, now, True),
|
|
(now - timedelta(hours=4), now - timedelta(hours=2), False), # past
|
|
(now + timedelta(hours=2), now + timedelta(hours=4), False), # future
|
|
(now + timedelta(hours=2), False, False), # future, from only
|
|
]:
|
|
with self.subTest(ooo_from=ooo_from, ooo_to=ooo_to):
|
|
with self.mock_datetime_and_now(now): # also mock cr.now()
|
|
test_user.write({
|
|
'out_of_office_from': ooo_from,
|
|
'out_of_office_to': ooo_to,
|
|
})
|
|
self.assertEqual(test_user.is_out_of_office, exp_ooo)
|
|
|
|
portal_user.write({
|
|
'out_of_office_from': ooo_from,
|
|
'out_of_office_to': ooo_to,
|
|
})
|
|
self.assertFalse(portal_user.is_out_of_office, 'Portal users are never OOO')
|
|
|
|
def test_web_create_users(self):
|
|
src = [
|
|
'POILUCHETTE@test.example.com',
|
|
'"Jean Poilvache" <POILVACHE@test.example.com>',
|
|
]
|
|
with self.mock_mail_gateway(), \
|
|
RecordCapturer(self.env['res.users']) as capture:
|
|
self.env['res.users'].web_create_users(src)
|
|
|
|
exp_emails = ['poiluchette@test.example.com', 'poilvache@test.example.com']
|
|
# check reset password are effectively sent
|
|
for user_email in exp_emails:
|
|
# do not use assertMailMailWEmails as mails are removed whatever we
|
|
# try to do, code is using a savepoint to avoid storing mail.mail
|
|
# in DB
|
|
self.assertSentEmail(
|
|
self.env.company.partner_id.email_formatted,
|
|
[user_email],
|
|
email_from=self.env.company.partner_id.email_formatted,
|
|
)
|
|
|
|
# order does not seem guaranteed
|
|
self.assertEqual(len(capture.records), 2, 'Should create one user / entry')
|
|
self.assertEqual(
|
|
sorted(capture.records.mapped('name')),
|
|
sorted(('poiluchette@test.example.com', 'Jean Poilvache'))
|
|
)
|
|
self.assertEqual(
|
|
sorted(capture.records.mapped('email')),
|
|
sorted(exp_emails)
|
|
)
|
|
|
|
|
|
@tagged('-at_install', 'post_install', 'res_users')
|
|
class TestUserTours(HttpCaseWithUserDemo):
|
|
|
|
def test_user_modify_own_profile(self):
|
|
"""" A user should be able to modify their own profile.
|
|
Even if that user does not have access rights to write on the res.users model. """
|
|
if 'hr.employee' in self.env and not self.user_demo.employee_id:
|
|
self.env['hr.employee'].create({
|
|
'name': 'Marc Demo',
|
|
'user_id': self.user_demo.id,
|
|
})
|
|
self.user_demo.group_ids += self.env.ref('hr.group_hr_user')
|
|
self.user_demo.tz = "Europe/Brussels"
|
|
self.user_demo.notification_type = "email"
|
|
|
|
# avoid 'reload_context' action in the middle of the tour to ease steps and form save checks
|
|
with patch.object(ResUsersPatchedInTest, 'preference_save', lambda self: True):
|
|
self.start_tour(
|
|
"/odoo",
|
|
"mail/static/tests/tours/user_modify_own_profile_tour.js",
|
|
login="demo",
|
|
)
|
|
self.assertEqual(self.user_demo.notification_type, "inbox")
|
|
|
|
|
|
@tagged("post_install", "-at_install")
|
|
class TestUserSettings(MailCommon):
|
|
|
|
@skip('Crashes in post_install, probably because other modules force creation through inverse (e.g. voip)')
|
|
def test_create_portal_user(self):
|
|
portal_group = self.env.ref('base.group_portal')
|
|
user = self.env.user.create({
|
|
'name': 'A portal user',
|
|
'login': 'portal_test',
|
|
'group_ids': [(6, 0, [portal_group.id])],
|
|
})
|
|
self.assertFalse(user.res_users_settings_ids, 'Portal users should not have settings by default')
|
|
|
|
def test_create_internal_user(self):
|
|
user = self.env.user.create({
|
|
'name': 'A internal user',
|
|
'login': 'test_user',
|
|
})
|
|
self.assertTrue(user.res_users_settings_ids, 'Internal users should have settings by default')
|
|
|
|
@users('employee')
|
|
def test_find_or_create_for_user_should_create_record_if_not_existing(self):
|
|
self.user_employee.res_users_settings_ids.unlink() # pre autocreate or a portal user switching to internal user
|
|
settings = self.user_employee.res_users_settings_ids
|
|
self.assertFalse(settings, "no records should exist")
|
|
|
|
self.env['res.users.settings']._find_or_create_for_user(self.user_employee)
|
|
settings = self.user_employee.res_users_settings_ids
|
|
self.assertTrue(settings, "a record should be created after _find_or_create_for_user is called")
|
|
|
|
@users('employee')
|
|
def test_find_or_create_for_user_should_return_correct_res_users_settings(self):
|
|
self.user_employee.res_users_settings_ids.unlink()
|
|
settings = self.env['res.users.settings'].create({
|
|
'user_id': self.user_employee.id,
|
|
})
|
|
result = self.env['res.users.settings']._find_or_create_for_user(self.user_employee)
|
|
self.assertEqual(result, settings, "Correct mail user settings should be returned")
|
|
|
|
@users('employee')
|
|
def test_set_res_users_settings_should_send_notification_on_bus(self):
|
|
settings = self.user_employee.res_users_settings_id
|
|
settings.is_discuss_sidebar_category_chat_open = False
|
|
settings.is_discuss_sidebar_category_channel_open = False
|
|
|
|
with self.assertBus(
|
|
[(self.cr.dbname, 'res.partner', self.partner_employee.id)],
|
|
[{
|
|
'type': 'res.users.settings',
|
|
'payload': {
|
|
'id': settings.id,
|
|
'is_discuss_sidebar_category_chat_open': True,
|
|
},
|
|
}]):
|
|
settings.set_res_users_settings({'is_discuss_sidebar_category_chat_open': True})
|
|
|
|
@users('employee')
|
|
def test_set_res_users_settings_should_set_settings_properly(self):
|
|
settings = self.user_employee.res_users_settings_id
|
|
settings.set_res_users_settings({'is_discuss_sidebar_category_chat_open': True})
|
|
self.assertEqual(
|
|
settings.is_discuss_sidebar_category_chat_open,
|
|
True,
|
|
"category state should be updated correctly"
|
|
)
|