adds RbacRoleControllerRestTest + RbacRoleRepositoryIntegrationTest + fix duplicate key
This commit is contained in:
parent
57cf316c00
commit
212b1077c8
@ -1,9 +1,6 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacrole;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.*;
|
||||
import org.hibernate.annotations.Formula;
|
||||
import org.springframework.data.annotation.Immutable;
|
||||
|
||||
@ -14,6 +11,7 @@ import java.util.UUID;
|
||||
@Table(name = "rbacrole_rv")
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Immutable
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@ -25,16 +23,16 @@ public class RbacRoleEntity {
|
||||
@Column(name="objectuuid")
|
||||
private UUID objectUuid;
|
||||
|
||||
@Column(name="roletype")
|
||||
@Enumerated(EnumType.STRING)
|
||||
private RbacRoleType roleType;
|
||||
|
||||
@Column(name="objecttable")
|
||||
private String objectTable;
|
||||
|
||||
@Column(name="objectidname")
|
||||
private String objectIdName;
|
||||
|
||||
@Column(name="roletype")
|
||||
@Enumerated(EnumType.STRING)
|
||||
private RbacRoleType roleType;
|
||||
|
||||
@Formula("objectTable||'#'||objectIdName||'.'||roleType")
|
||||
private String roleName;
|
||||
}
|
||||
|
@ -1,58 +1,17 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacrole;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface RbacRoleRepository extends Repository<RbacRoleEntity, UUID> {
|
||||
|
||||
/**
|
||||
* Retrieves an entity by its id.
|
||||
*
|
||||
* @param id must not be {@literal null}.
|
||||
* @return the entity with the given id or {@literal Optional#empty()} if none found.
|
||||
* @throws IllegalArgumentException if {@literal id} is {@literal null}.
|
||||
*/
|
||||
Optional<RbacRoleEntity> findByUuid(UUID id);
|
||||
|
||||
/**
|
||||
* Returns whether an entity with the given id exists.
|
||||
*
|
||||
* @param id must not be {@literal null}.
|
||||
* @return {@literal true} if an entity with the given id exists, {@literal false} otherwise.
|
||||
* @throws IllegalArgumentException if {@literal id} is {@literal null}.
|
||||
*/
|
||||
boolean existsByUuid(RbacRoleEntity id);
|
||||
|
||||
/**
|
||||
* Returns all instances of the type.
|
||||
*
|
||||
* @return all entities
|
||||
*/
|
||||
Iterable<RbacRoleEntity> findAll();
|
||||
|
||||
/**
|
||||
* Returns all entities sorted by the given options.
|
||||
*
|
||||
* @param sort the {@link Sort} specification to sort the results by, can be {@link Sort#unsorted()}, must not be
|
||||
* {@literal null}.
|
||||
* @return all entities sorted by the given options
|
||||
*/
|
||||
List<RbacRoleEntity> findAll(Sort sort);
|
||||
|
||||
/**
|
||||
* Returns a {@link Page} of entities meeting the paging restriction provided in the {@link Pageable} object.
|
||||
*
|
||||
* @param pageable the pageable to request a paged result, can be {@link Pageable#unpaged()}, must not be
|
||||
* {@literal null}.
|
||||
* @return a page of entities
|
||||
*/
|
||||
Page<RbacRoleEntity> findAll(Pageable pageable);
|
||||
|
||||
List<RbacRoleEntity> findAll();
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,6 @@ declare
|
||||
userUuid uuid;
|
||||
begin
|
||||
raise notice 'will createRole for %', roleDescriptor;
|
||||
raise notice 'will createRole for % % %', roleDescriptor.objecttable, roleDescriptor.objectuuid, roleDescriptor.roletype;
|
||||
roleUuid = createRole(roleDescriptor);
|
||||
|
||||
call grantPermissionsToRole(roleUuid, permissions.permissionUuids);
|
||||
|
@ -24,7 +24,7 @@ create or replace function packageOwner(pac package)
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
begin
|
||||
return roleDescriptor('package', pac.uuid, 'admin');
|
||||
return roleDescriptor('package', pac.uuid, 'owner');
|
||||
end; $$;
|
||||
|
||||
create or replace function packageAdmin(pac package)
|
||||
|
@ -23,7 +23,7 @@ create or replace procedure createPackageTestData(
|
||||
loop
|
||||
CONTINUE WHEN cust.reference < minCustomerReference;
|
||||
|
||||
for t in 0..randominrange(1, 2)
|
||||
for t in 0..2
|
||||
loop
|
||||
pacName = cust.prefix || to_char(t, 'fm00');
|
||||
currentTask = 'creating RBAC test package #' || pacName || ' for customer ' || cust.prefix || ' #' ||
|
||||
@ -59,4 +59,3 @@ do language plpgsql $$
|
||||
end;
|
||||
$$;
|
||||
--//
|
||||
|
||||
|
@ -0,0 +1,54 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacrole;
|
||||
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacrole.TestRbacRole.*;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@WebMvcTest(RbacRoleController.class)
|
||||
class RbacRoleControllerRestTest {
|
||||
|
||||
@Autowired
|
||||
MockMvc mockMvc;
|
||||
@MockBean
|
||||
Context contextMock;
|
||||
@MockBean
|
||||
RbacRoleRepository rbacRoleRepository;
|
||||
|
||||
@Test
|
||||
void apiCustomersWillReturnCustomersFromRepository() throws Exception {
|
||||
|
||||
// given
|
||||
when(rbacRoleRepository.findAll()).thenReturn(
|
||||
asList(hostmasterRole, customerXxxOwner, customerXxxAdmin));
|
||||
|
||||
// when
|
||||
mockMvc.perform(MockMvcRequestBuilders
|
||||
.get("/api/rbacroles")
|
||||
.header("current-user", "mike@hostsharing.net")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
|
||||
// then
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasSize(3)))
|
||||
.andExpect(jsonPath("$[0].roleName", is("global#hostsharing.admin")))
|
||||
.andExpect(jsonPath("$[1].roleName", is("customer#xxx.owner")))
|
||||
.andExpect(jsonPath("$[2].roleName", is("customer#xxx.admin")))
|
||||
.andExpect(jsonPath("$[2].uuid", is(customerXxxAdmin.getUuid().toString())))
|
||||
.andExpect(jsonPath("$[2].objectUuid", is(customerXxxAdmin.getObjectUuid().toString())))
|
||||
.andExpect(jsonPath("$[2].objectTable", is(customerXxxAdmin.getObjectTable().toString())))
|
||||
.andExpect(jsonPath("$[2].objectIdName", is(customerXxxAdmin.getObjectIdName().toString())));
|
||||
}
|
||||
}
|
@ -0,0 +1,169 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacrole;
|
||||
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.orm.jpa.JpaSystemException;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
import static net.hostsharing.test.JpaAttempt.attempt;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DataJpaTest
|
||||
@ComponentScan(basePackageClasses = { Context.class, RbacRoleRepository.class })
|
||||
class RbacRoleRepositoryIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
Context context;
|
||||
|
||||
@Autowired
|
||||
RbacRoleRepository rbacRoleRepository;
|
||||
|
||||
@Autowired EntityManager em;
|
||||
|
||||
@Nested
|
||||
class FindAllRbacRoles {
|
||||
|
||||
private static final String[] ALL_TEST_DATA_ROLES = new String[] {
|
||||
// @formatter:off
|
||||
"global#hostsharing.admin",
|
||||
"customer#aaa.admin", "customer#aaa.owner", "customer#aaa.tenant",
|
||||
"package#aaa00.admin", "package#aaa00.owner", "package#aaa00.tenant",
|
||||
"package#aaa01.admin", "package#aaa01.owner", "package#aaa01.tenant",
|
||||
"package#aaa02.admin", "package#aaa02.owner", "package#aaa02.tenant",
|
||||
"customer#aab.admin", "customer#aab.owner", "customer#aab.tenant",
|
||||
"package#aab00.admin", "package#aab00.owner", "package#aab00.tenant",
|
||||
"package#aab01.admin", "package#aab01.owner", "package#aab01.tenant",
|
||||
"package#aab02.admin", "package#aab02.owner", "package#aab02.tenant",
|
||||
"customer#aac.admin", "customer#aac.owner", "customer#aac.tenant",
|
||||
"package#aac00.admin", "package#aac00.owner", "package#aac00.tenant",
|
||||
"package#aac01.admin", "package#aac01.owner", "package#aac01.tenant",
|
||||
"package#aac02.admin", "package#aac02.owner", "package#aac02.tenant"
|
||||
// @formatter:on
|
||||
};
|
||||
|
||||
@Test
|
||||
public void hostsharingAdmin_withoutAssumedRole_canViewAllRbacRoles() {
|
||||
// given
|
||||
currentUser("mike@hostsharing.net");
|
||||
|
||||
// when
|
||||
final var result = rbacRoleRepository.findAll();
|
||||
|
||||
// then
|
||||
exactlyTheseRbacRolesAreReturned(result, ALL_TEST_DATA_ROLES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hostsharingAdmin_withAssumedHostsharingAdminRole_canViewAllRbacRoles() {
|
||||
given:
|
||||
currentUser("mike@hostsharing.net");
|
||||
assumedRoles("global#hostsharing.admin");
|
||||
|
||||
// when
|
||||
final var result = rbacRoleRepository.findAll();
|
||||
|
||||
then:
|
||||
exactlyTheseRbacRolesAreReturned(result, ALL_TEST_DATA_ROLES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void RbacRoleAdmin_withoutAssumedRole_canViewOnlyItsOwnRbacRole() {
|
||||
// given:
|
||||
currentUser("admin@aaa.example.com");
|
||||
|
||||
// when:
|
||||
final var result = rbacRoleRepository.findAll();
|
||||
|
||||
// then:
|
||||
exactlyTheseRbacRolesAreReturned(
|
||||
result,
|
||||
// @formatter:off
|
||||
"customer#aaa.admin", "customer#aaa.tenant",
|
||||
"package#aaa00.admin", "package#aaa00.owner", "package#aaa00.tenant",
|
||||
"package#aaa01.admin", "package#aaa01.owner", "package#aaa01.tenant",
|
||||
"package#aaa02.admin", "package#aaa02.owner", "package#aaa02.tenant"
|
||||
// @formatter:on
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void RbacRoleAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyItsOwnRbacRole() {
|
||||
currentUser("admin@aaa.example.com");
|
||||
assumedRoles("package#aaa00.admin");
|
||||
|
||||
final var result = rbacRoleRepository.findAll();
|
||||
|
||||
exactlyTheseRbacRolesAreReturned(result, "customer#aaa.tenant", "package#aaa00.tenant", "package#aaa00.admin");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void RbacRoleAdmin_withAssumedAlienPackageAdminRole_cannotViewAnyRbacRole() {
|
||||
// given:
|
||||
currentUser("admin@aaa.example.com");
|
||||
assumedRoles("package#aab00.admin");
|
||||
|
||||
// when
|
||||
final var attempt = attempt(
|
||||
em,
|
||||
() -> rbacRoleRepository.findAll());
|
||||
|
||||
// then
|
||||
attempt.assertExceptionWithRootCauseMessage(
|
||||
JpaSystemException.class,
|
||||
"user admin@aaa.example.com .* has no permission to assume role package#aab00#admin");
|
||||
}
|
||||
|
||||
@Test
|
||||
void unknownUser_withoutAssumedRole_cannotViewAnyRbacRoles() {
|
||||
currentUser("unknown@example.org");
|
||||
|
||||
final var attempt = attempt(
|
||||
em,
|
||||
() -> rbacRoleRepository.findAll());
|
||||
|
||||
attempt.assertExceptionWithRootCauseMessage(
|
||||
JpaSystemException.class,
|
||||
"hsadminng.currentUser defined as unknown@example.org, but does not exists");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void unknownUser_withAssumedRbacRoleRole_cannotViewAnyRbacRoles() {
|
||||
currentUser("unknown@example.org");
|
||||
assumedRoles("RbacRole#aaa.admin");
|
||||
|
||||
final var attempt = attempt(
|
||||
em,
|
||||
() -> rbacRoleRepository.findAll());
|
||||
|
||||
attempt.assertExceptionWithRootCauseMessage(
|
||||
JpaSystemException.class,
|
||||
"hsadminng.currentUser defined as unknown@example.org, but does not exists");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void currentUser(final String currentUser) {
|
||||
context.setCurrentUser(currentUser);
|
||||
assertThat(context.getCurrentUser()).as("precondition").isEqualTo(currentUser);
|
||||
}
|
||||
|
||||
void assumedRoles(final String assumedRoles) {
|
||||
context.assumeRoles(assumedRoles);
|
||||
assertThat(context.getAssumedRoles()).as("precondition").containsExactly(assumedRoles.split(";"));
|
||||
}
|
||||
|
||||
void exactlyTheseRbacRolesAreReturned(final Iterable<RbacRoleEntity> actualResult, final String... rbacRoleNames) {
|
||||
assertThat(actualResult)
|
||||
//.hasSize(rbacRoleNames.length)
|
||||
.extracting(RbacRoleEntity::getRoleName)
|
||||
.containsExactlyInAnyOrder(rbacRoleNames);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacrole;
|
||||
|
||||
import static java.util.UUID.randomUUID;
|
||||
|
||||
public class TestRbacRole {
|
||||
|
||||
public static final RbacRoleEntity hostmasterRole = rbacRole("global", "hostsharing", RbacRoleType.admin);
|
||||
static final RbacRoleEntity customerXxxOwner = rbacRole("customer", "xxx", RbacRoleType.owner);
|
||||
static final RbacRoleEntity customerXxxAdmin = rbacRole("customer", "xxx", RbacRoleType.admin);
|
||||
|
||||
static public RbacRoleEntity rbacRole(final String objectTable, final String objectIdName, final RbacRoleType roleType) {
|
||||
return new RbacRoleEntity(randomUUID(), randomUUID(), objectTable, objectIdName, roleType, objectTable+'#'+objectIdName+'.'+roleType);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user