diff options
| author | std-odoo <std@odoo.com> | 2020-08-13 12:38:02 +0000 |
|---|---|---|
| committer | Thibault Delavallée <tde@odoo.com> | 2020-08-17 16:29:49 +0000 |
| commit | 3dfb3c1e747bf8b78a20acff314212eca2f22998 (patch) | |
| tree | 974d9423864b45edc0ac8b575983aecd777eb825 /addons/website_event | |
| parent | d3b18979bfb5496fa4370fdf03a806c469127730 (diff) | |
[FIX] website_event(_*): improve user flow and experience from frontend
PURPOSE
Provide some fixes after internal test deployment of event online features.
Notably: user registration flow, various fixes in templates.
Also add some unit tests to avoid regressions while working on event features.
LINKS
Task ID-2169118
odoo/odoo#55967
odoo/enterprise#12438
X-original-commit: e66684b23eebaadc3df7b908427d3d7a83d4f0a0
Diffstat (limited to 'addons/website_event')
| -rw-r--r-- | addons/website_event/controllers/main.py | 15 | ||||
| -rw-r--r-- | addons/website_event/models/event_event.py | 6 | ||||
| -rw-r--r-- | addons/website_event/security/event_security.xml | 4 | ||||
| -rw-r--r-- | addons/website_event/security/ir.model.access.csv | 2 | ||||
| -rw-r--r-- | addons/website_event/tests/__init__.py | 1 | ||||
| -rw-r--r-- | addons/website_event/tests/test_website_event_access.py | 126 | ||||
| -rw-r--r-- | addons/website_event/views/event_templates.xml | 6 |
7 files changed, 148 insertions, 12 deletions
diff --git a/addons/website_event/controllers/main.py b/addons/website_event/controllers/main.py index 66a94677953..0665dce85bb 100644 --- a/addons/website_event/controllers/main.py +++ b/addons/website_event/controllers/main.py @@ -5,6 +5,7 @@ import babel.dates import re import werkzeug from werkzeug.datastructures import OrderedMultiDict +from werkzeug.exceptions import NotFound from ast import literal_eval from collections import defaultdict @@ -14,6 +15,7 @@ from dateutil.relativedelta import relativedelta from odoo import fields, http, _ from odoo.addons.http_routing.models.ir_http import slug from odoo.addons.website.controllers.main import QueryURL +from odoo.addons.event.controllers.main import EventController from odoo.http import request from odoo.osv import expression from odoo.tools.misc import get_lang, format_date @@ -28,7 +30,7 @@ class WebsiteEventController(http.Controller): @http.route(['/event', '/event/page/<int:page>', '/events', '/events/page/<int:page>'], type='http', auth="public", website=True, sitemap=sitemap_event) def events(self, page=1, **searches): Event = request.env['event.event'] - EventType = request.env['event.type'] + SudoEventType = request.env['event.type'].sudo() searches.setdefault('search', '') searches.setdefault('date', 'all') @@ -96,7 +98,7 @@ class WebsiteEventController(http.Controller): current_date = date[1] if searches["type"] != 'all': - current_type = EventType.browse(int(searches['type'])) + current_type = SudoEventType.browse(int(searches['type'])) domain_search["type"] = [("event_type_id", "=", int(searches["type"]))] if searches["country"] != 'all' and searches["country"] != 'online': @@ -297,6 +299,9 @@ class WebsiteEventController(http.Controller): @http.route(['/event/<model("event.event"):event>/registration/new'], type='json', auth="public", methods=['POST'], website=True) def registration_new(self, event, **post): + if not event.can_access_from_current_website(): + raise werkzeug.exceptions.NotFound() + tickets = self._process_tickets_form(event, post) availability_check = True if event.seats_limited: @@ -355,11 +360,11 @@ class WebsiteEventController(http.Controller): raise werkzeug.exceptions.NotFound() registrations = self._process_attendees_form(event, post) - attendees = self._create_attendees_from_registration_post(event, registrations) + attendees_sudo = self._create_attendees_from_registration_post(event, registrations) urls = event._get_event_resource_urls() return request.render("website_event.registration_complete", { - 'attendees': attendees, + 'attendees': attendees_sudo, 'event': event, 'google_url': urls.get('google_url'), 'iCal_url': urls.get('iCal_url') @@ -373,6 +378,6 @@ class WebsiteEventController(http.Controller): except: pass else: - # perform a search to filter on existing / valid tags implicitely + # perform a search to filter on existing / valid tags implicitely + apply rules on color tags = request.env['event.tag'].search([('id', 'in', tag_ids)]) return tags diff --git a/addons/website_event/models/event_event.py b/addons/website_event/models/event_event.py index 01d76489777..925aed32996 100644 --- a/addons/website_event/models/event_event.py +++ b/addons/website_event/models/event_event.py @@ -45,7 +45,7 @@ class Event(models.Model): email = self.env.user.partner_id.email for event in self: domain = ['&', '|', ('email', '=', email), ('partner_id', '=', self.env.user.partner_id.id), ('event_id', '=', event.id)] - event.is_participating = self.env['event.registration'].search_count(domain) + event.is_participating = self.env['event.registration'].sudo().search_count(domain) else: self.is_participating = False @@ -193,6 +193,10 @@ class Event(models.Model): # ------------------------------------------------------------ def google_map_link(self, zoom=8): + """ Temporary method for stable """ + return self._google_map_link(zoom=zoom) + + def _google_map_link(self, zoom=8): self.ensure_one() if self.address_id: return self.sudo().address_id.google_map_link(zoom=zoom) diff --git a/addons/website_event/security/event_security.xml b/addons/website_event/security/event_security.xml index d34a1f76a48..857e758e9c0 100644 --- a/addons/website_event/security/event_security.xml +++ b/addons/website_event/security/event_security.xml @@ -2,7 +2,7 @@ <odoo> <data noupdate="1"> <record id="event_event_public" model="ir.rule"> - <field name="name">event: Public</field> + <field name="name">Event: public/portal: published read</field> <field name="model_id" ref="event.model_event_event"/> <field name="domain_force">[('website_published', '=', True)]</field> <field name="groups" eval="[(4, ref('base.group_public')), (4, ref('base.group_portal'))]"/> @@ -13,7 +13,7 @@ </record> <record id="ir_rule_event_event_ticket_public" model="ir.rule"> - <field name="name">Event ticket: public/portal may read published</field> + <field name="name">Event Ticket: public/portal: published read</field> <field name="model_id" ref="event.model_event_event_ticket"/> <field name="domain_force">[('event_id.website_published', '=', True)]</field> <field name="groups" eval="[(4, ref('base.group_public')), (4, ref('base.group_portal'))]"/> diff --git a/addons/website_event/security/ir.model.access.csv b/addons/website_event/security/ir.model.access.csv index e55cfc58bbf..985c14e5190 100644 --- a/addons/website_event/security/ir.model.access.csv +++ b/addons/website_event/security/ir.model.access.csv @@ -1,7 +1,7 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_event_event_public,event.event.public,event.model_event_event,base.group_public,1,0,0,0 access_event_event_portal,event.event.portal,event.model_event_event,base.group_portal,1,0,0,0 -access_event_type_public,event.type.public,event.model_event_type,,1,0,0,0 +access_event_type_public,event.type.public,event.model_event_type,,0,0,0,0 access_event_event_ticket_public,event.event.ticket.public,event.model_event_event_ticket,base.group_public,1,0,0,0 access_event_event_ticket_portal,event.event.ticket.portal,event.model_event_event_ticket,base.group_portal,1,0,0,0 access_event_category_public,event.tag.category.public,event.model_event_tag_category,,1,0,0,0 diff --git a/addons/website_event/tests/__init__.py b/addons/website_event/tests/__init__.py index 6986da4eab7..41f5bb1157f 100644 --- a/addons/website_event/tests/__init__.py +++ b/addons/website_event/tests/__init__.py @@ -5,3 +5,4 @@ from . import common from . import test_event_internals from . import test_ui from . import test_website_event +from . import test_website_event_access diff --git a/addons/website_event/tests/test_website_event_access.py b/addons/website_event/tests/test_website_event_access.py new file mode 100644 index 00000000000..64da6f4c6c5 --- /dev/null +++ b/addons/website_event/tests/test_website_event_access.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from functools import partial +from datetime import datetime, timedelta + +from odoo.tests import HttpCase, new_test_user, 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), + }]) + + event_new_test_user = partial(new_test_user, context={'mail_create_nolog': True, 'mail_create_nosubscribe': True, 'mail_notrack': True, 'no_reset_password': True}) + self.event_manager = event_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 = event_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 = event_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_templates.xml b/addons/website_event/views/event_templates.xml index c3cf0609461..5cf6550e94e 100644 --- a/addons/website_event/views/event_templates.xml +++ b/addons/website_event/views/event_templates.xml @@ -356,12 +356,12 @@ <ul class="navbar-nav flex-row"> <li class="nav-item mr-3"> <a t-attf-href="/event?type=#{event.event_type_id.id}" t-if="event.event_type_id" class="nav-link"> - <i class="fa fa-folder-open text-primary mr-2"/><t t-esc="event.event_type_id.name"/> + <i class="fa fa-folder-open text-primary mr-2"/><span t-field="event.event_type_id"/> </a> </li> <li class="nav-item mr-3"> <a t-if="event.country_id" t-attf-href="/event?country=#{event.country_id.id}" class="nav-link"> - <i class="fa fa-map-marker text-primary mr-2"/><t t-esc="event.country_id.name"/> + <i class="fa fa-map-marker text-primary mr-2"/><span t-field="event.country_id"/> </a> </li> </ul> @@ -461,7 +461,7 @@ "fields": ["phone", "mobile", "email"] }'/> <i class="fa fa-map-marker fa-fw" role="img"/> - <a t-att-href="event.google_map_link()" target="_blank">Get the direction</a> + <a t-att-href="event._google_map_link()" target="_blank">Get the direction</a> </div> <!-- Organizer --> <div t-if="event.organizer_id" class="o_wevent_sidebar_block"> |
