package org.molgenis.security.user;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import org.molgenis.auth.*;
import org.molgenis.data.DataService;
import org.molgenis.data.support.QueryImpl;
import org.molgenis.security.core.runas.RunAsSystem;
import org.molgenis.security.core.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static java.util.stream.Collectors.toList;
import static org.molgenis.auth.GroupAuthorityMetaData.GROUP_AUTHORITY;
import static org.molgenis.auth.GroupMemberMetaData.GROUP_MEMBER;
import static org.molgenis.auth.UserMetaData.USER;
import static org.molgenis.auth.UserAuthorityMetaData.USER_AUTHORITY;
public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService
{
private final DataService dataService;
private final GrantedAuthoritiesMapper grantedAuthoritiesMapper;
@Autowired
public UserDetailsService(DataService dataService, GrantedAuthoritiesMapper grantedAuthoritiesMapper)
{
if (dataService == null) throw new IllegalArgumentException("DataService is null");
if (grantedAuthoritiesMapper == null) throw new IllegalArgumentException("Granted authorities mapper is null");
this.dataService = dataService;
this.grantedAuthoritiesMapper = grantedAuthoritiesMapper;
}
@Override
@RunAsSystem
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
try
{
User user = dataService
.findOne(USER, new QueryImpl<User>().eq(UserMetaData.USERNAME, username),
User.class);
if (user == null) throw new UsernameNotFoundException("unknown user '" + username + "'");
Collection<? extends GrantedAuthority> authorities = getAuthorities(user);
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), user.isActive(), true, true, true, authorities);
}
catch (Throwable e)
{
throw new RuntimeException(e);
}
}
public Collection<? extends GrantedAuthority> getAuthorities(User user)
{
// user authorities
List<? extends Authority> authorities = getUserAuthorities(user);
List<GrantedAuthority> grantedAuthorities =
authorities != null ? Lists.transform(authorities, new Function<Authority, GrantedAuthority>()
{
@Override
public GrantedAuthority apply(Authority authority)
{
return new SimpleGrantedAuthority(authority.getRole());
}
}) : null;
// // user group authorities
List<GroupAuthority> groupAuthorities = getGroupAuthorities(user);
List<GrantedAuthority> grantedGroupAuthorities = groupAuthorities != null ? Lists
.transform(groupAuthorities, new Function<GroupAuthority, GrantedAuthority>()
{
@Override
public GrantedAuthority apply(GroupAuthority groupAuthority)
{
return new SimpleGrantedAuthority(groupAuthority.getRole());
}
}) : null;
// union of user and group authorities
Set<GrantedAuthority> allGrantedAuthorities = new HashSet<GrantedAuthority>();
if (grantedAuthorities != null) allGrantedAuthorities.addAll(grantedAuthorities);
if (grantedGroupAuthorities != null) allGrantedAuthorities.addAll(grantedGroupAuthorities);
if (user.isSuperuser() != null && user.isSuperuser().booleanValue() == true)
{
allGrantedAuthorities.add(new SimpleGrantedAuthority(SecurityUtils.AUTHORITY_SU));
}
return grantedAuthoritiesMapper.mapAuthorities(allGrantedAuthorities);
}
private List<UserAuthority> getUserAuthorities(User user)
{
return dataService.findAll(USER_AUTHORITY,
new QueryImpl<UserAuthority>().eq(UserAuthorityMetaData.USER, user),
UserAuthority.class).collect(toList());
}
private List<GroupAuthority> getGroupAuthorities(User user)
{
List<GroupMember> groupMembers = dataService.findAll(GROUP_MEMBER,
new QueryImpl<GroupMember>().eq(GroupMemberMetaData.USER, user),
GroupMember.class).collect(toList());
if (!groupMembers.isEmpty())
{
List<Group> groups = Lists
.transform(groupMembers, new Function<GroupMember, Group>()
{
@Override
public Group apply(GroupMember groupMember)
{
return groupMember.getGroup();
}
});
return dataService.findAll(GROUP_AUTHORITY,
new QueryImpl<GroupAuthority>().in(GroupAuthorityMetaData.GROUP, groups),
GroupAuthority.class).collect(toList());
}
return null;
}
}