Skip to content

Commit

Permalink
SHIBUI-1848
Browse files Browse the repository at this point in the history
Corrected groups controller and added testing
  • Loading branch information
chasegawa committed Jun 24, 2021
1 parent 58cf987 commit 47e21b6
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ReloadableMetadat
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
import edu.internet2.tier.shibboleth.admin.ui.security.model.Group
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.GroupsRepository
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.util.ModelRepresentationConversions
Expand All @@ -29,6 +31,7 @@ import javax.annotation.PostConstruct
@Profile('dev')
class DevConfig {
private final UserRepository adminUserRepository
private final GroupsRepository groupsRepository
private final RoleRepository roleRepository

private final MetadataResolverRepository metadataResolverRepository
Expand All @@ -37,6 +40,7 @@ class DevConfig {
private final OpenSamlObjects openSamlObjects

DevConfig(UserRepository adminUserRepository,
GroupsRepository groupsRepository,
MetadataResolverRepository metadataResolverRepository,
RoleRepository roleRepository,
EntityDescriptorRepository entityDescriptorRepository,
Expand All @@ -47,11 +51,32 @@ class DevConfig {
this.roleRepository = roleRepository
this.entityDescriptorRepository = entityDescriptorRepository
this.openSamlObjects = openSamlObjects
this.groupsRepository = groupsRepository
}

@Transactional
@PostConstruct
void createDevUsers() {
void createDevUsersAndGroups() {
if (groupsRepository.count() == 0) {
def groups = [
new Group().with {
it.name = "A1"
it.description = "AAA Group"
it.resourceId = "AAA"
it
},
new Group().with {
it.name = "B1"
it.description = "BBB Group"
it.resourceId = "BBB"
it
}]
groups.each {
groupsRepository.save(it)
}
}
groupsRepository.flush()

if (roleRepository.count() == 0) {
def roles = [new Role().with {
name = 'ROLE_ADMIN'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import edu.internet2.tier.shibboleth.admin.ui.security.service.IGroupService;

@Controller
@RequestMapping(value = "/api/groups")
@RequestMapping(value = "/api/admin/groups")
public class GroupController {
@Autowired
private IGroupService groupService;
Expand All @@ -29,19 +29,19 @@ public class GroupController {
@Transactional
public ResponseEntity<?> create(@RequestBody Group group) {
// If already defined, we can't create a new one, nor will this call update the definition
Group g = groupService.find(group.getResourceId());
Group foundGroup = groupService.find(group.getResourceId());

if (g != null) {
if (foundGroup != null) {
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ServletUriComponentsBuilder.fromCurrentServletMapping().path("/api/groups").build().toUri());
headers.setLocation(ServletUriComponentsBuilder.fromCurrentServletMapping().path("/api/admin/groups").build().toUri());

return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED).headers(headers)
.body(new ErrorResponse(String.valueOf(HttpStatus.METHOD_NOT_ALLOWED.value()),
String.format("The group with resource id: [%s] and name: [%s] already exists.",
group.getResourceId(), group.getName())));
}

Group result = groupService.createOrUpdateGroup(g);
Group result = groupService.createOrUpdateGroup(group);
return ResponseEntity.status(HttpStatus.CREATED).body(result);
}

Expand All @@ -52,15 +52,15 @@ public ResponseEntity<?> update(@RequestBody Group group) {

if (g == null) {
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ServletUriComponentsBuilder.fromCurrentServletMapping().path("/api/groups").build().toUri());
headers.setLocation(ServletUriComponentsBuilder.fromCurrentServletMapping().path("/api/admin/groups").build().toUri());

return ResponseEntity.status(HttpStatus.NOT_FOUND).headers(headers)
.body(new ErrorResponse(String.valueOf(HttpStatus.NOT_FOUND.value()),
String.format("Unable to find group with resource id: [%s] and name: [%s]",
group.getResourceId(), group.getName())));
}

Group result = groupService.createOrUpdateGroup(g);
Group result = groupService.createOrUpdateGroup(group);
return ResponseEntity.ok(result);
}

Expand All @@ -77,7 +77,7 @@ public ResponseEntity<?> getOne(@PathVariable String resourceId) {

if (g == null) {
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ServletUriComponentsBuilder.fromCurrentServletMapping().path("/api/groups").build().toUri());
headers.setLocation(ServletUriComponentsBuilder.fromCurrentServletMapping().path("/api/admin/groups").build().toUri());

return ResponseEntity.status(HttpStatus.NOT_FOUND).headers(headers)
.body(new ErrorResponse(String.valueOf(HttpStatus.NOT_FOUND.value()),
Expand All @@ -93,7 +93,7 @@ public ResponseEntity<?> delete(@PathVariable String resourceId) {

if (g == null) {
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ServletUriComponentsBuilder.fromCurrentServletMapping().path("/api/groups").build().toUri());
headers.setLocation(ServletUriComponentsBuilder.fromCurrentServletMapping().path("/api/admin/groups").build().toUri());

return ResponseEntity.status(HttpStatus.NOT_FOUND).headers(headers)
.body(new ErrorResponse(String.valueOf(HttpStatus.NOT_FOUND.value()),
Expand All @@ -104,7 +104,7 @@ public ResponseEntity<?> delete(@PathVariable String resourceId) {
}
catch (Exception e) {
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ServletUriComponentsBuilder.fromCurrentServletMapping().path("/api/groups").build().toUri());
headers.setLocation(ServletUriComponentsBuilder.fromCurrentServletMapping().path("/api/admin/groups").build().toUri());

return ResponseEntity.status(HttpStatus.CONFLICT).headers(headers)
.body(new ErrorResponse(String.valueOf(HttpStatus.CONFLICT.value()), String.format(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ public class Group {
String name;

@Id
@Column(name = "resource_id", nullable = false)
@Column(name = "resource_id")
String resourceId = UUID.randomUUID().toString();
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import edu.internet2.tier.shibboleth.admin.ui.security.model.Group;

public interface GroupRepository extends JpaRepository<Group, String> {
public interface GroupsRepository extends JpaRepository<Group, String> {
List<Group> findAll();

Group findByResourceId(String id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
import org.springframework.stereotype.Service;

import edu.internet2.tier.shibboleth.admin.ui.security.model.Group;
import edu.internet2.tier.shibboleth.admin.ui.security.repository.GroupRepository;
import edu.internet2.tier.shibboleth.admin.ui.security.repository.GroupsRepository;

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

@Override
public Group createOrUpdateGroup(Group group) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package edu.internet2.tier.shibboleth.admin.ui.security.controller


import groovy.json.JsonOutput
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.MediaType
import org.springframework.security.test.context.support.WithMockUser
import org.springframework.test.annotation.Rollback
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.result.MockMvcResultHandlers
import org.springframework.transaction.annotation.Transactional

import spock.lang.Ignore
import spock.lang.Specification

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status

@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles(["no-auth", "dev"])
@Transactional
class GroupsControllerIntegrationTests extends Specification {
@Autowired
private MockMvc mockMvc

static RESOURCE_URI = '/api/admin/groups'

@Rollback
@WithMockUser(value = "admin", roles = ["ADMIN"])
def 'POST new group persists properly'() {
given:
def newGroup = [name: 'Foo',
description: 'Bar',
resourceId: 'FooBar']

def expectedJson = """
{
"name":"Foo",
"description":"Bar",
"resourceId":"FooBar"
}
"""

when:
def result = mockMvc.perform(post(RESOURCE_URI)
.contentType(MediaType.APPLICATION_JSON)
.content(JsonOutput.toJson(newGroup))
.accept(MediaType.APPLICATION_JSON))

then:
result.andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(content().json(expectedJson, false))

when: 'Try to create with an existing resource id'
result = mockMvc.perform(post(RESOURCE_URI)
.contentType(MediaType.APPLICATION_JSON)
.content(JsonOutput.toJson(newGroup))
.accept(MediaType.APPLICATION_JSON))

then: 'Expecting method not allowed'
result.andExpect(status().isMethodNotAllowed())
}

@Rollback
@WithMockUser(value = "admin", roles = ["ADMIN"])
def 'PUT (update) existing group persists properly'() {
given:
def group = [name: 'NOT AAA',
description: 'updated AAA',
resourceId: 'AAA']

def expectedJson = """
{
"name":"NOT AAA",
"description":"updated AAA",
"resourceId":"AAA"
}
"""
when:
def result = mockMvc.perform(put(RESOURCE_URI)
.contentType(MediaType.APPLICATION_JSON)
.content(JsonOutput.toJson(group))
.accept(MediaType.APPLICATION_JSON))

then:
result.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(content().json(expectedJson, false))

when: 'Try to update with a non-existing resource id'
def newGroup = [name: 'XXXXX',
description: 'should not work',
resourceId: 'XXXX']
def notFoundresult = mockMvc.perform(put(RESOURCE_URI)
.contentType(MediaType.APPLICATION_JSON)
.content(JsonOutput.toJson(newGroup))
.accept(MediaType.APPLICATION_JSON))

then: 'Expecting nothing happened because the object was not found'
notFoundresult.andExpect(status().isNotFound())
}

@WithMockUser(value = "admin", roles = ["ADMIN"])
def 'GET checks for groups (when there are existing groups)'() {
given:
def expectedJson = """
[
{
"name":"A1",
"description":"AAA Group",
"resourceId":"AAA"
},
{
"name":"B1",
"description":"BBB Group",
"resourceId":"BBB"
}
]"""
when: 'GET request is made for ALL groups in the system, and system has groups in it'
def result = mockMvc.perform(get(RESOURCE_URI))
then: 'Request completed with HTTP 200 and returned a list of users'
result.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(content().json(expectedJson, false))
when: 'GET request for a single specific group in a system that has groups'
def singleGroupRequest = mockMvc.perform(get("$RESOURCE_URI/BBB"))
then: 'GET request for a single specific group completed with HTTP 200'
singleGroupRequest.andExpect(status().isOk())
when: 'GET request for a single non-existent group in a system that has groups'
def nonexistentGroupRequest = mockMvc.perform(get("$RESOURCE_URI/CCC"))
then: 'The group not found'
nonexistentGroupRequest.andExpect(status().isNotFound())
}
@Rollback
@WithMockUser(value = "admin", roles = ["ADMIN"])
def 'DELETE ONE existing group'() {
when: 'GET request for a single specific group in a system that has groups'
def result = mockMvc.perform(get("$RESOURCE_URI/BBB"))
then: 'GET request for a single specific group completed with HTTP 200'
result.andExpect(status().isOk())
when: 'DELETE request is made'
result = mockMvc.perform(delete("$RESOURCE_URI/BBB"))
then: 'DELETE was successful'
result.andExpect(status().isNoContent())
when: 'GET request for a single specific group just deleted'
result = mockMvc.perform(get("$RESOURCE_URI/BBB"))
then: 'The group not found'
result.andExpect(status().isNotFound())
when: 'DELETE request for a single specific group that does not exist'
result = mockMvc.perform(delete("$RESOURCE_URI/CCCC"))
then: 'The group not found'
result.andExpect(status().isNotFound())
//ADD conflict test when the group has users
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import spock.lang.Specification
@ContextConfiguration(classes=[InternationalizationConfiguration])
@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"])
@EntityScan("edu.internet2.tier.shibboleth.admin.ui")
class GroupRepositoryTests extends Specification {
class GroupsRepositoryTests extends Specification {
@Autowired
GroupRepository repo
GroupsRepository repo

@Autowired
EntityManager entityManager
Expand Down

0 comments on commit 47e21b6

Please sign in to comment.