diff --git a/addons/website/models/website.py b/addons/website/models/website.py index 581ef97a380..0dfbb1402a9 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -573,7 +573,7 @@ class Website(models.Model): page_url = '/' + slugify(name, max_length=1024, path=True) page_url = self.get_unique_path(page_url) page_key = slugify(name) - result = dict({'url': page_url, 'view_id': False}) + result = {'url': page_url} if not name: name = 'Home' @@ -588,6 +588,7 @@ class Website(models.Model): 'arch': template_record.arch.replace(template, key), 'name': name, }) + result['view_id'] = view.id if view.arch_fs: view.arch_fs = False @@ -600,15 +601,16 @@ class Website(models.Model): 'view_id': view.id, 'track': True, }) - result['view_id'] = view.id + result['page_id'] = page.id if add_menu: - self.env['website.menu'].create({ + menu = self.env['website.menu'].create({ 'name': name, 'url': page_url, 'parent_id': website.menu_id.id, 'page_id': page.id, 'website_id': website.id, }) + result['menu_id'] = menu.id return result @api.model diff --git a/addons/website_event/__manifest__.py b/addons/website_event/__manifest__.py index 90d1d7556b7..647f6e1ff51 100644 --- a/addons/website_event/__manifest__.py +++ b/addons/website_event/__manifest__.py @@ -3,7 +3,7 @@ { 'name': 'Events', - 'version': '1.3', + 'version': '1.4', 'category': 'Marketing/Events', 'sequence': 140, 'summary': 'Publish events, sell tickets', diff --git a/addons/website_event/models/event_event.py b/addons/website_event/models/event_event.py index f72e7857302..ab278a7e980 100644 --- a/addons/website_event/models/event_event.py +++ b/addons/website_event/models/event_event.py @@ -36,12 +36,30 @@ class Event(models.Model): website_menu = fields.Boolean( string='Website Menu', compute='_compute_website_menu', readonly=False, store=True, - help="Creates menus Introduction, Location and Register on the page " - "of the event on the website.") + help="Allows to display and manage event-specific menus on website.") menu_id = fields.Many2one('website.menu', 'Event Menu', copy=False) menu_register_cta = fields.Boolean( 'Extra Register Button', compute='_compute_menu_register_cta', readonly=False, store=True) + # sub-menus management + introduction_menu = fields.Boolean( + "Introduction Menu", compute="_compute_website_menu_data", + readonly=False, store=True) + introduction_menu_ids = fields.One2many( + "website.event.menu", "event_id", string="Introduction Menus", + domain=[("menu_type", "=", "introduction")]) + location_menu = fields.Boolean( + "Location Menu", compute="_compute_website_menu_data", + readonly=False, store=True) + location_menu_ids = fields.One2many( + "website.event.menu", "event_id", string="Location Menus", + domain=[("menu_type", "=", "location_menu")]) + register_menu = fields.Boolean( + "Register Menu", compute="_compute_website_menu_data", + readonly=False, store=True) + register_menu_ids = fields.One2many( + "website.event.menu", "event_id", string="Register Menus", + domain=[("menu_type", "=", "register")]) community_menu = fields.Boolean( "Community Menu", compute="_compute_community_menu", readonly=False, store=True, @@ -120,6 +138,15 @@ class Event(models.Model): for event in self: event.community_menu = False + @api.depends("website_menu") + def _compute_website_menu_data(self): + """ Synchronize with website_menu at change and let people update them + at will afterwards. """ + for event in self: + event.introduction_menu = event.website_menu + event.location_menu = event.website_menu + event.register_menu = event.website_menu + @api.depends("event_type_id", "website_menu") def _compute_menu_register_cta(self): """ At type onchange: synchronize. At website_menu update: synchronize. """ @@ -186,10 +213,15 @@ class Event(models.Model): :return list: list of fields, each of which triggering a menu update like website_menu, website_track, ... """ - return ['website_menu', 'community_menu'] + return ['community_menu', 'introduction_menu', 'location_menu', 'register_menu'] def _get_menu_type_field_matching(self): - return {'community': 'community_menu'} + return { + 'community': 'community_menu', + 'introduction': 'introduction_menu', + 'location': 'location_menu', + 'register': 'register_menu', + } def _split_menus_state_by_field(self): """ For each field linked to a menu, get the set of events having this @@ -248,15 +280,12 @@ class Event(models.Model): """ self.ensure_one() return [ - (_('Introduction'), False, 'website_event.template_intro', 1, False), - (_('Location'), False, 'website_event.template_location', 50, False), - (_('Register'), '/event/%s/register' % slug(self), False, 100, False), + (_('Introduction'), False, 'website_event.template_intro', 1, 'introduction'), + (_('Location'), False, 'website_event.template_location', 50, 'location'), + (_('Register'), '/event/%s/register' % slug(self), False, 100, 'register'), + (_('Community'), '/event/%s/community' % slug(self), False, 80, 'community'), ] - def _get_community_menu_entries(self): - self.ensure_one() - return [(_('Community'), '/event/%s/community' % slug(self), False, 80, 'community')] - def _update_website_menus(self, menus_update_by_field=None): """ Synchronize event configuration and its menu entries for frontend. @@ -267,13 +296,16 @@ class Event(models.Model): elif event.website_menu and not event.menu_id: root_menu = self.env['website.menu'].sudo().create({'name': event.name, 'website_id': event.website_id.id}) event.menu_id = root_menu - if event.website_menu and (not menus_update_by_field or event in menus_update_by_field.get('website_menu')): - for name, url, xml_id, menu_sequence, menu_type in event._get_website_menu_entries(): - event._create_menu(menu_sequence, name, url, xml_id, menu_type=menu_type) if event.menu_id and (not menus_update_by_field or event in menus_update_by_field.get('community_menu')): - event._update_website_menu_entry('community_menu', 'community_menu_ids', '_get_community_menu_entries') + event._update_website_menu_entry('community_menu', 'community_menu_ids', 'community') + if event.menu_id and (not menus_update_by_field or event in menus_update_by_field.get('introduction_menu')): + event._update_website_menu_entry('introduction_menu', 'introduction_menu_ids', 'introduction') + if event.menu_id and (not menus_update_by_field or event in menus_update_by_field.get('location_menu')): + event._update_website_menu_entry('location_menu', 'location_menu_ids', 'location') + if event.menu_id and (not menus_update_by_field or event in menus_update_by_field.get('register_menu')): + event._update_website_menu_entry('register_menu', 'register_menu_ids', 'register') - def _update_website_menu_entry(self, fname_bool, fname_o2m, method_name): + def _update_website_menu_entry(self, fname_bool, fname_o2m, fmenu_type): """ Generic method to create menu entries based on a flag on event. This method is a bit obscure, but is due to preparation of adding new menus entries and pages for event in a stable version, leading to some constraints @@ -288,38 +320,44 @@ class Event(models.Model): self.ensure_one() new_menu = None + menu_data = [menu_info for menu_info in self._get_website_menu_entries() + if menu_info[4] == fmenu_type] if self[fname_bool] and not self[fname_o2m]: # menus not found but boolean True: get menus to create - for sequence, menu_data in enumerate(getattr(self, method_name)()): - # some modules have 4 data: name, url, xml_id, menu_type; however we - # plan to support sequence in future modules, so this hackish code is - # necessary to avoid crashing. Not nice, but stable target = meh. - if len(menu_data) == 4: - (name, url, xml_id, menu_type) = menu_data - menu_sequence = sequence - elif len(menu_data) == 5: - (name, url, xml_id, menu_sequence, menu_type) = menu_data - new_menu = self._create_menu(menu_sequence, name, url, xml_id, menu_type=menu_type) + for name, url, xml_id, menu_sequence, menu_type in menu_data: + new_menu = self._create_menu(menu_sequence, name, url, xml_id, menu_type) elif not self[fname_bool]: # will cascade delete to the website.event.menu self[fname_o2m].mapped('menu_id').sudo().unlink() return new_menu - def _create_menu(self, sequence, name, url, xml_id, menu_type=False): - """ If url: create a website menu. Menu leads directly to the URL that - should be a valid route. If xml_id: create a new page, take its url back - thanks to new_page of website, then link it to a menu. Template is - duplicated and linked to a new url, meaning each menu will have its own - copy of the template. + def _create_menu(self, sequence, name, url, xml_id, menu_type): + """ Create a new menu for the current event. + + If url: create a website menu. Menu leads directly to the URL that + should be a valid route. + + If xml_id: create a new page using the qweb template given by its + xml_id. Take its url back thanks to new_page of website, then link + it to a menu. Template is duplicated and linked to a new url, meaning + each menu will have its own copy of the template. This is currently + limited to two menus: introduction and location. :param menu_type: type of menu. Mainly used for inheritance purpose - allowing more fine-grain tuning of menus. """ + allowing more fine-grain tuning of menus. + """ self.check_access_rights('write') + view_id = False if not url: - self.env['ir.ui.view'].with_context(_force_unlink=True).sudo().search([('name', '=', name + ' ' + self.name)]).unlink() - page_result = self.env['website'].sudo().new_page(name + ' ' + self.name, template=xml_id, ispage=False) + # add_menu=False, ispage=False -> simply create a new ir.ui.view with name + # and template + page_result = self.env['website'].sudo().new_page( + name=name + ' ' + self.name, template=xml_id, + add_menu=False, ispage=False) url = "/event/" + slug(self) + "/page" + page_result['url'] # url contains starting "/" + view_id = page_result['view_id'] + website_menu = self.env['website.menu'].sudo().create({ 'name': name, 'url': url, @@ -327,12 +365,12 @@ class Event(models.Model): 'sequence': sequence, 'website_id': self.website_id.id, }) - if menu_type: - self.env['website.event.menu'].create({ - 'menu_id': website_menu.id, - 'event_id': self.id, - 'menu_type': menu_type, - }) + self.env['website.event.menu'].create({ + 'menu_id': website_menu.id, + 'event_id': self.id, + 'menu_type': menu_type, + 'view_id': view_id, + }) return website_menu # ------------------------------------------------------------ diff --git a/addons/website_event/models/website_event_menu.py b/addons/website_event/models/website_event_menu.py index b19c7d8ca75..63a2c63f8a6 100644 --- a/addons/website_event/models/website_event_menu.py +++ b/addons/website_event/models/website_event_menu.py @@ -10,6 +10,14 @@ class EventMenu(models.Model): menu_id = fields.Many2one('website.menu', string='Menu', ondelete='cascade') event_id = fields.Many2one('event.event', string='Event', ondelete='cascade') - menu_type = fields.Selection([ - ('community', 'Community Menu')], string="Menu Type", - ondelete={'community': 'cascade'}, required=True) + view_id = fields.Many2one('ir.ui.view', string='View', ondelete='cascade', help='Used when not being an url based menu') + menu_type = fields.Selection( + [('community', 'Community Menu'), + ('introduction', 'Introduction'), + ('location', 'Location'), + ('register', 'Register'), + ], string="Menu Type", required=True) + + def unlink(self): + self.view_id.sudo().unlink() + return super(EventMenu, self).unlink() diff --git a/addons/website_event/models/website_menu.py b/addons/website_event/models/website_menu.py index 1b96cd8552c..00f3a90814d 100644 --- a/addons/website_event/models/website_menu.py +++ b/addons/website_event/models/website_menu.py @@ -8,8 +8,7 @@ class WebsiteMenu(models.Model): _inherit = "website.menu" def unlink(self): - """ Override to synchronize event configuration fields with menu deletion. - This should be cleaned in upcoming versions. """ + """ Override to synchronize event configuration fields with menu deletion. """ event_updates = {} website_event_menus = self.env['website.event.menu'].search([('menu_id', 'in', self.ids)]) for event_menu in website_event_menus: @@ -18,7 +17,9 @@ class WebsiteMenu(models.Model): if event_menu.menu_type == menu_type: to_update.append(fname) - # call super that resumes the unlink of menus entries (including website event menus) + # manually remove website_event_menus to call their ``unlink`` method. Otherwise + # super unlinks at db level and skip model-specific behavior. + website_event_menus.unlink() res = super(WebsiteMenu, self).unlink() # update events diff --git a/addons/website_event/tests/__init__.py b/addons/website_event/tests/__init__.py index 77fa25d467c..3865a64e323 100644 --- a/addons/website_event/tests/__init__.py +++ b/addons/website_event/tests/__init__.py @@ -1,9 +1,6 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import common -from . import test_event_internals -from . import test_ui -from . import test_visitor_events +from . import test_event_menus +from . import test_event_visitor from . import test_website_event -from . import test_website_event_access diff --git a/addons/website_event/tests/common.py b/addons/website_event/tests/common.py index 3773179fe83..7fe660d403f 100644 --- a/addons/website_event/tests/common.py +++ b/addons/website_event/tests/common.py @@ -73,28 +73,28 @@ class TestWebsiteEventCommon(TestEventCommon): ) def _get_menus(self): - return set(['Introduction', 'Location', 'Register']) + return set(['Introduction', 'Location', 'Register', 'Community']) - def _assert_website_menus(self, event, menu_entries=None): + def _assert_website_menus(self, event, menus_in=None, menus_out=None): self.assertTrue(event.menu_id) - if menu_entries is None: - menu_entries = self._get_menus() + if menus_in is None: + menus_in = list(self._get_menus()) menus = self.env['website.menu'].search([('parent_id', '=', event.menu_id.id)]) - self.assertEqual(len(menus), len(menu_entries)) - self.assertEqual(set(menus.mapped('name')), menu_entries) + self.assertTrue(len(menus) >= len(menus_in)) + self.assertTrue(all(menu_name in menus.mapped('name') for menu_name in menus_in)) + if menus_out: + self.assertTrue(all(menu_name not in menus.mapped('name') for menu_name in menus_out)) for page_specific in ['Introduction', 'Location']: view = self.env['ir.ui.view'].search( [('name', '=', page_specific + ' ' + event.name)] ) - if page_specific in menu_entries: + if page_specific in menus_in: self.assertTrue(bool(view)) - # TDE FIXME: page deletion not done in 13.3 for Introduction/Location, difficult to fix - # without website.event.menu model (or crappy code based on name) - # else: - # self.assertFalse(bool(view)) + else: + self.assertFalse(bool(view)) class TestEventOnlineCommon(TestEventCommon, EventDtPatcher): diff --git a/addons/website_event/tests/test_event_internals.py b/addons/website_event/tests/test_event_internals.py deleted file mode 100644 index 9339da20e6a..00000000000 --- a/addons/website_event/tests/test_event_internals.py +++ /dev/null @@ -1,47 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from datetime import datetime, timedelta - -from odoo import fields -from odoo.addons.website_event.tests.common import TestWebsiteEventCommon -from odoo.tests.common import users - - -class TestEventWebsite(TestWebsiteEventCommon): - - @users('user_eventmanager') - def test_menu_create(self): - event = self.env['event.event'].create({ - 'name': 'TestEvent', - 'date_begin': fields.Datetime.to_string(datetime.today() + timedelta(days=1)), - 'date_end': fields.Datetime.to_string(datetime.today() + timedelta(days=15)), - 'website_menu': True, - 'community_menu': False, - }) - self._assert_website_menus(event) - - @users('user_event_web_manager') - def test_menu_management_frontend(self): - event = self.env['event.event'].create({ - 'name': 'TestEvent', - 'date_begin': fields.Datetime.to_string(datetime.today() + timedelta(days=1)), - 'date_end': fields.Datetime.to_string(datetime.today() + timedelta(days=15)), - 'website_menu': True, - 'community_menu': False, - }) - self.assertTrue(event.website_menu) - self._assert_website_menus(event) - - introduction_menu = event.menu_id.child_id.filtered(lambda menu: menu.name == 'Introduction') - introduction_menu.unlink() - - self.assertTrue(event.website_menu) - self._assert_website_menus(event, set(['Location', 'Register'])) - - @users('user_eventmanager') - def test_menu_update(self): - event = self.env['event.event'].browse(self.event_0.id) - self.assertFalse(event.menu_id) - event.website_menu = True - self._assert_website_menus(event) diff --git a/addons/website_event/tests/test_event_menus.py b/addons/website_event/tests/test_event_menus.py new file mode 100644 index 00000000000..aa65e159119 --- /dev/null +++ b/addons/website_event/tests/test_event_menus.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from datetime import datetime, timedelta + +from odoo import fields +from odoo.addons.website_event.tests.common import TestWebsiteEventCommon +from odoo.tests.common import users + + +class TestEventMenus(TestWebsiteEventCommon): + + @users('user_eventmanager') + def test_menu_management(self): + event = self.env['event.event'].create({ + 'name': 'TestEvent', + 'date_begin': fields.Datetime.to_string(datetime.today() + timedelta(days=1)), + 'date_end': fields.Datetime.to_string(datetime.today() + timedelta(days=15)), + 'website_menu': True, + 'community_menu': False, + }) + self.assertTrue(event.website_menu) + self.assertTrue(event.introduction_menu) + self.assertTrue(event.location_menu) + self.assertTrue(event.register_menu) + self.assertFalse(event.community_menu) + self._assert_website_menus(event, ['Introduction', 'Location', 'Register'], menus_out=['Community']) + + event.community_menu = True + self._assert_website_menus(event, ['Introduction', 'Location', 'Register', 'Community']) + + # test create without any requested menus + event = self.env['event.event'].create({ + 'name': 'TestEvent', + 'date_begin': fields.Datetime.to_string(datetime.today() + timedelta(days=1)), + 'date_end': fields.Datetime.to_string(datetime.today() + timedelta(days=15)), + 'website_menu': False, + }) + self.assertFalse(event.website_menu) + self.assertFalse(event.introduction_menu) + self.assertFalse(event.location_menu) + self.assertFalse(event.register_menu) + self.assertFalse(event.community_menu) + self.assertFalse(event.menu_id) + + # test update of website_menu triggering 3 sub menus + event.write({'website_menu': True}) + self._assert_website_menus(event, ['Introduction', 'Location', 'Register'], menus_out=['Community']) + + @users('user_event_web_manager') + def test_menu_management_frontend(self): + event = self.env['event.event'].create({ + 'name': 'TestEvent', + 'date_begin': fields.Datetime.to_string(datetime.today() + timedelta(days=1)), + 'date_end': fields.Datetime.to_string(datetime.today() + timedelta(days=15)), + 'website_menu': True, + 'community_menu': False, + }) + self._assert_website_menus(event, ['Introduction', 'Location', 'Register'], menus_out=['Community']) + + # simulate menu removal from frontend: aka unlinking a menu + event.menu_id.child_id.filtered(lambda menu: menu.name == 'Introduction').unlink() + + self.assertTrue(event.website_menu) + self._assert_website_menus(event, ['Location', 'Register'], menus_out=['Introduction', 'Community']) + + # re-created from backend + event.introduction_menu = True + self._assert_website_menus(event, ['Introduction', 'Location', 'Register'], menus_out=['Community']) diff --git a/addons/website_event/tests/test_visitor_events.py b/addons/website_event/tests/test_event_visitor.py similarity index 93% rename from addons/website_event/tests/test_visitor_events.py rename to addons/website_event/tests/test_event_visitor.py index 814cd531ac5..b9ef29c6547 100644 --- a/addons/website_event/tests/test_visitor_events.py +++ b/addons/website_event/tests/test_event_visitor.py @@ -4,10 +4,11 @@ from datetime import datetime, timedelta from odoo import fields -from odoo.addons.event.tests.common import TestEventCommon +from odoo.addons.website_event.tests.common import TestWebsiteEventCommon -class TestVisitorEvents(TestEventCommon): +class TestEventVisitor(TestWebsiteEventCommon): + def test_visitor_events(self): event_1 = self.env['event.event'].create({ 'name': 'OtherEvent', diff --git a/addons/website_event/tests/test_ui.py b/addons/website_event/tests/test_ui.py deleted file mode 100644 index ececf2096f5..00000000000 --- a/addons/website_event/tests/test_ui.py +++ /dev/null @@ -1,11 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -import odoo.tests -from odoo import tools - - -@odoo.tests.tagged('post_install', '-at_install') -class TestUi(odoo.tests.HttpCase): - def test_admin(self): - self.start_tour("/", 'website_event_tour', login='admin', step_delay=100) diff --git a/addons/website_event/tests/test_website_event.py b/addons/website_event/tests/test_website_event.py index 54e657d2c9f..36ce39b74c8 100644 --- a/addons/website_event/tests/test_website_event.py +++ b/addons/website_event/tests/test_website_event.py @@ -1,13 +1,121 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from datetime import datetime, timedelta + +from odoo.addons.base.tests.common import HttpCaseWithUserDemo +from odoo.addons.mail.tests.common import mail_new_test_user from odoo.addons.website.tests.test_base_url import TestUrlCommon +from odoo.addons.website_event.tests.common import TestWebsiteEventCommon from odoo.tests import tagged +from odoo.tools import mute_logger + + +@tagged('post_install', '-at_install') +class TestUi(HttpCaseWithUserDemo): + + def test_website_event_tour_admin(self): + self.start_tour("/", 'website_event_tour', login='admin', step_delay=100) @tagged('-at_install', 'post_install') -class TestUrlCanonical(TestUrlCommon): +class TestURLs(TestUrlCommon): - def test_01_canonical_url(self): + def test_canonical_url(self): self._assertCanonical('/event?date=all', self.domain + '/event') self._assertCanonical('/event?date=old', self.domain + '/event?date=old') + + +@tagged('post_install', '-at_install') +class TestWebsiteAccess(HttpCaseWithUserDemo, TestWebsiteEventCommon): + + def setUp(self): + super(TestWebsiteAccess, self).setUp() + + self.events = self.env['event.event'].create([{ + 'name': 'Event 0 - Sitemap test', + 'website_published': True, + 'date_begin': datetime.today() - timedelta(days=1), + 'date_end': datetime.today() + timedelta(days=1), + }, { + 'name': 'Event 1 - Sitemap test', + 'website_published': True, + 'date_begin': datetime.today() - timedelta(days=1), + 'date_end': datetime.today() + timedelta(days=1), + }, { + 'name': 'Event 2 - Sitemap test', + 'date_begin': datetime.today() - timedelta(days=1), + 'date_end': datetime.today() + timedelta(days=1), + }]) + + self.portal_user = mail_new_test_user( + self.env, name='Smeagol', login='user_portal', password='user_portal', email='portal@example.com', + groups='base.group_portal' + ) + + def test_website_access_event_manager(self): + """ Event managers are allowed to access both published and unpublished events """ + self.authenticate('user_eventmanager', 'user_eventmanager') + published_events = self.events.filtered(lambda event: event.website_published) + resp = self.url_open('/event/%i' % published_events[0].id) + self.assertEqual(resp.status_code, 200, 'Managers must have access to published event.') + + unpublished_events = self.events.filtered(lambda event: not event.website_published) + resp = self.url_open('/event/%i' % unpublished_events[0].id) + self.assertEqual(resp.status_code, 200, 'Managers must have access to unpublished event.') + + resp = self.url_open('/event') + self.assertTrue(published_events[0].name in resp.text, 'Managers must see the unpublished events.') + self.assertTrue(unpublished_events[0].name in resp.text, 'Managers must see the published events.') + + def test_website_access_event_uer(self): + """ Event users are allowed to access both published and unpublished events """ + self.authenticate('user_eventuser', 'user_eventuser') + published_events = self.events.filtered(lambda event: event.website_published) + resp = self.url_open('/event/%i' % published_events[0].id) + self.assertEqual(resp.status_code, 200, 'Event user must have access to published event.') + + unpublished_events = self.events.filtered(lambda event: not event.website_published) + resp = self.url_open('/event/%i' % unpublished_events[0].id) + self.assertEqual(resp.status_code, 200, 'Event user must have access to unpublished event.') + + resp = self.url_open('/event') + self.assertTrue(published_events[0].name in resp.text, 'Event user must see the unpublished events.') + self.assertTrue(unpublished_events[0].name in resp.text, 'Event user must see the published events.') + + @mute_logger('odoo.addons.http_routing.models.ir_http') + def test_website_access_portal(self): + """ Portal users access only published events """ + self.authenticate('user_portal', 'user_portal') + published_events = self.events.filtered(lambda event: event.website_published) + resp = self.url_open('/event/%i' % published_events[0].id) + self.assertEqual(resp.status_code, 200, 'Portal user must have access to published event.') + + unpublished_events = self.events.filtered(lambda event: not event.website_published) + resp = self.url_open('/event/%i' % unpublished_events[0].id) + self.assertEqual(resp.status_code, 403, 'Portal user must not have access to unpublished event.') + + resp = self.url_open('/event') + self.assertTrue(published_events[0].name in resp.text, 'Portal must see the published events.') + self.assertFalse(unpublished_events[0].name in resp.text, 'Portal should not see the unpublished events.') + + @mute_logger('odoo.addons.http_routing.models.ir_http') + def test_website_access_public(self): + """ Public users access only published events """ + published_events = self.events.filtered(lambda event: event.website_published) + resp = self.url_open('/event/%i' % published_events[0].id) + self.assertEqual(resp.status_code, 200, 'Public must have access to published event') + + unpublished_events = self.events.filtered(lambda event: not event.website_published) + resp = self.url_open('/event/%i' % unpublished_events[0].id) + self.assertEqual(resp.status_code, 403, 'Public must not have access to unpublished event') + + resp = self.url_open('/event') + self.assertTrue(published_events[0].name in resp.text, 'Public must see the published events.') + self.assertFalse(unpublished_events[0].name in resp.text, 'Public should not see the unpublished events.') + + def test_sitemap(self): + resp = self.url_open('/sitemap.xml') + self.assertTrue('/event/event-0' in resp.text, 'Published events must be present in the sitemap') + self.assertTrue('/event/event-1' in resp.text, 'Published events must be present in the sitemap') + self.assertFalse('/event/event-2' in resp.text, 'Unpublished events must not be present in the sitemap') diff --git a/addons/website_event/tests/test_website_event_access.py b/addons/website_event/tests/test_website_event_access.py deleted file mode 100644 index 1782e058c22..00000000000 --- a/addons/website_event/tests/test_website_event_access.py +++ /dev/null @@ -1,125 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from datetime import datetime, timedelta - -from odoo.addons.mail.tests.common import mail_new_test_user -from odoo.tests import HttpCase, tagged -from odoo.tools import mute_logger - - -@tagged('post_install', '-at_install') -class TestWebsiteEventAccess(HttpCase): - def setUp(self): - super(TestWebsiteEventAccess, self).setUp() - - self.events = self.env['event.event'].create([{ - 'name': 'Event 0 - Sitemap test', - 'website_published': True, - 'date_begin': datetime.today() - timedelta(days=1), - 'date_end': datetime.today() + timedelta(days=1), - }, { - 'name': 'Event 1 - Sitemap test', - 'website_published': True, - 'date_begin': datetime.today() - timedelta(days=1), - 'date_end': datetime.today() + timedelta(days=1), - }, { - 'name': 'Event 2 - Sitemap test', - 'date_begin': datetime.today() - timedelta(days=1), - 'date_end': datetime.today() + timedelta(days=1), - }]) - - self.event_manager = mail_new_test_user( - self.env, name='Gandalf le blanc', login='event_manager', password='event_manager', email='event.manager@example.com', - groups='event.group_event_manager,base.group_user' - ) - - self.event_user = mail_new_test_user( - self.env, name='Frodon Sacquet', login='event_user', password='event_user', email='event.user@example.com', - groups='event.group_event_user,base.group_user' - ) - - self.portal_user = mail_new_test_user( - self.env, name='Smeagol', login='user_portal', password='user_portal', email='portal@example.com', - groups='base.group_portal' - ) - - def test_sitemap(self): - resp = self.url_open('/sitemap.xml') - self.assertTrue('/event/event-0' in resp.text, 'Published events must be present in the sitemap') - self.assertTrue('/event/event-1' in resp.text, 'Published events must be present in the sitemap') - self.assertFalse('/event/event-2' in resp.text, 'Unpublished events must not be present in the sitemap') - - def test_events_access_1(self): - """Access to a published event with public user.""" - published_events = self.events.filtered(lambda event: event.website_published) - resp = self.url_open('/event/%i' % published_events[0].id) - self.assertEqual(resp.status_code, 200, 'We must have access to published event') - - def test_events_access_2(self): - """Access to an unpublished event with public user.""" - with mute_logger('odoo.addons.http_routing.models.ir_http'): - unpublished_events = self.events.filtered(lambda event: not event.website_published) - resp = self.url_open('/event/%i' % unpublished_events[0].id) - self.assertEqual(resp.status_code, 403, 'We must not have access to unpublished event') - - def test_events_access_3(self): - """Access to an published event with admin user.""" - self.authenticate('event_manager', 'event_manager') - published_events = self.events.filtered(lambda event: event.website_published) - resp = self.url_open('/event/%i' % published_events[0].id) - self.assertEqual(resp.status_code, 200, 'Admin must have access to published event.') - - def test_events_access_4(self): - """Access to an unpublished event with admin user.""" - self.authenticate('event_manager', 'event_manager') - unpublished_events = self.events.filtered(lambda event: not event.website_published) - resp = self.url_open('/event/%i' % unpublished_events[0].id) - self.assertEqual(resp.status_code, 200, 'Admin must have access to unpublished event.') - - def test_events_access_5(self): - """Access to an published event with event user.""" - self.authenticate('event_user', 'event_user') - published_events = self.events.filtered(lambda event: event.website_published) - resp = self.url_open('/event/%i' % published_events[0].id) - self.assertEqual(resp.status_code, 200, 'Event user must have access to published event.') - - def test_events_access_6(self): - """Access to an unpublished event with event user.""" - self.authenticate('event_user', 'event_user') - unpublished_events = self.events.filtered(lambda event: not event.website_published) - resp = self.url_open('/event/%i' % unpublished_events[0].id) - self.assertEqual(resp.status_code, 200, 'Event user must have access to unpublished event.') - - def test_events_access_7(self): - """Access to an published event with portal user.""" - self.authenticate('user_portal', 'user_portal') - published_events = self.events.filtered(lambda event: event.website_published) - resp = self.url_open('/event/%i' % published_events[0].id) - self.assertEqual(resp.status_code, 200, 'Portal user must have access to published event.') - - def test_events_access_8(self): - """Access to an unpublished event with portal user.""" - with mute_logger('odoo.addons.http_routing.models.ir_http'): - self.authenticate('user_portal', 'user_portal') - unpublished_events = self.events.filtered(lambda event: not event.website_published) - resp = self.url_open('/event/%i' % unpublished_events[0].id) - self.assertEqual(resp.status_code, 403, 'Portal user must not have access to unpublished event.') - - def test_events_home_page_1(self): - """Portal can only view the published events.""" - self.authenticate('user_portal', 'user_portal') - published_event = self.events.filtered(lambda event: event.website_published)[0] - unpublished_event = self.events.filtered(lambda event: not event.website_published)[0] - resp = self.url_open('/event') - self.assertTrue(unpublished_event.name not in resp.text, 'Portal should not see the unpublished events.') - self.assertTrue(published_event.name in resp.text, 'Portal must see the published events.') - - def test_events_home_page_2(self): - """Admin can see all the events.""" - self.authenticate('event_manager', 'event_manager') - published_event = self.events.filtered(lambda event: event.website_published)[0] - unpublished_event = self.events.filtered(lambda event: not event.website_published)[0] - resp = self.url_open('/event') - self.assertTrue(unpublished_event.name in resp.text, 'Admin must see the unpublished events.') - self.assertTrue(published_event.name in resp.text, 'Admin must see the published events.') diff --git a/addons/website_event/views/event_event_views.xml b/addons/website_event/views/event_event_views.xml index 369e0658516..4de480e95bf 100644 --- a/addons/website_event/views/event_event_views.xml +++ b/addons/website_event/views/event_event_views.xml @@ -23,6 +23,10 @@