<%#
 Copyright 2013-2023 the original author or authors from the JHipster project.

 This file is part of the JHipster project, see https://www.jhipster.tech/
 for more information.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      https://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-%>
package <%= packageName %>.service;

<%_
const pageName = ormTool !== 'mybatis' ? 'Page' : 'IPage';
const pageType = ormTool !== 'mybatis' ? 'Pageable' : `IPage<User>`;
const specificationType = ormTool !== 'mybatis' ? 'Specification' : 'QueryWrapper';
const specificationInstance = ormTool !== 'mybatis' ? 'specification' : 'queryWrapper';
const manyListName = ormTool !== 'mybatis' ? 'Set' : 'List';
const manyListType = ormTool !== 'mybatis' ? 'LinkedHashSet' : 'ArrayList';
_%>
import <%= packageName %>.config.Constants;
<%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase) { _%>
import <%= packageName %>.domain.Authority;
<%_ } _%>
<%_ if (!databaseTypeNo) { _%>
import <%= user.entityAbsoluteClass %>;
  <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase) { _%>
import <%= packageName %>.repository.AuthorityRepository;
    <%_ if (authenticationTypeSession && !reactive) { _%>
import <%= packageName %>.repository.PersistentTokenRepository;
    <%_ } _%>
  <%_ } _%>
import <%= packageName %>.repository.UserRepository;
  <%_ if (searchEngineElasticsearch) { _%>
import <%= packageName %>.repository.search.UserSearchRepository;
  <%_ } _%>
  <%_ if (!authenticationTypeOauth2) { _%>
import <%= packageName %>.security.AuthoritiesConstants;
  <%_ } _%>
import <%= packageName %>.security.SecurityUtils;
<%_ } _%>
import <%= packageName %>.service.dto.<%= user.adminUserDto %>;
<%_ if (!databaseTypeNo) { _%>
import <%= packageName %>.service.dto.<%= user.dtoClass %>;
<%_ } _%>
import <%= packageName %>.service.dto.AuthorityDTO;
import <%= packageName %>.service.mapper.UserMapper;
<%_ if (!authenticationTypeOauth2) { _%>

import tech.jhipster.security.RandomUtil;
<%_ } _%>

<%_ if (!databaseTypeNo) { _%>
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
<%_ } _%>
<%_ if (cacheProviderAny) { _%>
import org.springframework.cache.CacheManager;
<%_ } _%>
<%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase) { _%>
  <%_ if (!reactive) { _%>
    <%_ if (ormTool === 'hibernate') { _%>
import org.springframework.data.domain.Page;
    <%_ } else { _%>
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.diboot.core.service.impl.BaseServiceImpl;
import com.diboot.core.binding.Binder;
    <%_ } _%>
    <%_ if (databaseTypeCouchbase) { _%>
import org.springframework.data.domain.PageImpl;
    <%_ } _%>
  <%_ } _%>
import org.springframework.data.domain.Pageable;
  <%_ if (!authenticationTypeOauth2) { _%>
import org.springframework.scheduling.annotation.Scheduled;
  <%_ } _%>
<%_ } _%>
<%_ if (authenticationTypeOauth2) { _%>
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
<%_ } _%>
<%_ if (!authenticationTypeOauth2) { _%>
import org.springframework.security.crypto.password.PasswordEncoder;
<%_ } _%>
import org.springframework.stereotype.Service;
<%_ if (databaseTypeSql) { _%>
import org.springframework.transaction.annotation.Transactional;
<%_ } _%>
<%_ if (reactive) { _%>
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
<%_ } _%>

<%_ if ((databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase) && authenticationTypeSession && !reactive) { _%>
import java.time.LocalDate;
<%_ } _%>
<%_ if (!databaseTypeNo) { _%>
import java.time.LocalDateTime;
<%_ } _%>
<%_ if (databaseTypeSql && reactive && !authenticationTypeOauth2) { _%>
import java.time.ZoneOffset;
<%_ } _%>
<%_ if (!authenticationTypeOauth2) { _%>
import java.time.temporal.ChronoUnit;
<%_ } _%>
import java.util.*;
import java.time.Instant;
import java.time.ZonedDateTime;
<%_ if (!reactive || authenticationTypeOauth2) { _%>
import java.util.stream.Collectors;
<%_ } _%>

/**
 * Service class for managing users.
 */
@Service
<%_ if (databaseTypeSql && !reactive && ormTool === 'hibernate') { _%>
@Transactional
<%_ } _%>
public class UserService<% if (ormTool === 'mybatis') { %> extends BaseServiceImpl<UserRepository, User><% } %> {
<%_ if (!databaseTypeNo) { _%>

    private final Logger log = LoggerFactory.getLogger(UserService.class);

    private final UserRepository userRepository;
  <%_ if (!authenticationTypeOauth2) { _%>

    private final PasswordEncoder passwordEncoder;
  <%_ } _%>
  <%_ if (searchEngineElasticsearch) { _%>

    private final UserSearchRepository userSearchRepository;
  <%_ } _%>
  <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase) { _%>
    <%_ if (authenticationTypeSession  && !reactive) { _%>

    private final PersistentTokenRepository persistentTokenRepository;
    <%_ } _%>

    private final AuthorityRepository authorityRepository;
  <%_ } _%>
  <%_ if (cacheProviderAny) { _%>

    private final CacheManager cacheManager;
  <%_ } _%>

    private final UserMapper userMapper;

