diff --git a/addons/community_benefits/controllers/main.py b/addons/community_benefits/controllers/main.py index e32ac9c..3f4e371 100644 --- a/addons/community_benefits/controllers/main.py +++ b/addons/community_benefits/controllers/main.py @@ -2,6 +2,15 @@ from odoo import http from odoo.http import request +def _redirect_to_login_if_public(path): + """Manual login-required redirect - see community_classifieds for why this + is needed instead of auth='user' (a bug in this Odoo version's own + SessionExpiredException -> login-redirect handling).""" + if request.env.user._is_public(): + return request.redirect(f'/web/login?redirect={path}') + return None + + class BenefitsController(http.Controller): @http.route(['/benefits'], type='http', auth='public', website=True, sitemap=True) @@ -9,8 +18,11 @@ class BenefitsController(http.Controller): centres = request.env['community.benefit.partner'].sudo().search([('active', '=', True)]) return request.render('community_benefits.benefits_directory_page', {'centres': centres}) - @http.route(['/my/benefits'], type='http', auth='user', website=True) + @http.route(['/my/benefits'], type='http', auth='public', website=True) def my_benefits(self, **kwargs): + redirect = _redirect_to_login_if_public('/my/benefits') + if redirect: + return redirect partner = request.env.user.partner_id benefits = request.env['community.benefit'].sudo().search( request.env['community.benefit']._entitled_domain_for_partner(partner) diff --git a/addons/community_classifieds/controllers/main.py b/addons/community_classifieds/controllers/main.py index f800beb..c94f73c 100644 --- a/addons/community_classifieds/controllers/main.py +++ b/addons/community_classifieds/controllers/main.py @@ -19,6 +19,22 @@ def _has_active_membership(partner): return partner.membership_state in ('active', 'renewal_due') +def _redirect_to_login_if_public(path): + """Manual login-required redirect. + + Routes here use auth='public' (not 'user') and check this explicitly, + because Odoo's own auth='user' + website=True error handling has a bug + in this version: SessionExpiredException triggers a login redirect via + self.env['ir.http']._redirect(...), but self.env has already been reset + to None by the finally block in Request._serve_db by the time the error + handler runs, causing a 500 instead of a redirect. Checking auth + ourselves and issuing a plain redirect avoids that code path entirely. + """ + if request.env.user._is_public(): + return request.redirect(f'/web/login?redirect={path}') + return None + + class ClassifiedsController(http.Controller): @http.route(['/classifieds'], type='http', auth='public', website=True, sitemap=True) @@ -40,8 +56,11 @@ class ClassifiedsController(http.Controller): listing._increment_view_count() return request.render('community_classifieds.classifieds_detail_page', {'listing': listing}) - @http.route(['/classifieds/new'], type='http', auth='user', website=True) + @http.route(['/classifieds/new'], type='http', auth='public', website=True) def classifieds_new(self, **kwargs): + redirect = _redirect_to_login_if_public('/classifieds/new') + if redirect: + return redirect partner = request.env.user.partner_id if _is_module_installed(request.env, 'community_membership') and not _has_active_membership(partner): return request.render('community_classifieds.classifieds_membership_required', {}) @@ -67,14 +86,20 @@ class ClassifiedsController(http.Controller): return request.render('community_classifieds.classifieds_new_page', {}) - @http.route(['/classifieds/my'], type='http', auth='user', website=True) + @http.route(['/classifieds/my'], type='http', auth='public', website=True) def classifieds_my(self, **kwargs): + redirect = _redirect_to_login_if_public('/classifieds/my') + if redirect: + return redirect partner = request.env.user.partner_id listings = request.env['community.classified'].sudo().search([('poster_partner_id', '=', partner.id)]) return request.render('community_classifieds.classifieds_my_page', {'listings': listings}) - @http.route(['/classifieds//renew'], type='http', auth='user', website=True) + @http.route(['/classifieds//renew'], type='http', auth='public', website=True) def classifieds_renew(self, classified_id, **kwargs): + redirect = _redirect_to_login_if_public(f'/classifieds/{classified_id}/renew') + if redirect: + return redirect partner = request.env.user.partner_id listing = request.env['community.classified'].sudo().search([ ('id', '=', classified_id), ('poster_partner_id', '=', partner.id), diff --git a/addons/community_membership/controllers/portal.py b/addons/community_membership/controllers/portal.py index 26895c0..1559993 100644 --- a/addons/community_membership/controllers/portal.py +++ b/addons/community_membership/controllers/portal.py @@ -3,6 +3,15 @@ from odoo.addons.portal.controllers.portal import CustomerPortal from odoo.http import request +def _redirect_to_login_if_public(path): + """Manual login-required redirect - see community_classifieds for why this + is needed instead of auth='user' (a bug in this Odoo version's own + SessionExpiredException -> login-redirect handling).""" + if request.env.user._is_public(): + return request.redirect(f'/web/login?redirect={path}') + return None + + class MembershipPortal(CustomerPortal): def _prepare_home_portal_values(self, counters): @@ -12,16 +21,22 @@ class MembershipPortal(CustomerPortal): values['membership_count'] = 1 if partner.membership_state != 'none' else 0 return values - @http.route(['/my/membership'], type='http', auth='user', website=True) + @http.route(['/my/membership'], type='http', auth='public', website=True) def portal_my_membership(self, **kwargs): + redirect = _redirect_to_login_if_public('/my/membership') + if redirect: + return redirect partner = request.env.user.partner_id return request.render('community_membership.portal_my_membership', { 'partner': partner, 'page_name': 'membership', }) - @http.route(['/my/membership/renew'], type='http', auth='user', website=True) + @http.route(['/my/membership/renew'], type='http', auth='public', website=True) def portal_membership_renew(self, **kwargs): + redirect = _redirect_to_login_if_public('/my/membership/renew') + if redirect: + return redirect partner = request.env.user.partner_id invoice = request.env['account.move'].sudo().search([ ('partner_id', '=', partner.id), @@ -34,8 +49,11 @@ class MembershipPortal(CustomerPortal): return request.redirect('/my/membership') return request.redirect(f'/my/invoices/{invoice.id}') - @http.route(['/my/membership/card'], type='http', auth='user', website=True) + @http.route(['/my/membership/card'], type='http', auth='public', website=True) def portal_membership_card(self, **kwargs): + redirect = _redirect_to_login_if_public('/my/membership/card') + if redirect: + return redirect partner = request.env.user.partner_id pdf_content, _report_type = request.env['ir.actions.report'].sudo()._render_qweb_pdf( 'community_membership.action_report_membership_card', res_ids=partner.ids, diff --git a/addons/community_portal/controllers/portal.py b/addons/community_portal/controllers/portal.py index 621700f..23bb14f 100644 --- a/addons/community_portal/controllers/portal.py +++ b/addons/community_portal/controllers/portal.py @@ -48,8 +48,10 @@ class CommunityPortalDashboard(CustomerPortal): return values - @http.route(['/my/school'], type='http', auth='user', website=True) + @http.route(['/my/school'], type='http', auth='public', website=True) def portal_my_school(self, **kwargs): + if request.env.user._is_public(): + return request.redirect('/web/login?redirect=/my/school') partner = request.env.user.partner_id students = request.env['community.school.student'].sudo().search([ ('parent_partner_id', '=', partner.id), diff --git a/addons/community_school/controllers/attendance.py b/addons/community_school/controllers/attendance.py index 8605540..3d891c5 100644 --- a/addons/community_school/controllers/attendance.py +++ b/addons/community_school/controllers/attendance.py @@ -3,14 +3,26 @@ from odoo.exceptions import AccessDenied from odoo.http import request +def _redirect_to_login_if_public(path): + """Manual login-required redirect - see community_classifieds for why this + is needed instead of auth='user' (a bug in this Odoo version's own + SessionExpiredException -> login-redirect handling).""" + if request.env.user._is_public(): + return request.redirect(f'/web/login?redirect={path}') + return None + + class SchoolAttendanceController(http.Controller): def _get_teacher_classes(self): partner = request.env.user.partner_id return request.env['community.school.class'].sudo().search([('teacher_id', '=', partner.id)]) - @http.route(['/school/attendance'], type='http', auth='user', website=True) + @http.route(['/school/attendance'], type='http', auth='public', website=True) def attendance_home(self, class_id=None, date=None, **kwargs): + redirect = _redirect_to_login_if_public('/school/attendance') + if redirect: + return redirect classes = self._get_teacher_classes() if not classes: return request.render('community_school.portal_no_classes', {}) diff --git a/addons/event_qr_ticketing/controllers/checkin.py b/addons/event_qr_ticketing/controllers/checkin.py index 4cef49f..148610e 100644 --- a/addons/event_qr_ticketing/controllers/checkin.py +++ b/addons/event_qr_ticketing/controllers/checkin.py @@ -8,10 +8,22 @@ def _require_registration_desk(): raise AccessDenied() +def _redirect_to_login_if_public(path): + """Manual login-required redirect - see community_classifieds for why this + is needed instead of auth='user' (a bug in this Odoo version's own + SessionExpiredException -> login-redirect handling).""" + if request.env.user._is_public(): + return request.redirect(f'/web/login?redirect={path}') + return None + + class EventCheckinController(http.Controller): - @http.route(['/event/checkin', '/event/checkin/'], type='http', auth='user', website=True) + @http.route(['/event/checkin', '/event/checkin/'], type='http', auth='public', website=True) def checkin_page(self, event_id=None, **kwargs): + redirect = _redirect_to_login_if_public('/event/checkin') + if redirect: + return redirect _require_registration_desk() events = request.env['event.event'].search([('date_end', '>=', fields.Datetime.now())]) event = request.env['event.event'].browse(event_id) if event_id else events[:1]