def change_password(self, user, password, new_password, password_confirm): if new_password != password_confirm: msg = "Your password doesn't match the confirmation" raise RestApiException(msg, status_code=hcodes.HTTP_BAD_CONFLICT) if self.auth.VERIFY_PASSWORD_STRENGTH: check = True if password is not None: check, msg = self.verify_password_strength(new_password, old_pwd=password) else: check, msg = self.verify_password_strength( new_password, old_hash=user.password) if not check: raise RestApiException(msg, status_code=hcodes.HTTP_BAD_CONFLICT) if new_password is not None and password_confirm is not None: now = datetime.now(pytz.utc) user.password = BaseAuthentication.hash_password(new_password) user.last_password_change = now user.save() tokens = self.auth.get_tokens(user=user) for token in tokens: self.auth.invalidate_token(token=token["token"]) # changes the user uuid invalidating all tokens self.auth.invalidate_all_tokens() return True
def verify_password_strength(self, pwd, old_pwd=None, old_hash=None): if old_pwd is not None and pwd == old_pwd: return False, "Password cannot match the previous password" if old_hash is not None: new_hash = BaseAuthentication.hash_password(pwd) if old_hash == new_hash: return False, "Password cannot match the previous password" if len(pwd) < 8: return False, "Password is too short, use at least 8 characters" if not re.search("[a-z]", pwd): return False, "Password is too simple, missing lower case letters" if not re.search("[A-Z]", pwd): return False, "Password is too simple, missing upper case letters" if not re.search("[0-9]", pwd): return False, "Password is too simple, missing numbers" # special_characters = "['\s!#$%&\"(),*+,-./:;<=>?@[\\]^_`{|}~']" special_characters = "[^a-zA-Z0-9]" if not re.search(special_characters, pwd): return False, "Password is too simple, missing special characters" return True, None
def put(self, user_id=None): if user_id is None: raise RestApiException( "Please specify a user id", status_code=hcodes.HTTP_BAD_REQUEST) if not detector.check_availability('neo4j'): log.warning("This endpoint is implemented only for neo4j") return self.empty_response() schema = self.get_endpoint_custom_definition() self.graph = self.get_service_instance('neo4j') is_admin = self.auth.verify_admin() is_group_admin = self.auth.verify_group_admin() if not is_admin and not is_group_admin: raise RestApiException( "You are not authorized: missing privileges", status_code=hcodes.HTTP_BAD_UNAUTHORIZED) v = self.get_input() user = self.graph.User.nodes.get_or_none(uuid=user_id) # user = self.getNode(self.graph.User, user_id, field='uuid') if user is None: raise RestApiException( "This user cannot be found or you are not authorized") current_user = self.get_current_user() is_authorized = self.check_permissions( current_user, user, is_admin, is_group_admin ) if not is_authorized: raise RestApiException( "This user cannot be found or you are not authorized") unhashed_password = None if "password" in v and v["password"] == "": del v["password"] else: v["password"] = BaseAuthentication.hash_password(v["password"]) if "email" in v: v["email"] = v["email"].lower() self.update_properties(user, schema, v) user.save() if 'group' in v: group = self.parse_group(v) if not is_admin: if not group.coordinator.is_connected(current_user): raise RestApiException( "You are allowed to assign users to this group") p = None for p in user.belongs_to.all(): if p == group: continue if p is not None: user.belongs_to.reconnect(p, group) else: user.belongs_to.connect(group) roles = self.parse_roles(v) if not is_admin: allowed_roles = mem.customizer._configurations \ .get('variables', {}) \ .get('backend', {}) \ .get('allowed_roles', []) for r in roles: if r not in allowed_roles: raise RestApiException( "You are allowed to assign users to this role") self.auth.link_roles(user, roles) email_notification = v.get('email_notification', False) if email_notification and unhashed_password is not None: self.send_notification(user, unhashed_password, is_update=True) return self.empty_response()