# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import http from odoo.addons.auth_signup.controllers.main import AuthSignupHome from odoo.addons.web.controllers.home import SIGN_UP_REQUEST_PARAMS from odoo.http import request # partner_firstname exposes `firstname` / `lastname` on res.users and # res.partner; we need them as accepted qcontext params so the signup form # roundtrips them transparently through `get_auth_signup_qcontext`. SIGN_UP_REQUEST_PARAMS.add("firstname") SIGN_UP_REQUEST_PARAMS.add("lastname") # Session keys used by the membership signup flow. MEMBERSHIP_SIGNUP_SESSION_KEYS = ("membership_signup_active", "membership_signup_product_id") class AuthSignupHomeMembership(AuthSignupHome): def _prepare_signup_values(self, qcontext): values = super()._prepare_signup_values(qcontext) # partner_firstname: the signup form collects `firstname` / `lastname` # separately. We inject both into the signup values so the resulting # partner/user has them populated. # # We ALSO keep a composed `name` (firstname + " " + lastname) in the # values, on purpose. The core's `_create_user_from_template` # (`auth_signup/models/res_users.py`) rejects the signup with # `ValueError: Signup: no name or partner given for new user` if # neither `partner_id` nor `name` is present in the values — that # check runs BEFORE `template_user.copy(values)` reaches # `res.partner.create`, where `partner_firstname` would otherwise # recompute `name` from the split fields. # # By providing the composed `name`, the check passes; then, inside # `res.partner.create`, partner_firstname's override detects that both # `firstname` and `lastname` are in the vals and DISCARDS the composed # `name` (see `partner_firstname/models/res_partner.py:_name_fields_in_vals` # branch `del vals["name"]`), recomputing it from the split fields. # Net effect: the partner ends up with the proper `firstname`, # `lastname` and a recomputed `name`, exactly as intended. firstname = qcontext.get("firstname", "") lastname = qcontext.get("lastname", "") if firstname or lastname: values["firstname"] = firstname values["lastname"] = lastname partner_model = request.env["res.partner"] values["name"] = partner_model._get_computed_name( lastname, firstname ) return values @http.route() def web_auth_signup(self, *args, **kw): response = super().web_auth_signup(*args, **kw) # On a successful signup the user is now authenticated (session.uid # set) and the redirect to the product page will happen. Drop the # membership markers from the session so they cannot leak into later # /web/signup attempts by other visitors sharing the session (defence # in depth). if request.session.uid: for key in MEMBERSHIP_SIGNUP_SESSION_KEYS: request.session.pop(key, None) return response @http.route() def web_login(self, *args, **kw): response = super().web_login(*args, **kw) # Same cleanup on explicit login (covers the "Already have an # account?" branch from the signup page). if request.session.uid: for key in MEMBERSHIP_SIGNUP_SESSION_KEYS: request.session.pop(key, None) return response