From 97314fe641ffbab4f2f4f6a17408a78feca65744 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 13 Nov 2018 14:29:37 -0500 Subject: [PATCH] SHIBUI-975 --- .../admin/ui/ShibbolethUiApplication.java | 5 +- .../admin/ui/security/model/AdminRole.java | 6 +-- .../admin/ui/security/model/AdminUser.java | 2 +- .../springsecurity/AdminUserService.java | 3 +- .../src/main/resources/application.properties | 2 +- .../AdminUserServiceTests.groovy | 53 +++++++++++++++++++ 6 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/security/springsecurity/AdminUserServiceTests.groovy diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java index 84941894f..e9e4d33ae 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java @@ -66,9 +66,6 @@ public static class SampleAdminUsersCreator { @Autowired AdminUserRepository adminUserRepository; - @Autowired - AdminRoleRepository adminRoleRepository; - @Transactional @EventListener void createSampleAdminUsers(ApplicationStartedEvent e) { @@ -79,7 +76,7 @@ void createSampleAdminUsers(ApplicationStartedEvent e) { user.setUsername("admin"); user.setPassword("{noop}adminpass"); - //The complexity of managing bi-directional many-to-many. TODO: to encapsulate this association + //The complexity of managing bi-directional many-to-many. TODO: encapsulate this association //managing logic into domain model itself role.getAdmins().add(user); user.getRoles().add(role); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/model/AdminRole.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/model/AdminRole.java index b2e202359..faa7e3167 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/model/AdminRole.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/model/AdminRole.java @@ -1,8 +1,6 @@ package edu.internet2.tier.shibboleth.admin.ui.security.model; -import com.fasterxml.jackson.annotation.JsonProperty; import edu.internet2.tier.shibboleth.admin.ui.domain.AbstractAuditable; -import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; @@ -13,8 +11,6 @@ import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import java.util.HashSet; import java.util.Set; @@ -35,7 +31,7 @@ public class AdminRole extends AbstractAuditable { @Column(unique = true) private String name; - @ManyToMany(cascade = CascadeType.PERSIST, mappedBy = "roles", fetch = FetchType.EAGER) + @ManyToMany(cascade = CascadeType.ALL, mappedBy = "roles", fetch = FetchType.EAGER) private Set admins = new HashSet<>(); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/model/AdminUser.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/model/AdminUser.java index e56052a2c..0294c14bb 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/model/AdminUser.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/model/AdminUser.java @@ -39,7 +39,7 @@ public class AdminUser extends AbstractAuditable { private String lastName; @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) - @ManyToMany(cascade = CascadeType.PERSIST) + @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name = "adminuser_role", joinColumns = @JoinColumn(name = "admin_user_id"), inverseJoinColumns = @JoinColumn(name = "admin_role_id")) private Set roles = new HashSet<>(); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/springsecurity/AdminUserService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/springsecurity/AdminUserService.java index 02c052bee..c1f1c06b8 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/springsecurity/AdminUserService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/springsecurity/AdminUserService.java @@ -16,7 +16,7 @@ import static java.util.stream.Collectors.toSet; /** - * Spring Security {@link UserDetailsService} implementation for local administration of admin users ins the system. + * Spring Security {@link UserDetailsService} implementation for local administration of admin users in the system. * * @author Dmitriy Kopylenko */ @@ -38,6 +38,7 @@ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundEx .collect(toSet()); if (grantedAuthorities.isEmpty()) { + //As defined by the UserDetailsService API contract throw new UsernameNotFoundException(String.format("No roles are defined for user [%s]", username)); } diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index b108787bd..3e95e06b7 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -4,7 +4,7 @@ # Logging Configuration #logging.config=classpath:log4j2.xml -logging.level.org.springframework.security=DEBUG +#logging.level.org.springframework.security=DEBUG logging.level.org.springframework=INFO logging.level.edu.internet2.tier.shibboleth.admin.ui=INFO diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/security/springsecurity/AdminUserServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/security/springsecurity/AdminUserServiceTests.groovy new file mode 100644 index 000000000..40b92e561 --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/security/springsecurity/AdminUserServiceTests.groovy @@ -0,0 +1,53 @@ +package edu.internet2.tier.shibboleth.admin.ui.security.springsecurity + +import edu.internet2.tier.shibboleth.admin.ui.security.repository.AdminRoleRepository +import edu.internet2.tier.shibboleth.admin.ui.security.repository.AdminUserRepository +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.context.annotation.Profile +import org.springframework.security.core.userdetails.UsernameNotFoundException +import org.springframework.test.annotation.DirtiesContext +import org.springframework.test.context.ActiveProfiles +import spock.lang.Specification + +/** + * Tests for AdminUserService + * + * @author Dmitriy Kopylenko + */ +@SpringBootTest +@ActiveProfiles('dev') +class AdminUserServiceTests extends Specification { + + @Autowired + AdminUserService adminUserService + + @Autowired + AdminRoleRepository adminRoleRepository + + @Autowired + AdminUserRepository adminUserRepository + + + def "Loading existing admin user with admin role"() { + given: 'Valid user with admin role is available (loaded by Spring Boot Listener in dev profile)' + def user = adminUserService.loadUserByUsername('admin') + + expect: + user.username == 'admin' + user.password == '{noop}adminpass' + user.getAuthorities().size() == 1 + user.getAuthorities()[0].authority == 'ROLE_ADMIN' + user.enabled + user.accountNonExpired + user.credentialsNonExpired + } + + def "Loading NON-existing admin user with admin role"() { + when: 'Non-existent admin user is tried to be looked up' + adminUserService.loadUserByUsername('nonexisting') + + then: + thrown UsernameNotFoundException + } +}