    public UserService(UserRepository userRepository<% if (!authenticationTypeOauth2) { %>, PasswordEncoder passwordEncoder<% } %><% if (searchEngineElasticsearch) { %>, UserSearchRepository userSearchRepository<% } %><% if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase) { %><% if (authenticationTypeSession && !reactive) { %>, PersistentTokenRepository persistentTokenRepository<% } %>, AuthorityRepository authorityRepository<% } %><% if (cacheProviderAny) { %>, CacheManager cacheManager<% } %>, UserMapper userMapper) {
        this.userRepository = userRepository;
  <%_ if (!authenticationTypeOauth2) { _%>
        this.passwordEncoder = passwordEncoder;
  <%_ } _%>
  <%_ if (searchEngineElasticsearch) { _%>
        this.userSearchRepository = userSearchRepository;
  <%_ } _%>
  <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase) { _%>
    <%_ if (authenticationTypeSession && !reactive) { _%>
        this.persistentTokenRepository = persistentTokenRepository;
    <%_ } _%>
        this.authorityRepository = authorityRepository;
  <%_ } _%>
  <%_ if (cacheProviderAny) { _%>
        this.cacheManager = cacheManager;
  <%_ } _%>
        this.userMapper = userMapper;
    }
  <%_ if (!authenticationTypeOauth2) { _%>

    <%_ if (databaseTypeSql && reactive) { _%>
    @Transactional
    <%_ } _%>
    public <% if (reactive) { %>Mono<% } else { %>Optional<% } %><<%= user.persistClass %>> activateRegistration(String key) {
        log.debug("Activating user for activation key {}", key);
        return userRepository.findOneByActivationKey(key)
            .<% if (reactive) { %>flatMap<% } else { %>map<% } %>(user -> {
                // activate given user for the registration key.
                user.setActivated(true);
                user.setActivationKey(null);
    <%_ if (reactive) { _%>
                return saveUser(user);
            })
      <%_ if (searchEngineElasticsearch) { _%>
            .flatMap(user -> userSearchRepository.save(user).thenReturn(user))
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
            .doOnNext(this::clearUserCaches)
      <%_ } _%>
            .doOnNext(user -> log.debug("Activated user: {}", user));
    <%_ } else { _%>
      <%_ if (databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase || databaseTypeCassandra) { _%>
                userRepository.save(user);
      <%_ } _%>
      <%_ if (searchEngineElasticsearch) { _%>
                userSearchRepository.save(user);
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
                this.clearUserCaches(user);
      <%_ } _%>
                log.debug("Activated user: {}", user);
                return user;
            });
    <%_ } _%>
    }

    <%_ if (databaseTypeSql && reactive) { _%>
    @Transactional
    <%_ } _%>
    public <% if (reactive) { %>Mono<% } else { %>Optional<% } %><<%= user.persistClass %>> completePasswordReset(String newPassword, String key) {
        log.debug("Reset user password for reset key {}", key);
        return userRepository.findOneByResetKey(key)
            .filter(user -> user.getResetDate().isAfter(Instant.now().minus(1, ChronoUnit.DAYS)))
    <%_ if (reactive) { _%>
            .publishOn(Schedulers.boundedElastic())
            .map(user -> {
                user.setPassword(passwordEncoder.encode(newPassword));
                user.setResetKey(null);
                user.setResetDate(null);
                return user;
            })
            .flatMap(this::saveUser)<% if (cacheProviderAny) { %>
            .doOnNext(this::clearUserCaches)<% } %>;
    <%_ } else { _%>
            .map(user -> {
                user.setPassword(passwordEncoder.encode(newPassword));
                user.setResetKey(null);
                user.setResetDate(null);
      <%_ if (databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase || databaseTypeCassandra || ormTool === 'mybatis') { _%>
                userRepository.save(user);
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
                this.clearUserCaches(user);
      <%_ } _%>
                return user;
            });
    <%_ } _%>
    }

    <%_ if (databaseTypeSql && reactive) { _%>
    @Transactional
    <%_ } _%>
    public <% if (reactive) { %>Mono<% } else { %>Optional<% } %><<%= user.persistClass %>> requestPasswordReset(String mail) {
        return userRepository.findOneByEmailIgnoreCase(mail)
            .filter(<%= user.persistClass %>::isActivated)
    <%_ if (reactive) { _%>
            .publishOn(Schedulers.boundedElastic())
            .map(user -> {
                user.setResetKey(RandomUtil.generateResetKey());
                user.setResetDate(Instant.now());
                return user;
            })
            .flatMap(this::saveUser)<% if (cacheProviderAny) { %>
            .doOnNext(this::clearUserCaches)<% } %>;
    <%_ } else { _%>
            .map(user -> {
                user.setResetKey(RandomUtil.generateResetKey());
                user.setResetDate(Instant.now());
      <%_ if (databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase || databaseTypeCassandra) { _%>
                userRepository.save(user);
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
                this.clearUserCaches(user);
      <%_ } _%>
                return user;
            });
    <%_ } _%>
    }

    <%_ if (databaseTypeSql && reactive) { _%>
    @Transactional
    <%_ } _%>
    public <% if (reactive) { %>Mono<<%= user.persistClass %>><% } else { %><%= user.persistClass %><% } %> registerUser(<%= user.adminUserDto %> userDTO, String password) {
    <%_ if (reactive) { _%>
        return userRepository.findOneByLogin(userDTO.getLogin().toLowerCase())
            .flatMap(existingUser -> {
                if (!existingUser.isActivated()) {
      <%_ if (cacheProviderAny) { _%>
                    this.clearUserCaches(existingUser);
      <%_ } _%>
                    return userRepository.delete(existingUser);
                } else {
                    return Mono.error(new UsernameAlreadyUsedException());
                }
            })
            .then(userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()))
            .flatMap(existingUser -> {
                if (!existingUser.isActivated()) {
      <%_ if (cacheProviderAny) { _%>
                    this.clearUserCaches(existingUser);
      <%_ } _%>
                    return userRepository.delete(existingUser);
                } else {
                    return Mono.error(new EmailAlreadyUsedException());
                }
            })
            .publishOn(Schedulers.boundedElastic())
            .then(Mono.fromCallable(() -> {
                <%= user.persistClass %> newUser = new <%= user.persistClass %>();
      <%_ if (databaseTypeCassandra) { _%>
                newUser.setId(UUID.randomUUID().toString());
      <%_ } _%>
                String encryptedPassword = passwordEncoder.encode(password);
                newUser.setLogin(userDTO.getLogin().toLowerCase());
                // new user gets initially a generated password
                newUser.setPassword(encryptedPassword);
                newUser.setFirstName(userDTO.getFirstName());
                newUser.setLastName(userDTO.getLastName());
                if (userDTO.getEmail() != null) {
                    newUser.setEmail(userDTO.getEmail().toLowerCase());
                }
      <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase) { _%>
                newUser.setImageUrl(userDTO.getImageUrl());
      <%_ } _%>
                newUser.setLangKey(userDTO.getLangKey());
                // new user is not active
                newUser.setActivated(false);
                // new user gets registration key
                newUser.setActivationKey(RandomUtil.generateActivationKey());
                return newUser;
            }))
            .flatMap(newUser -> {
                <%= manyListName%><<% if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j) { %>Authority<% } else { %>String<% } %>> authorities = new <%= manyListType%><>();
      <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j) { _%>
                return authorityRepository.findFirstByCode(AuthoritiesConstants.USER)
                    .map(authorities::add)
                    .thenReturn(newUser)
                    .doOnNext(user -> user.setAuthorities(authorities))
                    .flatMap(this::saveUser)
      <%_ } else { _%>
                authorities.add(AuthoritiesConstants.USER);
                newUser.setAuthorities(authorities);
                return saveUser(newUser)
      <%_ } _%>
      <%_ if (searchEngineElasticsearch) { _%>
                    .flatMap(user -> userSearchRepository.save(user).thenReturn(user))
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
                    .doOnNext(this::clearUserCaches)
      <%_ } _%>
                    .doOnNext(user -> log.debug("Created Information for User: {}", user));
            });
    <%_ } else { /* !reactive */ _%>
        userRepository.findOneByLogin(userDTO.getLogin().toLowerCase()).ifPresent(existingUser -> {
            boolean removed = removeNonActivatedUser(existingUser);
            if (!removed) {
                throw new UsernameAlreadyUsedException();
            }
        });
        userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()).ifPresent(existingUser -> {
            boolean removed = removeNonActivatedUser(existingUser);
            if (!removed) {
                throw new EmailAlreadyUsedException();
            }
        });
        <%= user.persistClass %> newUser = new <%= user.persistClass %>();
      <%_ if (databaseTypeCassandra) { _%>
        newUser.setId(UUID.randomUUID().toString());
      <%_ } _%>
        String encryptedPassword = passwordEncoder.encode(password);
        newUser.setLogin(userDTO.getLogin().toLowerCase());
        // new user gets initially a generated password
        newUser.setPassword(encryptedPassword);
        newUser.setFirstName(userDTO.getFirstName());
        newUser.setLastName(userDTO.getLastName());
        if (userDTO.getEmail() != null) {
            newUser.setEmail(userDTO.getEmail().toLowerCase());
        }
      <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeCouchbase || databaseTypeNeo4j) { _%>
        newUser.setImageUrl(userDTO.getImageUrl());
      <%_ } _%>
        newUser.setLangKey(userDTO.getLangKey());
        // new user is not active
        newUser.setActivated(false);
        // new user gets registration key
        newUser.setActivationKey(RandomUtil.generateActivationKey());
      <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j) { _%>
        <%= manyListName%><Authority> authorities = new <%= manyListType%><>();
        authorityRepository.findFirstByCode(AuthoritiesConstants.USER).ifPresent(authorities::add);
      <%_ } else { _%>
        <%= manyListName%><String> authorities = new <%= manyListType%><>();
        authorities.add(AuthoritiesConstants.USER);
      <%_ } _%>
        newUser.setAuthorities(authorities);
        userRepository.save(newUser);
      <%_ if (searchEngineElasticsearch) { _%>
        userSearchRepository.save(newUser);
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
        this.clearUserCaches(newUser);
      <%_ } _%>
        log.debug("Created Information for User: {}", newUser);
        return newUser;
    <%_ } _%>
    }

    <%_ if (!reactive) { _%>
    private boolean removeNonActivatedUser(<%= user.persistClass %> existingUser) {
        if (existingUser.isActivated()) {
             return false;
        }
        userRepository.delete<%= ormTool === 'mybatis' ? 'ById' : ''%>(existingUser);
      <%_ if (databaseTypeSql && ormTool === 'hibernate') { _%>
        userRepository.flush();
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
        this.clearUserCaches(existingUser);
      <%_ } _%>
        return true;
    }

    <%_ } _%>
    <%_ if (databaseTypeSql && reactive) { _%>
    @Transactional
    <%_ } _%>
    public <% if (reactive) { %>Mono<<%= user.persistClass %>><% } else { %><%= user.persistClass %><% } %> createUser(<%= user.adminUserDto %> userDTO) {
        <%= user.persistClass %> user = new <%= user.persistClass %>();
    <%_ if (databaseTypeCassandra) { _%>
        user.setId(UUID.randomUUID().toString());
    <%_ } _%>
        user.setLogin(userDTO.getLogin().toLowerCase());
        user.setFirstName(userDTO.getFirstName());
        user.setLastName(userDTO.getLastName());
        user.setMobile(userDTO.getMobile());
        if (userDTO.getEmail() != null) {
            user.setEmail(userDTO.getEmail().toLowerCase());
        }
    <%_ if (databaseTypeSql || databaseTypeCouchbase || databaseTypeMongodb || databaseTypeNeo4j) { _%>
        user.setImageUrl(userDTO.getImageUrl());
    <%_ } _%>
        if (userDTO.getLangKey() == null) {
            user.setLangKey(Constants.DEFAULT_LANGUAGE); // default language
        } else {
            user.setLangKey(userDTO.getLangKey());
        }
    <%_ if (reactive) { _%>
      <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j) { _%>
        return Flux.fromIterable(userDTO.getAuthorities() != null ? userDTO.getAuthorities() : new <%= manyListType%><>())
            .flatMap(authorityRepository::findFirstByCode)
            .doOnNext(authority -> user.getAuthorities().add(authority))
            .then(Mono.just(user))
      <%_ } else { _%>
        user.setAuthorities(userDTO.getAuthorities());
        return Mono.just(user)
      <%_ } _%>
            .publishOn(Schedulers.boundedElastic())
            .map(newUser -> {
                String encryptedPassword = passwordEncoder.encode(RandomUtil.generatePassword());
                newUser.setPassword(encryptedPassword);
                newUser.setResetKey(RandomUtil.generateResetKey());
                newUser.setResetDate(Instant.now());
                newUser.setActivated(true);
                return newUser;
            })
            .flatMap(this::saveUser)
      <%_ if (searchEngineElasticsearch) { _%>
            .flatMap(user1 -> userSearchRepository.save(user1).thenReturn(user1))
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
            .doOnNext(this::clearUserCaches)
      <%_ } _%>
            .doOnNext(user1 -> log.debug("Created Information for User: {}", user1));
    <%_ } else { _%>
        String encryptedPassword = passwordEncoder.encode(RandomUtil.generatePassword());
        user.setPassword(encryptedPassword);
        user.setResetKey(RandomUtil.generateResetKey());
        user.setResetDate(Instant.now());
        user.setActivated(true);
      <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j) { _%>
        if (userDTO.getAuthorities() != null) {
            <%= manyListName%><Authority> authorities = userDTO.getAuthorities().stream()
                .map(authorityDTO -> {
                    Authority authority = new Authority();
                    authority.setId(authorityDTO.getId());
                    authority.setCode(authorityDTO.getCode());
                    return authority;
                })
                .collect(Collectors.to<%= manyListName%>());
            user.setAuthorities(authorities);
        }
      <%_ } else { _%>
        user.setAuthorities(userDTO.getAuthorities());
      <%_ } _%>
        userRepository.<%= ormTool === 'hibernate' ? 'save' : 'insert'%>(user);
      <%_ if (searchEngineElasticsearch) { _%>
        userSearchRepository.index(user);
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
        this.clearUserCaches(user);
      <%_ } _%>
        log.debug("Created Information for User: {}", user);
        return user;
    <%_ } _%>
    }

    /**
     * Update all information for a specific user, and return the modified user.
     *
     * @param userDTO user to update.
     * @return updated user.
     */
    <%_ if (databaseTypeSql && reactive) { _%>
    @Transactional
    <%_ } _%>
    public <% if (reactive) { %>Mono<% } else { %>Optional<% } %><<%= user.adminUserDto %>> updateUser(<%= user.adminUserDto %> userDTO) {
    <%_ if (reactive) { _%>
        return userRepository.findById(userDTO.getId())
            .<%_ if (databaseTypeSql || databaseTypeMongodb) { _%>flatMap<% } else { %>map<% } %>(user -> {
    <%_ } else { _%>
        return Optional.of(userRepository
            .findById(userDTO.getId()))
            .filter(Optional::isPresent)
            .map(Optional::get)
            .map(user -> {
    <%_ } _%>
    <%_ if (databaseTypeCouchbase) { _%>
                if (!user.getLogin().equals(userDTO.getLogin())) {
                    userRepository.deleteById(userDTO.getId());
                }
    <%_ } _%>
    <%_ if (cacheProviderAny) { _%>
                this.clearUserCaches(user);
    <%_ } _%>
                user.setLogin(userDTO.getLogin().toLowerCase());
                user.setFirstName(userDTO.getFirstName());
                user.setLastName(userDTO.getLastName());
                if (userDTO.getEmail() != null) {
                    user.setEmail(userDTO.getEmail().toLowerCase());
                }
    <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase) { _%>
                user.setImageUrl(userDTO.getImageUrl());
    <%_ } _%>
                user.setActivated(userDTO.isActivated());
                user.setLangKey(userDTO.getLangKey());
    <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j) { _%>
                <%= manyListName%><Authority> managedAuthorities = user.getAuthorities();
                managedAuthorities.clear();
    <%_ } else { /* Cassandra & Couchbase */ _%>
                user.setAuthorities(userDTO.getAuthorities());
    <%_ } _%>
    <%_ if (reactive) { _%>
      <%_ if (databaseTypeSql || databaseTypeMongodb) { _%>
        <%_ if (databaseTypeSql) { _%>
                return userRepository
                    .deleteUserAuthorities(user.getId())
                    .thenMany(Flux.fromIterable(userDTO.getAuthorities()))
        <%_ } else { _%>
                return Flux.fromIterable(userDTO.getAuthorities())
        <%_ } _%>
                    .flatMap(authorityRepository::findById)
                    .map(managedAuthorities::add)
                    .then(Mono.just(user));
      <%_ } else { _%>
                return user;
      <%_ } _%>
            })
            .flatMap(this::saveUser)
      <%_ if (searchEngineElasticsearch) { _%>
            .flatMap(user -> userSearchRepository.save(user).thenReturn(user))
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
            .doOnNext(this::clearUserCaches)
      <%_ } _%>
            .doOnNext(user -> log.debug("Changed Information for User: {}", user))
    <%_ } else { /* reactive */ _%>
      <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j) { _%>
                userDTO.getAuthorities().stream()
                    .map(AuthorityDTO::getCode)
                    .map(authorityRepository::findFirstByCode)
                    .filter(Optional::isPresent)
                    .map(Optional::get)
                    .forEach(managedAuthorities::add);
      <%_ } _%>
      <%_ if (ormTool === 'hibernate') { %>
                userRepository.save(user);
      <%_ } else { %>
                this.createOrUpdateAndRelatedRelations(user, <% if (javaVersion === '8') { %>Collections.singletonList("authorities")<% } else { %>List.of("authorities")<% } %>);
      <%_ } _%>
      <%_ if (searchEngineElasticsearch) { _%>
                userSearchRepository.index(user);
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
                this.clearUserCaches(user);
      <%_ } _%>
                log.debug("Changed Information for User: {}", user);
                return user;
            })
    <%_ } _%>
            .map(userMapper::userToAdminUserDTO);
    }

    <%_ if (reactive) { _%>
      <%_ if (databaseTypeSql) { _%>
    @Transactional
      <%_ } _%>
    public Mono<Void> deleteUser(String login) {
        return userRepository.findOneByLogin(login)
            .flatMap(user -> userRepository.delete(user).thenReturn(user))
      <%_ if (searchEngineElasticsearch) { _%>
            .flatMap(user -> userSearchRepository.delete(user).thenReturn(user))
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
            .doOnNext(this::clearUserCaches)
      <%_ } _%>
            .doOnNext(user -> log.debug("Deleted User: {}", user))
            .then();
    }
    <%_ } else { _%>
    public void deleteUser(String login) {
        userRepository.findOneByLogin(login).ifPresent(user -> {
            userRepository.delete<%= ormTool === 'mybatis' ? 'ById' : ''%>(user);
      <%_ if (searchEngineElasticsearch) { _%>
            userSearchRepository.deleteFromIndex(user);
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
            this.clearUserCaches(user);
      <%_ } _%>
            log.debug("Deleted User: {}", user);
        });
    }
    <%_ } _%>
  <%_ } /* authenticationType !== 'oauth2'*/ _%>

    /**
     * Update basic information (first name, last name, email, language) for the current user.
     *
     * @param firstName first name of user.
     * @param lastName  last name of user.
     * @param email     email id of user.
     * @param langKey   language key.
  <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeCouchbase || databaseTypeNeo4j) { _%>
     * @param imageUrl  image URL of user.
  <%_ } _%>
  <%_ if (reactive) { _%>
     * @return a completed {@link Mono}.
  <%_ } _%>
     */
  <%_ if (databaseTypeSql && reactive) { _%>
    @Transactional
  <%_ } _%>
    public <% if (reactive) { %>Mono<Void><% } else { %>void<% } %> updateUser(String firstName, String lastName, String email, String langKey<% if (databaseTypeSql || databaseTypeMongodb || databaseTypeCouchbase || databaseTypeNeo4j) { %>, String imageUrl<% } %>, String mobile) {
        <% if (reactive) { %>return <% } %>SecurityUtils.getCurrentUserLogin()
            .flatMap(userRepository::findOneByLogin)
            .<% if (reactive) { %>flatMap<% } else { %>ifPresent<% } %>(user -> {
                user.setFirstName(firstName);
                user.setLastName(lastName);
                if (email != null) {
                    user.setEmail(email.toLowerCase());
                }
                user.setLangKey(langKey);
                user.setMobile(mobile);
  <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeCouchbase || databaseTypeNeo4j) { _%>
                user.setImageUrl(imageUrl);
  <%_ } _%>
  <%_ if (reactive) { _%>
                return saveUser(user);
            })
    <%_ if (searchEngineElasticsearch) { _%>
            .flatMap(user -> userSearchRepository.save(user).thenReturn(user))
    <%_ } _%>
    <%_ if (cacheProviderAny) { _%>
            .doOnNext(this::clearUserCaches)
    <%_ } _%>
            .doOnNext(user -> log.debug("Changed Information for User: {}", user))
            .then();
  <%_ } else { _%>
                userRepository.save(user);
    <%_ if (searchEngineElasticsearch) { _%>
                userSearchRepository.index(user);
    <%_ } _%>
    <%_ if (cacheProviderAny) { _%>
                this.clearUserCaches(user);
    <%_ } _%>
                log.debug("Changed Information for User: {}", user);
            });
  <%_ } _%>
    }

  <%_ if (reactive) { _%>
    <%_ if (databaseTypeSql && authenticationTypeOauth2) { _%>
    @Transactional
    public Mono<<%= user.persistClass %>> saveUser(<%= user.persistClass %> user) {
        return saveUser(user, false);
    }

    <%_ } _%>
    <%_ if (databaseTypeSql) { _%>
    @Transactional
    <%_ } _%>
    <% if (!databaseTypeSql) { %>private <% } else { %>public <% } %>Mono<<%= user.persistClass %>> saveUser(<%= user.persistClass %> user<% if (databaseTypeSql && authenticationTypeOauth2) { %>, boolean forceCreate<% } %>) {
    <%_ if (databaseTypeCassandra) { _%>
        return userRepository.save(user);
    <%_ } else { _%>
        return SecurityUtils.getCurrentUserLogin()
            .switchIfEmpty(Mono.just(Constants.SYSTEM))
            .flatMap(login -> {
                if (user.getCreatedBy() == null) {
                    user.setCreatedBy(login);
                }
                user.setLastModifiedBy(login);
      <%_ if (databaseTypeSql) { _%>
                // Saving the relationship can be done in an entity callback
                // once https://github.com/spring-projects/spring-data-r2dbc/issues/215 is done
        <%_ if (authenticationTypeOauth2) { _%>
                Mono<<%= user.persistClass %>> persistedUser;
                if (forceCreate) {
                    persistedUser = userRepository.create(user);
                } else {
                    persistedUser = userRepository.save(user);
                }
                return persistedUser
        <%_ } else { _%>
                return userRepository.save(user)
        <%_ } _%>
                    .flatMap(savedUser ->
                        Flux.fromIterable(user.getAuthorities())
                            .flatMap(authority -> userRepository.saveUserAuthority(savedUser.getId(), authority.getName()))
                            .then(Mono.just(savedUser))
                    );
      <%_ } else { _%>
                return userRepository.save(user);
      <%_ } _%>
            });
    <%_ } _%>
    }
  <%_ } _%>
  <%_ if (!authenticationTypeOauth2) { _%>

    <%_ if (databaseTypeSql) { _%>
    @Transactional
    <%_ } _%>
    public <% if (reactive) { %>Mono<Void><% } else { %>void<% } %> changePassword(String currentClearTextPassword, String newPassword) {
        <% if (reactive) { %>return <% } %>SecurityUtils.getCurrentUserLogin()
            .flatMap(userRepository::findOneByLogin)
    <%_ if (reactive) { _%>
            .publishOn(Schedulers.boundedElastic())
            .map(user -> {
    <%_ } else { _%>
            .ifPresent(user -> {
    <%_ } _%>
                String currentEncryptedPassword = user.getPassword();
                if (!passwordEncoder.matches(currentClearTextPassword, currentEncryptedPassword)) {
                    throw new InvalidPasswordException();
                }
                String encryptedPassword = passwordEncoder.encode(newPassword);
                user.setPassword(encryptedPassword);
                <%_ if (ormTool === 'mybatis') { _%>
                userRepository.save(user);
                <%_ } _%>
    <%_ if (reactive) { _%>
                return user;
            })
            .flatMap(this::saveUser)
      <%_ if (cacheProviderAny) { _%>
            .doOnNext(this::clearUserCaches)
      <%_ } _%>
            .doOnNext(user -> log.debug("Changed password for User: {}", user))
            .then();
    <%_ } else { _%>
      <%_ if (databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase || databaseTypeCassandra) { _%>
                userRepository.save(user);
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
                this.clearUserCaches(user);
      <%_ } _%>
                log.debug("Changed password for User: {}", user);
            });
    <%_ } _%>
    }
  <%_ } _%>

  <%_ if (databaseTypeSql && ormTool === 'hibernate') { _%>
    @Transactional(readOnly = true)
  <%_ } _%>
  <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase) { _%>
    public <% if (reactive) { %>Flux<% } else { %><%= pageName %><% } %><<%= user.adminUserDto %>> getAllManagedUsers(<%- pageType %> pageable) {
        return userRepository.<%= ormTool === 'hibernate' ? 'findAll' : 'selectPage'%><% if (reactive) { %><% if (databaseTypeSql) { %>WithAuthorities<% } else { %>By<% if (!databaseTypeCouchbase) { %>IdNotNull<% }}} %>(pageable<% if (ormTool === 'mybatis') { %>, null<% } %>).<%= ormTool === 'hibernate' ? 'map' : 'convert'%>(userMapper::userToAdminUserDTO);
    }

    <%_ if (databaseTypeSql && ormTool === 'hibernate') { _%>
    @Transactional(readOnly = true)
    <%_ } _%>
    public <% if (reactive) { %>Flux<% } else { %><%= pageName %><% } %><<%= user.dtoClass %>> getAllPublicUsers(<%- pageType %> pageable) {
        return userRepository.findAllBy<% if (!databaseTypeCouchbase) { %>IdNotNullAnd<% } %>ActivatedIsTrue(pageable).<%= ormTool === 'hibernate' ? 'map' : 'convert'%>(userMapper::toDto);
    }

    <%_ if (reactive) { _%>

      <%_ if (databaseTypeSql) { _%>
    @Transactional(readOnly = true)
      <%_ } _%>
    public Mono<Long> countManagedUsers() {
        return userRepository.count();
    }
    <%_ } _%>
  <%_ } else { /* Cassandra */ _%>
    public <% if (reactive) { %>Flux<% } else { %>List<% } %><<%= user.adminUserDto %>> getAllManagedUsers() {
        return userRepository.findAll()<% if (!reactive) { %>.stream()<% } %>
            .map(<%= user.adminUserDto %>::new)<% if (!reactive) { %>
            .toList()<% } %>;
    }

    public <% if (reactive) { %>Flux<% } else { %>List<% } %><<%= user.dtoClass %>> getAllPublicUsers() {
        return userRepository.findAll()<% if (!reactive) { %>.stream()<% } %>
            .filter(user -> user.isActivated())
            .map(<%= user.dtoClass %>::new)<% if (!reactive) { %>
            .toList()<% } %>;
    }
  <%_ } _%>

  <%_ if (databaseTypeSql && ormTool === 'hibernate') { _%>
    @Transactional(readOnly = true)
  <%_ } _%>
    public <% if (reactive) { %>Mono<% } else { %>Optional<% } %><<%= user.adminUserDto %>> getUserWithAuthoritiesByLogin(String login) {
  <%_ if (databaseTypeSql) { _%>
        return userRepository.findOneWithAuthoritiesByLogin(login).map(userMapper::userToAdminUserDTO);
  <%_ } else {
      /* MongoDB, Couchbase and Cassandra */
  _%>
        return userRepository.findOneByLogin(login);
  <%_ } _%>
    }

  <%_ if (!authenticationTypeOauth2) { _%>
    <%_ if (databaseTypeSql && ormTool === 'hibernate') { _%>
    @Transactional(readOnly = true)
    <%_ } _%>
    public <% if (reactive) { %>Mono<% } else { %>Optional<% } %><<%= user.persistClass %>> getUserWithAuthorities() {
        return SecurityUtils.getCurrentUserLogin().flatMap(userRepository::findOne<% if (databaseTypeSql) { %>WithAuthorities<% } %>ByLogin);
    }
  <%_ } _%>
  <%_ if ((databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase) && authenticationTypeSession  && !reactive) { _%>

    /**
     * Persistent Token are used for providing automatic authentication, they should be automatically deleted after
     * 30 days.
     * <p>
     * This is scheduled to get fired everyday, at midnight.
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void removeOldPersistentTokens() {
        LocalDate now = LocalDate.now();
        persistentTokenRepository.findByTokenDateBefore(now.minusMonths(1)).forEach(token -> {
            log.debug("Deleting token {}", token.getSeries());<% if (databaseType === 'sql') { %>
            <%= user.persistClass %> user = token.getUser();
            user.getPersistentTokens().remove(token);<% } %>
            persistentTokenRepository.delete(token);
        });
    }
  <%_ } _%>
  <%_ if (!authenticationTypeOauth2 && (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase)) { _%>

    /**
     * Not activated users should be automatically deleted after 3 days.
     * <p>
     * This is scheduled to get fired everyday, at 01:00 (am).
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void removeNotActivatedUsers() {
    <%_ if (reactive) { _%>
        removeNotActivatedUsersReactively().blockLast();
    <%_ } else { _%>
        userRepository
            .findAllByActivatedIsFalseAndActivationKeyIsNotNullAndCreatedDateBefore(ZonedDateTime.now().minus(3, ChronoUnit.DAYS))
            .forEach(user -> {
                log.debug("Deleting not activated user {}", user.getLogin());
                userRepository.delete<%= ormTool === 'mybatis' ? 'ById' : ''%>(user);
      <%_ if (searchEngineElasticsearch) { _%>
                userSearchRepository.deleteFromIndex(user);
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
                this.clearUserCaches(user);
      <%_ } _%>
            });
    <%_ } _%>
    }

    <%_ if (reactive) { _%>
      <%_ if (databaseTypeSql) { _%>
    @Transactional
      <%_ } _%>
    public Flux<<%= user.persistClass %>> removeNotActivatedUsersReactively() {
        return userRepository
            .findAllByActivatedIsFalseAndActivationKeyIsNotNullAndCreatedDateBefore(<%_ if (databaseTypeSql) { _%>LocalDateTime.ofInstant(Instant.now().minus(3, ChronoUnit.DAYS), ZoneOffset.UTC)<%_ } else { _%>Instant.now().minus(3, ChronoUnit.DAYS)<%_ } _%>)
            .flatMap(user -> userRepository.delete(user).thenReturn(user))
      <%_ if (searchEngineElasticsearch) { _%>
            .flatMap(user -> userSearchRepository.delete(user).thenReturn(user))
      <%_ } _%>
      <%_ if (cacheProviderAny) { _%>
            .doOnNext(this::clearUserCaches)
      <%_ } _%>
            .doOnNext(user -> log.debug("Deleted User: {}", user));
    }
    <%_ } _%>
  <%_ } _%>
  <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j || databaseTypeCouchbase) { _%>

    /**
     * Gets a list of all the authorities.
     * @return a list of all the authorities.
     */
    <%_ if (databaseTypeSql && ormTool === 'hibernate') { _%>
    @Transactional(readOnly = true)
    <%_ } _%>
    public <% if (reactive) { %>Flux<% } else { %>List<% } %><String> getAuthorities() {
        return authorityRepository.findAll()<% if (!reactive) { %>.stream()<% } %>.map(Authority::getName)<% if (!reactive) { %>.<% if (javaVersion === '8') { %>collect(Collectors.toList())<% } else { _%>toList()<% } %><% } %>;
    }
  <%_ } _%>
  <%_ if (authenticationTypeOauth2) { _%>

    private <% if (reactive) { %>Mono<<%= user.persistClass %>><% } else { %><%= user.persistClass %><% } %> syncUserWithIdP(Map<String, Object> details, <%= user.persistClass %> user) {
        // save authorities in to sync user roles/groups between IdP and JHipster's local database
    <%_ if (reactive) { _%>
        Collection<String> userAuthorities =
            user.getAuthorities().stream()<% if (!databaseTypeCouchbase) { %>.map(Authority::getName)<% } %>.toList();

        return getAuthorities().collectList()
            .flatMapMany(dbAuthorities -> {
                List<Authority> authoritiesToSave = userAuthorities.stream()
                    .filter(authority -> !dbAuthorities.contains(authority))
                    .map(authority -> {
                        Authority authorityToSave = new Authority();
                        authorityToSave.setName(authority);
                        return authorityToSave;
                    })
                    .toList();
                return Flux.fromIterable(authoritiesToSave);
            })
            .doOnNext(authority -> log.debug("Saving authority '{}' in local database", authority))
            .flatMap(authorityRepository::save)
            .then(userRepository.findOneByLogin(user.getLogin()))
            .switchIfEmpty(<% if (authenticationTypeOauth2 && databaseTypeSql) { %>saveUser(user, true)<% } else { %>userRepository.save(user)<% } %>)
            .flatMap(existingUser -> {
                // if IdP sends last updated information, use it to determine if an update should happen
                if (details.get("updated_at") != null) {
                    Instant dbModifiedDate = existingUser.getLastModifiedDate();
                    Instant idpModifiedDate;
                    if (details.get("updated_at") instanceof Instant) {
                        idpModifiedDate = (Instant) details.get("updated_at");
                    } else {
                        idpModifiedDate = Instant.ofEpochSecond((Integer) details.get("updated_at"));
                    }
                    if (idpModifiedDate.isAfter(dbModifiedDate)) {
                        log.debug("Updating user '{}' in local database", user.getLogin());
                        return updateUser(user.getFirstName(), user.getLastName(), user.getEmail(),
                            user.getLangKey(), user.getImageUrl());
                    }
                    // no last updated info, blindly update
                } else {
                    log.debug("Updating user '{}' in local database", user.getLogin());
                    return updateUser(user.getFirstName(), user.getLastName(), user.getEmail(),
                        user.getLangKey(), user.getImageUrl());
                }
                return Mono.empty();
            })
            .thenReturn(user);
    <%_ } else { _%>
        Collection<String> dbAuthorities = getAuthorities();
      <%_ if (!databaseTypeCouchbase) { _%>
        Collection<String> userAuthorities =
            user.getAuthorities().stream().map(Authority::getName).toList();
      <%_ } else { _%>
        Collection<String> userAuthorities = user.getAuthorities();
      <%_ } _%>
        for (String authority : userAuthorities) {
            if (!dbAuthorities.contains(authority)) {
                log.debug("Saving authority '{}' in local database", authority);
                Authority authorityToSave = new Authority();
                authorityToSave.setName(authority);
                authorityRepository.save(authorityToSave);
            }
        }
        // save account in to sync users between IdP and JHipster's local database
        Optional<<%= user.persistClass %>> existingUser = userRepository.findOneByLogin(user.getLogin());
        if (existingUser.isPresent()) {
            // if IdP sends last updated information, use it to determine if an update should happen
            if (details.get("updated_at") != null) {
                Instant dbModifiedDate = existingUser.orElseThrow().getLastModifiedDate();
                Instant idpModifiedDate;
                if (details.get("updated_at") instanceof Instant) {
                    idpModifiedDate = (Instant) details.get("updated_at");
                } else {
                    idpModifiedDate = Instant.ofEpochSecond((Integer) details.get("updated_at"));
                }
                if (idpModifiedDate.isAfter(dbModifiedDate)) {
                    log.debug("Updating user '{}' in local database", user.getLogin());
                    updateUser(user.getFirstName(), user.getLastName(), user.getEmail(),
                        user.getLangKey(), user.getImageUrl());
                }
                // no last updated info, blindly update
            } else {
                log.debug("Updating user '{}' in local database", user.getLogin());
                updateUser(user.getFirstName(), user.getLastName(), user.getEmail(),
                    user.getLangKey(), user.getImageUrl());
            }
        } else {
            log.debug("Saving user '{}' in local database", user.getLogin());
            userRepository.save(user);
      <%_ if (cacheProviderAny) { _%>
            this.clearUserCaches(user);
      <%_ } _%>
        }
        return user;
    <%_ } _%>
    }
  <%_ } _%>

