123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- # -*- coding: utf-8 -*-
- # Copyright 2015 LasLabs Inc.
- # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
- import re
- from datetime import datetime, timedelta
- from openerp import api, fields, models, _
- from ..exceptions import PassError
- def delta_now(**kwargs):
- dt = datetime.now() + timedelta(**kwargs)
- return fields.Datetime.to_string(dt)
- class ResUsers(models.Model):
- _inherit = 'res.users'
- password_write_date = fields.Datetime(
- 'Last password update',
- readonly=True,
- )
- password_history_ids = fields.One2many(
- string='Password History',
- comodel_name='res.users.pass.history',
- inverse_name='user_id',
- readonly=True,
- )
- @api.model
- def create(self, vals):
- vals['password_write_date'] = fields.Datetime.now()
- return super(ResUsers, self).create(vals)
- @api.multi
- def write(self, vals):
- if vals.get('password'):
- self.check_password(vals['password'])
- vals['password_write_date'] = fields.Datetime.now()
- return super(ResUsers, self).write(vals)
- @api.multi
- def password_match_message(self):
- self.ensure_one()
- company_id = self.company_id
- message = []
- if company_id.password_lower:
- message.append('* ' + _('Minúsculas'))
- if company_id.password_upper:
- message.append('* ' + _('Mayúsculas'))
- if company_id.password_numeric:
- message.append('* ' + _('Numeros'))
- if company_id.password_special:
- message.append('* ' + _('Caracteres Especiales'))
- if len(message):
- message = [_('Tambien debe contener:')] + message
- if company_id.password_length:
- message = [
- _('La contraseña debe tener %d caracteres o mas.') %
- company_id.password_length
- ] + message
- return '\r'.join(message)
- @api.multi
- def check_password(self, password):
- self.ensure_one()
- if not password:
- return True
- company_id = self.company_id
- password_regex = ['^']
- if company_id.password_lower:
- password_regex.append('(?=.*?[a-z])')
- if company_id.password_upper:
- password_regex.append('(?=.*?[A-Z])')
- if company_id.password_numeric:
- password_regex.append(r'(?=.*?\d)')
- if company_id.password_special:
- password_regex.append(r'(?=.*?\W)')
- password_regex.append('.{%d,}$' % company_id.password_length)
- if not re.search(''.join(password_regex), password):
- raise PassError(_(self.password_match_message()))
- return True
- @api.multi
- def _password_has_expired(self):
- self.ensure_one()
- if not self.password_write_date:
- return True
- write_date = fields.Datetime.from_string(self.password_write_date)
- today = fields.Datetime.from_string(fields.Datetime.now())
- days = (today - write_date).days
- return days > self.company_id.password_expiration
- @api.multi
- def action_expire_password(self):
- expiration = delta_now(days=+1)
- for rec_id in self:
- rec_id.mapped('partner_id').signup_prepare(
- signup_type="reset", expiration=expiration
- )
- @api.multi
- def _validate_pass_reset(self):
- """ It provides validations before initiating a pass reset email
- :raises: PassError on invalidated pass reset attempt
- :return: True on allowed reset
- """
- for rec_id in self:
- pass_min = rec_id.company_id.password_minimum
- if pass_min <= 0:
- pass
- write_date = fields.Datetime.from_string(
- rec_id.password_write_date
- )
- delta = timedelta(hours=pass_min)
- if write_date + delta > datetime.now():
- raise PassError(
- _('Passwords can only be reset every %d hour(s). '
- 'Please contact an administrator for assistance.') %
- pass_min,
- )
- return True
- @api.multi
- def _set_password(self, password):
- """ It validates proposed password against existing history
- :raises: PassError on reused password
- """
- crypt = self._crypt_context()[0]
- for rec_id in self:
- recent_passes = rec_id.company_id.password_history
- if recent_passes < 0:
- recent_passes = rec_id.password_history_ids
- else:
- recent_passes = rec_id.password_history_ids[
- 0:recent_passes-1
- ]
- if len(recent_passes.filtered(
- lambda r: crypt.verify(password, r.password_crypt)
- )):
- raise PassError(
- _('Cannot use the most recent %d passwords') %
- rec_id.company_id.password_history
- )
- super(ResUsers, self)._set_password(password)
- @api.multi
- def _set_encrypted_password(self, encrypted):
- """ It saves password crypt history for history rules """
- super(ResUsers, self)._set_encrypted_password(encrypted)
- self.write({
- 'password_history_ids': [(0, 0, {
- 'password_crypt': encrypted,
- })],
- })
|