WebUserServiceImpl.java

/*
 * Copyright 2020 Global Crop Diversity Trust
 *
 * 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
 *
 *   http://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 org.gringlobal.service.impl;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import javax.persistence.EntityManager;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.gringlobal.custom.elasticsearch.SearchException;
import org.gringlobal.model.WebCooperator;
import org.gringlobal.model.WebUser;
import org.gringlobal.model.security.UserRole;
import org.gringlobal.persistence.WebUserRepository;
import org.gringlobal.service.WebCooperatorService;
import org.gringlobal.service.WebUserService;
import org.gringlobal.service.filter.WebUserFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * The Class WebUserServiceImpl.
 */
@Service(value = "webUserService")
@Slf4j
public class WebUserServiceImpl extends FilteredCRUDServiceImpl<WebUser, WebUserFilter, WebUserRepository> implements WebUserService {

	@Autowired
	@Qualifier("soapPasswordEncoder")
	private PasswordEncoder soapPasswordEncoder;

	@Autowired
	private Validator validator;

	@Autowired
	private WebCooperatorService webCooperatorService;

	@Autowired
	private EntityManager entityManager;

	@Override
	@Transactional
	public WebUser upsertWebCooperator(WebUser webUser, WebCooperator source) {
		WebUser loaded = reload(webUser);

		if (loaded.getWebCooperator() == null) {
			loaded.setWebCooperator(webCooperatorService.create(source));
			repository.save(loaded);
		} else {
			webCooperatorService.update(source, loaded.getWebCooperator());
		}
		return reload(loaded);
	}

	@Override
	@Transactional
	public WebUser create(WebUser source) {
		WebUser webUser = new WebUser();
		webUser.setIsEnabled(source.getIsEnabled());
		webUser.setWebCooperator(source.getWebCooperator());
		webUser.setSysLang(source.getSysLang());
		webUser.setUsername(source.getUsername());
		webUser.setPassword(soapPasswordEncoder.encode(source.getPassword()));

		final var saved = repository.save(webUser);
		return _lazyLoad(saved);
	}


	@Override
	@Transactional
	public WebUser update(WebUser source, WebUser target) {
		target.setIsEnabled(source.getIsEnabled());
		target.setWebCooperator(source.getWebCooperator());
		target.setSysLang(source.getSysLang());

		Set<ConstraintViolation<WebUser>> violations = validator.validate(target);
		if (CollectionUtils.isNotEmpty(violations))
			throw new ConstraintViolationException("Invalid WebUser.", violations);

		final var saved = repository.save(target);
		return _lazyLoad(saved);
	}

	@Override
	@Transactional
	@PreAuthorize("hasRole('ADMINISTRATOR')")
	public WebUser remove(WebUser entity) {
		return super.remove(entity);
	}

	@Override
	@PreAuthorize("hasRole('ADMINISTRATOR')")
	public Page<WebUser> list(WebUserFilter filter, Pageable page) throws SearchException {
		return super.list(WebUser.class, filter, page);
	}

	@Override
	@Transactional
	@PreAuthorize("hasRole('ADMINISTRATOR')")
	public WebUser setAccountActive(Long id, boolean enabled) {
		WebUser user = get(id);
		user.setIsEnabled(enabled ? "Y" : "N");
		final var saved = repository.save(user);
		return _lazyLoad(saved);
	}

	@Override
	@Transactional
	public WebUser setPassword(Long id, String password) {
		final WebUser user = get(id);
		user.setPassword(soapPasswordEncoder.encode(password));
		return repository.save(user);
	}

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		WebUser webUser = repository.findByUsername(username);
		if (webUser == null) {
			throw new UsernameNotFoundException("Username not found");
		}
		log.debug("Found web user {} for name: {}", webUser, username);

		webUser.lazyLoad();
		webUser.setRuntimeAuthorities(List.of(UserRole.WEBUSER, UserRole.EVERYONE));

		log.debug("WebUser {}#{} has authorities: {}", webUser.getUsername(), webUser.getId(), webUser.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.joining(
				",")));

		entityManager.detach(webUser);
		return webUser;
	}
}