Files
odoo_source/addons/auth_signup/controllers/main.py
T
Julien Castiaux ab4000fb3c [REF] base: Remove deprecated exceptions and osv
TL;DR: remember `osv` and `except_orm` ? You can forget about them.

* Deprecated `except_orm` dropped.
* `UserError` elevated as super type of all user-related
  errors.
* Unused `DeferredException` dropped.
* Unused `QWebException` dropped (real one is in `qweb.py`).
* `MailDeliveryException` made a python exception.
* `name` legacy exception attribute made an alias of the python standard
  `args[0]` attribute and deprecated.
* `value` legacy exception attribute dropped.
* `exception_type` RPC error response key dropped.
* Deprecated `osv` module dropped.
* `--osv-memory-age-limit` cli option made an alias of
  `--transient-age-limit` and deprecated.

The `odoo.exceptions.Warning` have long been a deprecated alias to
`UserError`. It is going to be removed in a future version but first we
explicitly deprecate it with a warning.

The `odoo.exceptions.DeferredException` was a very old internal
exception, it has been removed without deprecation notice as it is never
raised.

The `odoo.exceptions.except_orm` has been a deprecated exception type
with deprecation warning for 5 years, it has been removed in favor of
UserError which becomes the super class of all user-related errors.

The `odoo.base.models.ir_mail_server.MailDeliveryException` was
inheriting `except_orm`. As it is not related to a user error but is
more of a problem an admin much take care of, the exception has been
made a Python error.

The `exception_type` JSON key in RPC error responses was holding an
hardcoded value derived from the exception type. Its usage has been
dropped in favor of the `name` JSON key that holds the precise exception
name. Again as it was hardly used in the source code (beside the crash
manager) it has been dropped without deprecation warning.

Since we are here trying to clean odoo custom exceptions, we are also
deprecating the `name` exception attribute in favor of the more standard
`args[0]` attribute.

The `name` (along with `value`) were two attributes used to raise
`except_orm` exceptions before the introduction of `UserError`,
`AccessError` and related exceptions. The `name` attribute, at the time,
was holding the exception type/title. Nowadays it contains the error
message. The `value` attribute, at the time, was holding the error
message. Nowadays it is no more used.

The `osv` module contains very old deprecated aliases. There is no
simple way to log a deprecation warning for osv, osv_memory and
osv_abstract but as they have not been in use for ages, they have been
removed too. To be consistent, the `--osv-memory-age-limit` cli option
has been made a deprecated alias to the `--transient-age-limit`.

closes odoo/odoo#45723

Task: 2187728
Related: odoo/enterprise#9162
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-04-08 08:41:17 +00:00

