Skip to content

Commit

Permalink
SHIBUI-1740
Browse files Browse the repository at this point in the history
Updates/refactoring to support default admin group.
Updates/refactoring to support users default to their "own" group
  • Loading branch information
chasegawa committed Jul 18, 2021
1 parent 47cd01d commit 7c745c6
Show file tree
Hide file tree
Showing 23 changed files with 1,065 additions and 1,285 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import edu.internet2.tier.shibboleth.admin.ui.security.model.Role
import edu.internet2.tier.shibboleth.admin.ui.security.model.User
import edu.internet2.tier.shibboleth.admin.ui.security.repository.RoleRepository
import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository
import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService
import groovy.util.logging.Slf4j
import org.springframework.boot.context.event.ApplicationStartedEvent
import org.springframework.context.event.EventListener
Expand All @@ -19,11 +20,13 @@ class UserBootstrap {
private final ShibUIConfiguration shibUIConfiguration
private final UserRepository userRepository
private final RoleRepository roleRepository
private final UserService userService

UserBootstrap(ShibUIConfiguration shibUIConfiguration, UserRepository userRepository, RoleRepository roleRepository) {
UserBootstrap(ShibUIConfiguration shibUIConfiguration, UserRepository userRepository, RoleRepository roleRepository, UserService userService) {
this.shibUIConfiguration = shibUIConfiguration
this.userRepository = userRepository
this.roleRepository = roleRepository
this.userService = userService
}

@Transactional
Expand All @@ -50,7 +53,7 @@ class UserBootstrap {
it.emailAddress = email
it
}
userRepository.saveAndFlush(user)
userService.save(user)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
package edu.internet2.tier.shibboleth.admin.ui.configuration;

import javax.servlet.http.HttpServletRequest;

import org.apache.lucene.analysis.Analyzer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.util.UrlPathHelper;

import com.fasterxml.jackson.databind.Module;

import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects;
import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository;
import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository;
Expand All @@ -13,49 +34,28 @@
import edu.internet2.tier.shibboleth.admin.ui.service.DefaultMetadataResolversPositionOrderContainerService;
import edu.internet2.tier.shibboleth.admin.ui.service.DirectoryService;
import edu.internet2.tier.shibboleth.admin.ui.service.DirectoryServiceImpl;
import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService;
import edu.internet2.tier.shibboleth.admin.ui.service.EntityIdsSearchService;
import edu.internet2.tier.shibboleth.admin.ui.service.EntityIdsSearchServiceImpl;
import edu.internet2.tier.shibboleth.admin.ui.service.EntityService;
import edu.internet2.tier.shibboleth.admin.ui.service.FileCheckingFileWritingService;
import edu.internet2.tier.shibboleth.admin.ui.service.FileWritingService;
import edu.internet2.tier.shibboleth.admin.ui.service.FilterService;
import edu.internet2.tier.shibboleth.admin.ui.service.FilterTargetService;
import edu.internet2.tier.shibboleth.admin.ui.service.JPAEntityDescriptorServiceImpl;
import edu.internet2.tier.shibboleth.admin.ui.service.JPAEntityServiceImpl;
import edu.internet2.tier.shibboleth.admin.ui.service.JPAFilterServiceImpl;
import edu.internet2.tier.shibboleth.admin.ui.service.JPAFilterTargetServiceImpl;
import edu.internet2.tier.shibboleth.admin.ui.service.JPAMetadataResolverServiceImpl;
import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverService;
import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolversPositionOrderContainerService;
import edu.internet2.tier.shibboleth.admin.util.AttributeUtility;
import edu.internet2.tier.shibboleth.admin.util.EntityDescriptorConverstionUtils;
import edu.internet2.tier.shibboleth.admin.util.LuceneUtility;
import edu.internet2.tier.shibboleth.admin.util.ModelRepresentationConversions;
import org.apache.lucene.analysis.Analyzer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.util.UrlPathHelper;

import javax.servlet.http.HttpServletRequest;

@Configuration
@EnableConfigurationProperties({CustomPropertiesConfiguration.class, ShibUIConfiguration.class})
@ComponentScan(basePackages="{ edu.internet2.tier.shibboleth.admin.ui.service }")
@EnableConfigurationProperties({ CustomPropertiesConfiguration.class, ShibUIConfiguration.class })
public class CoreShibUiConfiguration {
private static final Logger logger = LoggerFactory.getLogger(CoreShibUiConfiguration.class);

@Bean
public OpenSamlObjects openSamlObjects() {
return new OpenSamlObjects();
Expand All @@ -65,12 +65,7 @@ public OpenSamlObjects openSamlObjects() {
public EntityService jpaEntityService() {
return new JPAEntityServiceImpl(openSamlObjects());
}

@Bean
public EntityDescriptorService jpaEntityDescriptorService(UserService userService) {
return new JPAEntityDescriptorServiceImpl(openSamlObjects(), jpaEntityService(), userService);
}


@Bean
public FilterService jpaFilterService() {
return new JPAFilterServiceImpl();
Expand Down Expand Up @@ -99,13 +94,18 @@ public AttributeUtility attributeUtility() {

@Bean
@ConditionalOnProperty(name = "shibui.metadata-dir")
public EntityDescriptorFilesScheduledTasks entityDescriptorFilesScheduledTasks(EntityDescriptorRepository entityDescriptorRepository, @Value("${shibui.metadata-dir}") final String metadataDir) {
return new EntityDescriptorFilesScheduledTasks(metadataDir, entityDescriptorRepository, openSamlObjects(), fileWritingService());
public EntityDescriptorFilesScheduledTasks entityDescriptorFilesScheduledTasks(
EntityDescriptorRepository entityDescriptorRepository,
@Value("${shibui.metadata-dir}") final String metadataDir) {
return new EntityDescriptorFilesScheduledTasks(metadataDir, entityDescriptorRepository, openSamlObjects(),
fileWritingService());
}

@Bean
@ConditionalOnProperty(name = "shibui.metadataProviders.target")
public MetadataProvidersScheduledTasks metadataProvidersScheduledTasks(@Value("${shibui.metadataProviders.target}") final Resource resource, final MetadataResolverService metadataResolverService) {
public MetadataProvidersScheduledTasks metadataProvidersScheduledTasks(
@Value("${shibui.metadataProviders.target}") final Resource resource,
final MetadataResolverService metadataResolverService) {
return new MetadataProvidersScheduledTasks(resource, metadataResolverService, fileWritingService());
}

Expand All @@ -124,7 +124,8 @@ public LocaleChangeInterceptor localeChangeInterceptor() {
/**
* A WebMvcConfigurer that won't mangle the path for the entities endpoint.
*
* inspired by [ https://stackoverflow.com/questions/13482020/encoded-slash-2f-with-spring-requestmapping-path-param-gives-http-400 ]
* inspired by [
* https://stackoverflow.com/questions/13482020/encoded-slash-2f-with-spring-requestmapping-path-param-gives-http-400 ]
*
* @return configurer
*/
Expand Down Expand Up @@ -166,10 +167,9 @@ public void addInterceptors(InterceptorRegistry registry) {
}

@Bean
public MetadataResolversPositionOrderContainerService
metadataResolversPositionOrderContainerService(MetadataResolversPositionOrderContainerRepository
positionOrderContainerRepository,
MetadataResolverRepository resolverRepository) {
public MetadataResolversPositionOrderContainerService metadataResolversPositionOrderContainerService(
MetadataResolversPositionOrderContainerRepository positionOrderContainerRepository,
MetadataResolverRepository resolverRepository) {

return new DefaultMetadataResolversPositionOrderContainerService(positionOrderContainerRepository, resolverRepository);

Expand Down Expand Up @@ -209,4 +209,11 @@ public UserService userService(RoleRepository roleRepository, UserRepository use
public FileWritingService fileWritingService() {
return new FileCheckingFileWritingService();
}

@Bean
public EntityDescriptorConverstionUtils EntityDescriptorConverstionUtilsInit(EntityService entityService, OpenSamlObjects oso) {
EntityDescriptorConverstionUtils.setEntityService(entityService);
EntityDescriptorConverstionUtils.setOpenSamlObjects(oso);
return new EntityDescriptorConverstionUtils();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import edu.internet2.tier.shibboleth.admin.ui.security.model.User;
import edu.internet2.tier.shibboleth.admin.ui.security.repository.RoleRepository;
import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository;
import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService;
import edu.internet2.tier.shibboleth.admin.ui.security.springsecurity.AdminUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
Expand All @@ -28,10 +29,10 @@

import java.util.Collections;

import javax.transaction.Transactional;

/**
* Web security configuration.
* <p>
* Workaround for slashes in URL from [https://stackoverflow.com/questions/48453980/spring-5-0-3-requestrejectedexception-the-request-was-rejected-because-the-url]
*/
@Configuration
@ConditionalOnMissingBean(WebSecurityConfigurerAdapter.class)
Expand All @@ -46,6 +47,9 @@ public class WebSecurityConfig {
@Autowired
private UserRepository userRepository;

@Autowired
private UserService userService;

@Autowired
private RoleRepository roleRepository;

Expand Down Expand Up @@ -82,6 +86,7 @@ protected void configure(HttpSecurity http) throws Exception {
}

@Override
@Transactional
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// TODO: more configurable authentication
PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
Expand All @@ -100,10 +105,10 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
});
u.setRoles(Collections.singleton(adminRole));
u.setEmailAddress("admin@localhost");
return userRepository.saveAndFlush(u);
return userService.save(u);
});
adminUser.setPassword(defaultPassword);
userRepository.saveAndFlush(adminUser);
userService.save(adminUser);

auth
.inMemoryAuthentication()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public IDPSSODescriptor getIDPSSODescriptor(String s) {
}

public Group getGroup() {
return group == null ? Group.DEFAULT_GROUP : group;
return group == null ? Group.ADMIN_GROUP : group;
}

@Transient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public String getId() {
}

public String getGroupId() {
return groupId == null ? Group.DEFAULT_GROUP.getResourceId() : groupId;
return groupId == null ? Group.ADMIN_GROUP.getResourceId() : groupId;
}

public List<LogoutEndpointRepresentation> getLogoutEndpoints() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ public interface EntityDescriptorRepository extends JpaRepository<EntityDescript
* SHIBUI-1740 This is here to aid in migration of systems using the SHIBUI prior to group functionality being added
* @deprecated - this is intended to be removed at some future date and is here only for migration purposes.
*/
@Deprecated
List<EntityDescriptor> findAllByGroupIsNull();
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,18 @@
@Entity(name = "user_groups")
@Data
public class Group {
public Group() {
}

public Group(User user) {
resourceId=user.getUsername();
name=user.getUsername();
description="default user-group";
}

@Transient
@JsonIgnore
public static Group DEFAULT_GROUP;
public static Group ADMIN_GROUP;

@Column(name = "group_description", nullable = true)
String description;
Expand All @@ -46,7 +55,4 @@ public class Group {
@JsonIgnore
@EqualsAndHashCode.Exclude
Set<EntityDescriptor> entityDescriptors;

@Column(name = "default_group", nullable = false)
boolean defaultGroup = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ public class User extends AbstractAuditable {
private String username;

public Group getGroup() {
return group == null ? Group.DEFAULT_GROUP : group;
return group;
}

public String getGroupId() {
if (groupId == null && getGroup() != null) {
groupId = getGroup().getResourceId();
if (groupId == null) {
groupId = group == null ? null : getGroup().getResourceId();
}
return groupId;
}
Expand All @@ -91,10 +91,11 @@ public String getRole() {
return this.role;
}

/**
* If (for some reason) the incoming group is null, the user is defaulted to their own group
*/
public void setGroup(Group assignedGroup) {
this.group = assignedGroup;
if (group != null) {
groupId = group.getResourceId();
}
this.groupId = getGroup().getResourceId();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,4 @@ public interface GroupsRepository extends JpaRepository<Group, String> {

@SuppressWarnings("unchecked")
Group save(Group group);

Group findByDefaultGroupTrue();
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package edu.internet2.tier.shibboleth.admin.ui.security.service;

import java.util.List;
import java.util.UUID;

import javax.annotation.PostConstruct;
import javax.transaction.Transactional;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

Expand All @@ -16,10 +15,17 @@
import edu.internet2.tier.shibboleth.admin.ui.security.repository.GroupsRepository;

@Service
public class GroupServiceImpl implements IGroupService {
public class GroupServiceImpl implements IGroupService, InitializingBean {
@Autowired
private GroupsRepository repo;

public GroupServiceImpl() {
}

public GroupServiceImpl(GroupsRepository repo) {
this.repo = repo;
}

@Override
public Group createGroup(Group group) throws GroupExistsConflictException {
Group foundGroup = find(group.getResourceId());
Expand Down Expand Up @@ -63,18 +69,19 @@ public Group updateGroup(Group group) throws EntityNotFoundException {
return repo.save(group);
}

@PostConstruct
/**
* Ensure (mostly for migrations) that we have defined a default admin group
*/
@Override
@Transactional
private void ensureDefaultGroupExists() {
// This is something of a migration piece to ensure there is a default group that users and entity descriptors
// can be assigned to out of the box.
Group g = repo.findByDefaultGroupTrue();
public void afterPropertiesSet() {
Group g = repo.findByResourceId("admingroup");
if (g == null) {
g = new Group();
g.setDefaultGroup(true);
g.setName("DEFAULT-GROUP");
g.setName("ADMIN-GROUP");
g.setResourceId("admingroup");
g = repo.save(g);
}
Group.DEFAULT_GROUP = g;
Group.ADMIN_GROUP = g;
}
}
Loading

0 comments on commit 7c745c6

Please sign in to comment.