UserServiceImpl.java
/*
* Copyright 2019 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.compatibility.service.impl;
import java.util.Date;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.genesys.blocks.security.NoUserFoundException;
import org.genesys.blocks.security.UserException;
import org.gringlobal.compatibility.service.UserService;
import org.gringlobal.model.Cooperator;
import org.gringlobal.model.QSite;
import org.gringlobal.model.QSysLang;
import org.gringlobal.model.QSysUser;
import org.gringlobal.model.SysLang;
import org.gringlobal.model.SysUser;
import org.gringlobal.persistence.CooperatorRepository;
import org.gringlobal.persistence.SysLangRepository;
import org.gringlobal.persistence.SysUserRepository;
import org.gringlobal.soap.Datatable;
import org.gringlobal.soap.Datatable.HasChanges;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedCredentialsNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(readOnly = true)
@DependsOn("applicationStartup")
@Slf4j
public class UserServiceImpl implements UserService {
@Autowired
private SysUserRepository userRepository;
@Autowired
private CooperatorRepository cooperatorRepository;
@Autowired
private SysLangRepository langRepository;
@Autowired
private org.gringlobal.service.UserService userService;
@Override
@PreAuthorize("hasAuthority('GROUP_ADMINS') || hasAuthority('GROUP_CTUSERS')")
public Datatable login(final String username) throws AuthenticationException {
SysUser sysUser = sysUserFromAuthentication();
if (!sysUser.getUsername().equalsIgnoreCase(username)) {
throw new PreAuthenticatedCredentialsNotFoundException("Username mismatch");
}
try {
sysUser = userService.loadSysUser(sysUser.getId());
} catch (NoUserFoundException e) {
throw new PreAuthenticatedCredentialsNotFoundException("No such user");
}
/*@formatter:off*/
/*
<sys_user_id>1</sys_user_id>
<user_name>administrator</user_name>
<is_enabled>Y</is_enabled>
<cooperator_id>48</cooperator_id>
<created_date>2009-01-09T00:00:00-08:00</created_date>
<created_by>1</created_by>
<modified_date>2024-12-08T17:16:49-08:00</modified_date>
<modified_by>48</modified_by>
<owned_date>2009-01-09T00:00:00-08:00</owned_date>
<owned_by>1</owned_by>
<sys_lang_id>1</sys_lang_id>
<site_id>1</site_id>
<site>SYS</site>
<groups>admins allusers ctusers webtools</groups>
<login_token>Qq4ycIMSCFwSUH4UjyvqQjWMKiDPx7SzGsKTTeQNKj/pLE4vmovqrvN3Xou/qGJtj549oAj7DYYccPHTUyUc1NoXFQ6GuPQKZ2O+C98K0IB4MeJsiEeLJE/zwPw1+q9w</login_token>
<warning />
*/
/*@formatter:on*/
final Datatable result = new Datatable("validate_login", List.of(
new Datatable.Column("sys_user_id", QSysUser.sysUser.id.getType()),
new Datatable.Column("user_name", QSysUser.sysUser.username.getType()),
new Datatable.Column("is_enabled", QSysUser.sysUser.isEnabled.getType()),
new Datatable.Column("cooperator_id", QSysUser.sysUser.cooperator().id.getType()),
new Datatable.Column("created_date", Date.class),
new Datatable.Column("created_by", Long.class),
new Datatable.Column("modified_date", Date.class),
new Datatable.Column("owned_date", Date.class),
new Datatable.Column("owned_by", Long.class),
new Datatable.Column("sys_lang_id", QSysLang.sysLang.id.getType()),
new Datatable.Column("site_id", QSite.site.id.getType()),
new Datatable.Column("site", QSite.site.siteShortName.getType()),
new Datatable.Column("groups", String.class),
new Datatable.Column("login_token", String.class),
new Datatable.Column("warning", String.class)
));
Cooperator userCooperator = sysUser.getCooperator();
if (userCooperator == null) {
throw new RuntimeException("User has no Cooperator record.");
}
String userGroups = sysUser.getGroupMaps().stream().map(group -> group.getSysGroup().getAuthority()).reduce("", (a, b) -> a += "\t" + b).strip();
result.addRow(HasChanges.original, sysUser.getId(), sysUser.getUsername(), sysUser.getIsEnabled(), userCooperator.getId(), sysUser.getCreatedDate(), null,
sysUser.getLastModifiedDate(), null, null, userCooperator.getSysLang().getId(),
userCooperator.getSite() == null ? null : userCooperator.getSite().getId(),
userCooperator.getSite() == null ? null : userCooperator.getSite().getSiteShortName(),
userGroups,
// Token
"THIS-IS-NOT-A-TOKEN",
// Warning
null);
return result;
}
@Override
@PreAuthorize("hasAuthority('GROUP_ADMINS') || hasAuthority('GROUP_CTUSERS')")
@Transactional
public Datatable setPassword(final String targetUserName, final String newPassword) throws UserException {
final SysUser sysTargetUser = userRepository.findOne(QSysUser.sysUser.username.eq(targetUserName)).orElse(null);
if (sysTargetUser != null) {
userService.setPassword(sysTargetUser, newPassword);
log.warn("Updated password for {} to {} hashed={}", sysTargetUser.getUsername(), /* newPassword */"*", sysTargetUser.getPassword());
}
return new Datatable();
}
@Override
@PreAuthorize("hasAuthority('GROUP_ADMINS') || hasAuthority('GROUP_CTUSERS')")
@Transactional
public Datatable setLanguage(final long newLanguageID) {
final SysUser sysUser = sysUserFromAuthentication();
final Cooperator cooperator = cooperatorRepository.findById(sysUser.getCooperator().getId()).orElse(sysUser.getCooperator());
final SysLang sysLang = langRepository.findById(newLanguageID).orElse(null);
cooperator.setSysLang(sysLang);
return new Datatable();
}
static SysUser sysUserFromAuthentication() {
SysUser sysUser = null;
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
final Object principal = authentication.getPrincipal();
if (principal instanceof SysUser) {
sysUser = (SysUser) principal;
} else {
log.warn("Principal {} is not SysUser, but type {}. Auth of type {}", principal, principal.getClass(), authentication.getClass());
throw new PreAuthenticatedCredentialsNotFoundException("Principal is not SysUser");
}
}
return sysUser;
}
}