<%_ } /* databaseType !== 'no' */ _%>
<%_ if (authenticationTypeOauth2) { _%>
    /**
     * Returns the user from an OAuth 2.0 login or resource server with JWT.
  <%_ if (!databaseTypeNo) { _%>
     * Synchronizes the user in the local repository.
  <%_ } _%>
     *
     * @param authToken the authentication token.
     * @return the user from the authentication.
     */
  <%_ if (databaseTypeSql && ormTool === 'hibernate') { _%>
    @Transactional
  <%_ } _%>
    public <% if (reactive) { %>Mono<<%= user.adminUserDto %>><% } else { %><%= user.adminUserDto %><% } %> getUserFromAuthentication(AbstractAuthenticationToken authToken) {
        Map<String, Object> attributes;
        if (authToken instanceof OAuth2AuthenticationToken) {
            attributes = ((OAuth2AuthenticationToken) authToken).getPrincipal().getAttributes();
        } else if (authToken instanceof JwtAuthenticationToken) {
            attributes = ((JwtAuthenticationToken) authToken).getTokenAttributes();
        } else {
            throw new IllegalArgumentException("AuthenticationToken is not OAuth2 or JWT!");
        }
        <%= databaseTypeNo ? user.adminUserDto : user.persistClass %> user = getUser(attributes);
        user.setAuthorities(authToken.getAuthorities().stream()
            .map(GrantedAuthority::getAuthority)
  <%_ if (databaseTypeSql || databaseTypeMongodb || databaseTypeNeo4j) { _%>
            .map(authority -> {
                Authority auth = new Authority();
                auth.setName(authority);
                return auth;
            })
  <%_ } _%>
            .collect(Collectors.toSet()));

  <%_ if (databaseTypeNo) { _%>
        return <% if (reactive) { %>Mono.just(user)<% } else { %>user<% } %>;
  <%_ } else { _%>
    <%_ if (reactive) { _%>
        return syncUserWithIdP(attributes, user).flatMap(u -> Mono.just(new <%= user.adminUserDto %>(u)));
    <%_ } else { _%>
        return new <%= user.adminUserDto %>(syncUserWithIdP(attributes, user));
    <%_ } _%>
  <%_ } _%>
    }

    private static <%= databaseTypeNo ? user.adminUserDto : user.persistClass %> getUser(Map<String, Object> details) {
        <%= databaseTypeNo ? user.adminUserDto : user.persistClass %> user = new <%= databaseTypeNo ? user.adminUserDto : user.persistClass %>();
        Boolean activated = Boolean.TRUE;
        String sub = String.valueOf(details.get("sub"));
        String username = null;
        if (details.get("preferred_username") != null) {
            username = ((String) details.get("preferred_username")).toLowerCase();
        }
        // handle resource server JWT, where sub claim is email and uid is ID
        if (details.get("uid") != null) {
            user.setId((String) details.get("uid"));
            user.setLogin(sub);
        } else {
            user.setId(sub);
        }
        if (username != null) {
            user.setLogin(username);
        } else if (user.getLogin() == null) {
            user.setLogin(user.getId());
        }
        if (details.get("given_name") != null) {
            user.setFirstName((String) details.get("given_name"));
        } else if (details.get("name") != null) {
            user.setFirstName((String) details.get("name"));
        }
        if (details.get("family_name") != null) {
            user.setLastName((String) details.get("family_name"));
        }
        if (details.get("email_verified") != null) {
            activated = (Boolean) details.get("email_verified");
        }
        if (details.get("email") != null) {
            user.setEmail(((String) details.get("email")).toLowerCase());
        } else if (sub.contains("|") && (username != null && username.contains("@"))) {
            // special handling for Auth0
            user.setEmail(username);
        } else {
            user.setEmail(sub);
        }
        if (details.get("langKey") != null) {
            user.setLangKey((String) details.get("langKey"));
        } else if (details.get("locale") != null) {
            // trim off country code if it exists
            String locale = (String) details.get("locale");
            if (locale.contains("_")) {
                locale = locale.substring(0, locale.indexOf('_'));
            } else if (locale.contains("-")) {
                locale = locale.substring(0, locale.indexOf('-'));
            }
            user.setLangKey(locale.toLowerCase());
        } else {
            // set langKey to default if not specified by IdP
            user.setLangKey(Constants.DEFAULT_LANGUAGE);
        }
        if (details.get("picture") != null) {
            user.setImageUrl((String) details.get("picture"));
        }
        user.setActivated(activated);
        return user;
    }
<%_ } _%>
<%_ if (cacheProviderAny && !databaseTypeNo) { _%>

    private void clearUserCaches(<%= user.persistClass %> user) {
        Objects.requireNonNull(cacheManager.getCache(UserRepository.USERS_BY_LOGIN_CACHE)).evict(user.getLogin());
        if (user.getEmail() != null) {
            Objects.requireNonNull(cacheManager.getCache(UserRepository.USERS_BY_EMAIL_CACHE)).evict(user.getEmail());
        }
    }
<%_ } _%>

    /**
     * Update mobile for a specific user, and return the modified user.
     *
     * @param mobile mobile to update.
     * @return updated user.
     */
    <%_ if (databaseTypeSql && ormTool === 'mybatis') { _%>
    @Transactional
    <%_ } _%>
    public <% if (reactive) { %>Mono<% } else { %>Optional<% } %><AdminUserDTO> updateUserMobile(String mobile) {
        <%_ if (!reactive) { _%>
        return Optional
            .of(userRepository.findOneByLogin(SecurityUtils.getCurrentUserLogin().orElseThrow(<% if (javaVersion === '8') { %>() -> new NoSuchElementException("No value present")<% } %>)))
            .filter(Optional::isPresent)
            .map(Optional::get)
            .map(user -> {
        <%_ } else { _%>
        return SecurityUtils.getCurrentUserLogin().flatMap(userRepository::findOneByLogin)
            .<%_ if (['sql', 'mongodb'].includes(databaseType)) { _%>flatMap<% } else { %>map<% } %>(user -> {
        <%_ } _%>
                    user.setMobile(mobile);
                    <%_ if (searchEngineElasticsearch) { _%>
                    userSearchRepository.save(user);
                    <%_ } _%>
                    <%_ if (['mongodb', 'neo4j', 'couchbase', 'cassandra'].includes(databaseType)) { _%>
                    return userRepository.save(user);
                    <%_ } else { _%>
                        <%_ if (ormTool === 'hibernate')  { _%>
                    return userRepository.save(user);
                        <%_ } else { _%>
                        userRepository.save(user);
                        return user;
                        <%_ } _%>
                    <%_ } _%>
                }
            )
            .map(userMapper::userToAdminUserDTO);
    }
    <%_ if (databaseTypeSql && ormTool === 'hibernate') { _%>
    @Transactional(readOnly = true)
    <%_ } _%>
    public <% if (reactive) { %>Mono<% } else { %>Optional<% } %><UserDTO> findOneByMobile(String mobile) {
        log.debug("Request to get Person : {}", mobile);
        return userRepository.findByMobile(mobile)
            .map(userMapper::toDto);
    }
    <%_ if (databaseTypeMongodb) { _%>

    public List<AdminUserDTO> getFieldByCriteria(Query query) {
        return userMapper.usersToAdminUserDTOs(mongoTemplate.find(query, User.class));
    }
    <%_ } _%>

    <%_ if (databaseTypeSql && ormTool === 'hibernate') { _%>
    @Transactional(readOnly = true)
    <%_ } _%>
    public <% if (reactive) { %>Mono<<% } %>Boolean<% if (reactive) { %>><% } %> existsByMobileAndLoginNot(String mobile,String login) {
        log.debug("Request to get Person : {}", mobile);
        return userRepository.existsByMobileAndLoginNot(mobile,login);
    }

    public Optional<AdminUserDTO> getUserWithAuthorities(<%= user.primaryKey.type %> id) {
        return userRepository.findById(id).map(user -> {
            <%_ if (ormTool === 'mybatis') { _%>
            Binder.bindRelations(user);
            <%_ } _%>
            return userMapper.userToAdminUserDTO(user);
        });
    }
}