146 lines
6.8 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
import werkzeug
from odoo import http, _
from odoo.addons.auth_signup.models.res_users import SignupError
from odoo.addons.web.controllers.main import ensure_db, Home
from odoo.addons.base_setup.controllers.main import BaseSetup
from odoo.exceptions import UserError
from odoo.http import request
_logger = logging.getLogger(__name__)
class AuthSignupHome(Home):
@http.route()
def web_login(self, *args, **kw):
ensure_db()
response = super(AuthSignupHome, self).web_login(*args, **kw)
response.qcontext.update(self.get_auth_signup_config())
if request.httprequest.method == 'GET' and request.session.uid and request.params.get('redirect'):
# Redirect if already logged in and redirect param is present
return http.redirect_with_hash(request.params.get('redirect'))
return response
@http.route('/web/signup', type='http', auth='public', website=True, sitemap=False)
def web_auth_signup(self, *args, **kw):
qcontext = self.get_auth_signup_qcontext()
if not qcontext.get('token') and not qcontext.get('signup_enabled'):
raise werkzeug.exceptions.NotFound()
if 'error' not in qcontext and request.httprequest.method == 'POST':
try:
self.do_signup(qcontext)
# Send an account creation confirmation email
if qcontext.get('token'):
User = request.env['res.users']
user_sudo = User.sudo().search(
User._get_login_domain(qcontext.get('login')), order=User._get_login_order(), limit=1
)
template = request.env.ref('auth_signup.mail_template_user_signup_account_created', raise_if_not_found=False)
if user_sudo and template:
template.sudo().send_mail(user_sudo.id, force_send=True)
return self.web_login(*args, **kw)
except UserError as e:
qcontext['error'] = e.args[0]
except (SignupError, AssertionError) as e:
if request.env["res.users"].sudo().search([("login", "=", qcontext.get("login"))]):
qcontext["error"] = _("Another user is already registered using this email address.")
else:
_logger.error("%s", e)
qcontext['error'] = _("Could not create a new account.")
response = request.render('auth_signup.signup', qcontext)
response.headers['X-Frame-Options'] = 'DENY'
return response
@http.route('/web/reset_password', type='http', auth='public', website=True, sitemap=False)
def web_auth_reset_password(self, *args, **kw):
qcontext = self.get_auth_signup_qcontext()
if not qcontext.get('token') and not qcontext.get('reset_password_enabled'):
raise werkzeug.exceptions.NotFound()
if 'error' not in qcontext and request.httprequest.method == 'POST':
try:
if qcontext.get('token'):
self.do_signup(qcontext)
return self.web_login(*args, **kw)
else:
login = qcontext.get('login')
assert login, _("No login provided.")
_logger.info(
"Password reset attempt for <%s> by user <%s> from %s",
login, request.env.user.login, request.httprequest.remote_addr)
request.env['res.users'].sudo().reset_password(login)
qcontext['message'] = _("An email has been sent with credentials to reset your password")
except UserError as e:
qcontext['error'] = e.args[0]
except SignupError:
qcontext['error'] = _("Could not reset your password")
_logger.exception('error when resetting password')
except Exception as e:
qcontext['error'] = str(e)
response = request.render('auth_signup.reset_password', qcontext)
response.headers['X-Frame-Options'] = 'DENY'
return response
def get_auth_signup_config(self):
"""retrieve the module config (which features are enabled) for the login page"""
get_param = request.env['ir.config_parameter'].sudo().get_param
return {
'signup_enabled': request.env['res.users']._get_signup_invitation_scope() == 'b2c',
'reset_password_enabled': get_param('auth_signup.reset_password') == 'True',
}
def get_auth_signup_qcontext(self):
""" Shared helper returning the rendering context for signup and reset password """
qcontext = request.params.copy()
qcontext.update(self.get_auth_signup_config())
if not qcontext.get('token') and request.session.get('auth_signup_token'):
qcontext['token'] = request.session.get('auth_signup_token')
if qcontext.get('token'):
try:
# retrieve the user info (name, login or email) corresponding to a signup token
token_infos = request.env['res.partner'].sudo().signup_retrieve_info(qcontext.get('token'))
for k, v in token_infos.items():
qcontext.setdefault(k, v)
except:
qcontext['error'] = _("Invalid signup token")
qcontext['invalid_token'] = True
return qcontext
def do_signup(self, qcontext):
""" Shared helper that creates a res.partner out of a token """
values = { key: qcontext.get(key) for key in ('login', 'name', 'password') }
if not values:
raise UserError(_("The form was not properly filled in."))
if values.get('password') != qcontext.get('confirm_password'):
raise UserError(_("Passwords do not match; please retype them."))
supported_lang_codes = [code for code, _ in request.env['res.lang'].get_installed()]
lang = request.context.get('lang', '').split('_')[0]
if lang in supported_lang_codes:
values['lang'] = lang
self._signup_with_values(qcontext.get('token'), values)
request.env.cr.commit()
def _signup_with_values(self, token, values):
db, login, password = request.env['res.users'].sudo().signup(values, token)
request.env.cr.commit() # as authenticate will use its own cursor we need to commit the current transaction
uid = request.session.authenticate(db, login, password)
if not uid:
raise SignupError(_('Authentication Failed.'))
class AuthBaseSetup(BaseSetup):
@http.route('/base_setup/data', type='json', auth='user')
def base_setup_data(self, **kwargs):
res = super().base_setup_data(**kwargs)
res.update({'resend_invitation': True})
return res