use context.define(...) instead of setCurrent...
This commit is contained in:
parent
7d4815e2cf
commit
4aa8b85bb6
@ -191,7 +191,7 @@ jacocoTestCoverageVerification {
|
|||||||
'net.hostsharing.hsadminng.generated.**',
|
'net.hostsharing.hsadminng.generated.**',
|
||||||
'net.hostsharing.hsadminng.HsadminNgApplication',
|
'net.hostsharing.hsadminng.HsadminNgApplication',
|
||||||
'net.hostsharing.hsadminng.TestController',
|
'net.hostsharing.hsadminng.TestController',
|
||||||
'net.hostsharing.hsadminng.Mapper',
|
'net.hostsharing.hsadminng.Mapper'
|
||||||
]
|
]
|
||||||
|
|
||||||
limit {
|
limit {
|
||||||
@ -205,7 +205,8 @@ jacocoTestCoverageVerification {
|
|||||||
excludes = [
|
excludes = [
|
||||||
'net.hostsharing.hsadminng.generated.**',
|
'net.hostsharing.hsadminng.generated.**',
|
||||||
'net.hostsharing.hsadminng.HsadminNgApplication.main',
|
'net.hostsharing.hsadminng.HsadminNgApplication.main',
|
||||||
'net.hostsharing.hsadminng.TestController.*']
|
'net.hostsharing.hsadminng.TestController.*'
|
||||||
|
]
|
||||||
|
|
||||||
limit {
|
limit {
|
||||||
counter = 'BRANCH'
|
counter = 'BRANCH'
|
||||||
|
@ -1,20 +1,33 @@
|
|||||||
package net.hostsharing.hsadminng.context;
|
package net.hostsharing.hsadminng.context;
|
||||||
|
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.PersistenceContext;
|
import javax.persistence.PersistenceContext;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static java.util.function.Predicate.not;
|
||||||
import static org.springframework.transaction.annotation.Propagation.MANDATORY;
|
import static org.springframework.transaction.annotation.Propagation.MANDATORY;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class Context {
|
public class Context {
|
||||||
|
|
||||||
|
private static final Set<String> HEADERS_TO_IGNORE = Set.of(
|
||||||
|
"accept-encoding",
|
||||||
|
"connection",
|
||||||
|
"content-length",
|
||||||
|
"host",
|
||||||
|
"user-agent");
|
||||||
@PersistenceContext
|
@PersistenceContext
|
||||||
private EntityManager em;
|
private EntityManager em;
|
||||||
|
|
||||||
@ -22,81 +35,111 @@ public class Context {
|
|||||||
private HttpServletRequest request;
|
private HttpServletRequest request;
|
||||||
|
|
||||||
@Transactional(propagation = MANDATORY)
|
@Transactional(propagation = MANDATORY)
|
||||||
public void register(final String currentUser, final String assumedRoles) {
|
public void define(final String currentUser) {
|
||||||
if (request != null) {
|
define(currentUser, null);
|
||||||
setCurrentTask(request.getMethod() + " " + request.getRequestURI());
|
|
||||||
} else {
|
|
||||||
|
|
||||||
final Optional<StackWalker.StackFrame> caller =
|
|
||||||
StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
|
|
||||||
.walk(frames ->
|
|
||||||
frames.skip(1)
|
|
||||||
.filter(c -> c.getDeclaringClass()
|
|
||||||
.getPackageName()
|
|
||||||
.startsWith("net.hostsharing.hsadminng"))
|
|
||||||
.filter(c -> !c.getDeclaringClass().getName().contains("BySpringCGLIB$$"))
|
|
||||||
.findFirst());
|
|
||||||
final var callerName = caller.map(
|
|
||||||
c -> c.getDeclaringClass().getSimpleName() + "." + c.getMethodName())
|
|
||||||
.orElse("unknown");
|
|
||||||
setCurrentTask(callerName);
|
|
||||||
}
|
|
||||||
setCurrentUser(currentUser);
|
|
||||||
if (!StringUtils.isBlank(assumedRoles)) {
|
|
||||||
assumeRoles(assumedRoles);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(propagation = MANDATORY)
|
@Transactional(propagation = MANDATORY)
|
||||||
public void setCurrentTask(final String task) {
|
public void define(final String currentUser, final String assumedRoles) {
|
||||||
final var sql = String.format(
|
define(toTask(request), toCurl(request), currentUser, assumedRoles);
|
||||||
"set local hsadminng.currentTask = '%s';",
|
}
|
||||||
shortenToMaxLength(task, 95)
|
|
||||||
);
|
@Transactional(propagation = MANDATORY)
|
||||||
em.createNativeQuery(sql).executeUpdate();
|
public void define(
|
||||||
|
final String currentTask,
|
||||||
|
final String currentRequest,
|
||||||
|
final String currentUser,
|
||||||
|
final String assumedRoles) {
|
||||||
|
final var query = em.createNativeQuery(
|
||||||
|
"call defineContext(:currentTask, :currentRequest, :currentUser, :assumedRoles);");
|
||||||
|
query.setParameter("currentTask", shortenToMaxLength(currentTask, 96));
|
||||||
|
query.setParameter("currentRequest", shortenToMaxLength(currentRequest, 512)); // TODO.SPEC: length?
|
||||||
|
query.setParameter("currentUser", currentUser);
|
||||||
|
query.setParameter("assumedRoles", assumedRoles != null ? assumedRoles : "");
|
||||||
|
query.executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCurrentTask() {
|
public String getCurrentTask() {
|
||||||
return (String) em.createNativeQuery("select current_setting('hsadminng.currentTask');").getSingleResult();
|
return (String) em.createNativeQuery("select current_setting('hsadminng.currentTask');").getSingleResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(propagation = MANDATORY)
|
|
||||||
public void setCurrentUser(final String userName) {
|
|
||||||
em.createNativeQuery(
|
|
||||||
String.format(
|
|
||||||
"set local hsadminng.currentUser = '%s';",
|
|
||||||
userName
|
|
||||||
)
|
|
||||||
).executeUpdate();
|
|
||||||
assumeNoSpecialRole();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCurrentUser() {
|
public String getCurrentUser() {
|
||||||
return String.valueOf(em.createNativeQuery("select currentUser()").getSingleResult());
|
return String.valueOf(em.createNativeQuery("select currentUser()").getSingleResult());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(propagation = MANDATORY)
|
|
||||||
public void assumeRoles(final String roles) {
|
|
||||||
em.createNativeQuery(
|
|
||||||
String.format(
|
|
||||||
"set local hsadminng.assumedRoles = '%s';",
|
|
||||||
roles
|
|
||||||
)
|
|
||||||
).executeUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(propagation = MANDATORY)
|
|
||||||
public void assumeNoSpecialRole() {
|
|
||||||
em.createNativeQuery(
|
|
||||||
"set local hsadminng.assumedRoles = '';"
|
|
||||||
).executeUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] getAssumedRoles() {
|
public String[] getAssumedRoles() {
|
||||||
return (String[]) em.createNativeQuery("select assumedRoles()").getSingleResult();
|
return (String[]) em.createNativeQuery("select assumedRoles()").getSingleResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String shortenToMaxLength(final String task, final int maxLength) {
|
private static String getCallerMethodNameFromStack() {
|
||||||
return task.substring(0, Math.min(task.length(), maxLength));
|
final Optional<StackWalker.StackFrame> caller =
|
||||||
|
StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
|
||||||
|
.walk(frames -> frames
|
||||||
|
.skip(2)
|
||||||
|
.filter(c -> c.getDeclaringClass() != Context.class)
|
||||||
|
.filter(c -> c.getDeclaringClass()
|
||||||
|
.getPackageName()
|
||||||
|
.startsWith("net.hostsharing.hsadminng"))
|
||||||
|
.filter(c -> !c.getDeclaringClass().getName().contains("BySpringCGLIB$$"))
|
||||||
|
.findFirst());
|
||||||
|
return caller.map(
|
||||||
|
c -> c.getDeclaringClass().getSimpleName() + "." + c.getMethodName())
|
||||||
|
.orElse("unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toTask(final HttpServletRequest request) {
|
||||||
|
if (isRequestScopeAvailable()) {
|
||||||
|
return request.getMethod() + " " + request.getRequestURI();
|
||||||
|
} else {
|
||||||
|
return getCallerMethodNameFromStack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private String toCurl(final HttpServletRequest request) {
|
||||||
|
if (!isRequestScopeAvailable()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var curlCommand = "curl -0 -v";
|
||||||
|
|
||||||
|
// append method
|
||||||
|
curlCommand += " -X " + request.getMethod();
|
||||||
|
|
||||||
|
// append request url
|
||||||
|
curlCommand += " " + request.getRequestURI();
|
||||||
|
|
||||||
|
// append headers
|
||||||
|
final var headers = Collections.list(request.getHeaderNames()).stream()
|
||||||
|
.filter(not(HEADERS_TO_IGNORE::contains))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
for (String headerName : headers) {
|
||||||
|
final var headerValue = request.getHeader(headerName);
|
||||||
|
curlCommand += " \\" + System.lineSeparator() + String.format("-H '%s:%s'", headerName, headerValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// body
|
||||||
|
final String body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
|
||||||
|
if (!StringUtils.isEmpty(body)) {
|
||||||
|
curlCommand += " \\" + System.lineSeparator() + "--data-binary @- ";
|
||||||
|
curlCommand +=
|
||||||
|
"<< EOF" + System.lineSeparator() + System.lineSeparator() + body + System.lineSeparator() + "EOF";
|
||||||
|
}
|
||||||
|
|
||||||
|
return curlCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isRequestScopeAvailable() {
|
||||||
|
return RequestContextHolder.getRequestAttributes() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String shortenToMaxLength(final String raw, final int maxLength) {
|
||||||
|
if (raw == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (raw.length() <= maxLength) {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
return raw.substring(0, maxLength - 3) + "...";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
package net.hostsharing.hsadminng.context;
|
||||||
|
|
||||||
|
import javax.servlet.ReadListener;
|
||||||
|
import javax.servlet.ServletInputStream;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class HttpServletRequestBodyCache extends ServletInputStream {
|
||||||
|
|
||||||
|
private InputStream inputStream;
|
||||||
|
|
||||||
|
public HttpServletRequestBodyCache(byte[] body) {
|
||||||
|
this.inputStream = new ByteArrayInputStream(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
return inputStream.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int available() throws IOException {
|
||||||
|
return inputStream.available();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFinished() {
|
||||||
|
try {
|
||||||
|
return available() == 0;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReady() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReadListener(final ReadListener listener) {
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package net.hostsharing.hsadminng.context;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class HttpServletRequestBodyCachingFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(
|
||||||
|
final HttpServletRequest request,
|
||||||
|
final HttpServletResponse response,
|
||||||
|
final FilterChain filterChain)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
filterChain.doFilter(new HttpServletRequestWithCachedBody(request), response);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package net.hostsharing.hsadminng.context;
|
||||||
|
|
||||||
|
import org.springframework.util.StreamUtils;
|
||||||
|
|
||||||
|
import javax.servlet.ServletInputStream;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletRequestWrapper;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
public class HttpServletRequestWithCachedBody extends HttpServletRequestWrapper {
|
||||||
|
|
||||||
|
private byte[] cachedBody;
|
||||||
|
|
||||||
|
public HttpServletRequestWithCachedBody(HttpServletRequest request) throws IOException {
|
||||||
|
super(request);
|
||||||
|
final var requestInputStream = request.getInputStream();
|
||||||
|
this.cachedBody = StreamUtils.copyToByteArray(requestInputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServletInputStream getInputStream() throws IOException {
|
||||||
|
return new HttpServletRequestBodyCache(this.cachedBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BufferedReader getReader() throws IOException {
|
||||||
|
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.cachedBody);
|
||||||
|
return new BufferedReader(new InputStreamReader(byteArrayInputStream));
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,6 @@ package net.hostsharing.hsadminng.hs.hscustomer;
|
|||||||
import net.hostsharing.hsadminng.context.Context;
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
import net.hostsharing.hsadminng.generated.api.v1.api.CustomersApi;
|
import net.hostsharing.hsadminng.generated.api.v1.api.CustomersApi;
|
||||||
import net.hostsharing.hsadminng.generated.api.v1.model.CustomerResource;
|
import net.hostsharing.hsadminng.generated.api.v1.model.CustomerResource;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@ -33,7 +32,7 @@ public class CustomerController implements CustomersApi {
|
|||||||
String assumedRoles,
|
String assumedRoles,
|
||||||
String prefix
|
String prefix
|
||||||
) {
|
) {
|
||||||
context.register(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
final var result = customerRepository.findCustomerByOptionalPrefixLike(prefix);
|
final var result = customerRepository.findCustomerByOptionalPrefixLike(prefix);
|
||||||
|
|
||||||
@ -47,7 +46,7 @@ public class CustomerController implements CustomersApi {
|
|||||||
final String assumedRoles,
|
final String assumedRoles,
|
||||||
final CustomerResource customer) {
|
final CustomerResource customer) {
|
||||||
|
|
||||||
context.register(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
if (customer.getUuid() == null) {
|
if (customer.getUuid() == null) {
|
||||||
customer.setUuid(UUID.randomUUID());
|
customer.setUuid(UUID.randomUUID());
|
||||||
|
@ -5,7 +5,6 @@ import net.hostsharing.hsadminng.context.Context;
|
|||||||
import net.hostsharing.hsadminng.generated.api.v1.api.PackagesApi;
|
import net.hostsharing.hsadminng.generated.api.v1.api.PackagesApi;
|
||||||
import net.hostsharing.hsadminng.generated.api.v1.model.PackageResource;
|
import net.hostsharing.hsadminng.generated.api.v1.model.PackageResource;
|
||||||
import net.hostsharing.hsadminng.generated.api.v1.model.PackageUpdateResource;
|
import net.hostsharing.hsadminng.generated.api.v1.model.PackageUpdateResource;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@ -33,7 +32,7 @@ public class PackageController implements PackagesApi {
|
|||||||
String assumedRoles,
|
String assumedRoles,
|
||||||
String name
|
String name
|
||||||
) {
|
) {
|
||||||
context.register(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
final var result = packageRepository.findAllByOptionalNameLike(name);
|
final var result = packageRepository.findAllByOptionalNameLike(name);
|
||||||
return ResponseEntity.ok(mapList(result, PackageResource.class));
|
return ResponseEntity.ok(mapList(result, PackageResource.class));
|
||||||
@ -47,7 +46,7 @@ public class PackageController implements PackagesApi {
|
|||||||
final UUID packageUuid,
|
final UUID packageUuid,
|
||||||
final PackageUpdateResource body) {
|
final PackageUpdateResource body) {
|
||||||
|
|
||||||
context.register(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
final var current = packageRepository.findByUuid(packageUuid);
|
final var current = packageRepository.findByUuid(packageUuid);
|
||||||
OptionalFromJson.of(body.getDescription()).ifPresent(current::setDescription);
|
OptionalFromJson.of(body.getDescription()).ifPresent(current::setDescription);
|
||||||
|
@ -3,7 +3,6 @@ package net.hostsharing.hsadminng.rbac.rbacgrant;
|
|||||||
import net.hostsharing.hsadminng.context.Context;
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
import net.hostsharing.hsadminng.generated.api.v1.api.RbacgrantsApi;
|
import net.hostsharing.hsadminng.generated.api.v1.api.RbacgrantsApi;
|
||||||
import net.hostsharing.hsadminng.generated.api.v1.model.RbacGrantResource;
|
import net.hostsharing.hsadminng.generated.api.v1.model.RbacGrantResource;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@ -38,7 +37,7 @@ public class RbacGrantController implements RbacgrantsApi {
|
|||||||
final UUID grantedRoleUuid,
|
final UUID grantedRoleUuid,
|
||||||
final UUID granteeUserUuid) {
|
final UUID granteeUserUuid) {
|
||||||
|
|
||||||
context.register(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
final var id = new RbacGrantId(granteeUserUuid, grantedRoleUuid);
|
final var id = new RbacGrantId(granteeUserUuid, grantedRoleUuid);
|
||||||
final var result = rbacGrantRepository.findById(id);
|
final var result = rbacGrantRepository.findById(id);
|
||||||
@ -54,7 +53,7 @@ public class RbacGrantController implements RbacgrantsApi {
|
|||||||
final String currentUser,
|
final String currentUser,
|
||||||
final String assumedRoles) {
|
final String assumedRoles) {
|
||||||
|
|
||||||
context.register(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
return ResponseEntity.ok(mapList(rbacGrantRepository.findAll(), RbacGrantResource.class));
|
return ResponseEntity.ok(mapList(rbacGrantRepository.findAll(), RbacGrantResource.class));
|
||||||
}
|
}
|
||||||
@ -66,7 +65,7 @@ public class RbacGrantController implements RbacgrantsApi {
|
|||||||
final String assumedRoles,
|
final String assumedRoles,
|
||||||
final RbacGrantResource body) {
|
final RbacGrantResource body) {
|
||||||
|
|
||||||
context.register(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
final var granted = rbacGrantRepository.save(map(body, RbacGrantEntity.class));
|
final var granted = rbacGrantRepository.save(map(body, RbacGrantEntity.class));
|
||||||
em.flush();
|
em.flush();
|
||||||
@ -88,7 +87,7 @@ public class RbacGrantController implements RbacgrantsApi {
|
|||||||
final UUID grantedRoleUuid,
|
final UUID grantedRoleUuid,
|
||||||
final UUID granteeUserUuid) {
|
final UUID granteeUserUuid) {
|
||||||
|
|
||||||
context.register(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
rbacGrantRepository.deleteByRbacGrantId(new RbacGrantId(granteeUserUuid, grantedRoleUuid));
|
rbacGrantRepository.deleteByRbacGrantId(new RbacGrantId(granteeUserUuid, grantedRoleUuid));
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ public class RbacRoleController implements RbacrolesApi {
|
|||||||
final String currentUser,
|
final String currentUser,
|
||||||
final String assumedRoles) {
|
final String assumedRoles) {
|
||||||
|
|
||||||
context.register(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
return ResponseEntity.ok(mapList(rbacRoleRepository.findAll(), RbacRoleResource.class));
|
return ResponseEntity.ok(mapList(rbacRoleRepository.findAll(), RbacRoleResource.class));
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,12 @@ package net.hostsharing.hsadminng.rbac.rbacuser;
|
|||||||
|
|
||||||
import net.hostsharing.hsadminng.context.Context;
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
import net.hostsharing.hsadminng.generated.api.v1.api.RbacusersApi;
|
import net.hostsharing.hsadminng.generated.api.v1.api.RbacusersApi;
|
||||||
import net.hostsharing.hsadminng.generated.api.v1.model.RbacGrantResource;
|
|
||||||
import net.hostsharing.hsadminng.generated.api.v1.model.RbacUserPermissionResource;
|
import net.hostsharing.hsadminng.generated.api.v1.model.RbacUserPermissionResource;
|
||||||
import net.hostsharing.hsadminng.generated.api.v1.model.RbacUserResource;
|
import net.hostsharing.hsadminng.generated.api.v1.model.RbacUserResource;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantId;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -33,7 +30,7 @@ public class RbacUserController implements RbacusersApi {
|
|||||||
public ResponseEntity<RbacUserResource> createUser(
|
public ResponseEntity<RbacUserResource> createUser(
|
||||||
final RbacUserResource body
|
final RbacUserResource body
|
||||||
) {
|
) {
|
||||||
context.register(body.getName(), null);
|
context.define(body.getName());
|
||||||
|
|
||||||
if (body.getUuid() == null) {
|
if (body.getUuid() == null) {
|
||||||
body.setUuid(UUID.randomUUID());
|
body.setUuid(UUID.randomUUID());
|
||||||
@ -55,7 +52,7 @@ public class RbacUserController implements RbacusersApi {
|
|||||||
final String assumedRoles,
|
final String assumedRoles,
|
||||||
final UUID userUuid) {
|
final UUID userUuid) {
|
||||||
|
|
||||||
context.register(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
final var result = rbacUserRepository.findByUuid(userUuid);
|
final var result = rbacUserRepository.findByUuid(userUuid);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
@ -71,7 +68,7 @@ public class RbacUserController implements RbacusersApi {
|
|||||||
final String assumedRoles,
|
final String assumedRoles,
|
||||||
final String userName
|
final String userName
|
||||||
) {
|
) {
|
||||||
context.register(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
return ResponseEntity.ok(mapList(rbacUserRepository.findByOptionalNameLike(userName), RbacUserResource.class));
|
return ResponseEntity.ok(mapList(rbacUserRepository.findByOptionalNameLike(userName), RbacUserResource.class));
|
||||||
}
|
}
|
||||||
@ -83,8 +80,10 @@ public class RbacUserController implements RbacusersApi {
|
|||||||
final String assumedRoles,
|
final String assumedRoles,
|
||||||
final UUID userUuid
|
final UUID userUuid
|
||||||
) {
|
) {
|
||||||
context.register(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
return ResponseEntity.ok(mapList(rbacUserRepository.findPermissionsOfUserByUuid(userUuid), RbacUserPermissionResource.class));
|
return ResponseEntity.ok(mapList(
|
||||||
|
rbacUserRepository.findPermissionsOfUserByUuid(userUuid),
|
||||||
|
RbacUserPermissionResource.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,38 @@
|
|||||||
--liquibase formatted sql
|
--liquibase formatted sql
|
||||||
|
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
--changeset context-DEFINE:1 endDelimiter:--//
|
||||||
|
-- ----------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
Defines the transaction context.
|
||||||
|
*/
|
||||||
|
|
||||||
|
create or replace procedure defineContext(
|
||||||
|
currentTask varchar,
|
||||||
|
currentRequest varchar,
|
||||||
|
currentUser varchar,
|
||||||
|
assumedRoles varchar
|
||||||
|
)
|
||||||
|
language plpgsql as $$
|
||||||
|
begin
|
||||||
|
raise notice 'currentRequest: %', defineContext.currentRequest;
|
||||||
|
execute format('set local hsadminng.currentTask to %L', currentTask);
|
||||||
|
execute format('set local hsadminng.currentUser to %L', currentUser);
|
||||||
|
if length(assumedRoles) > 0 then
|
||||||
|
execute format('set local hsadminng.assumedRoles to %L', assumedRoles);
|
||||||
|
else
|
||||||
|
execute format('set local hsadminng.assumedRoles to %L', '');
|
||||||
|
end if;
|
||||||
|
end; $$;
|
||||||
|
--//
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset context-CURRENT-TASK:1 endDelimiter:--//
|
--changeset context-CURRENT-TASK:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
/*
|
/*
|
||||||
Returns the current tas as set by `hsadminng.currentTask`.
|
Returns the current task as set by `hsadminng.currentTask`.
|
||||||
Raises exception if not set.
|
Raises exception if not set.
|
||||||
*/
|
*/
|
||||||
create or replace function currentTask()
|
create or replace function currentTask()
|
||||||
@ -117,7 +145,7 @@ create or replace function findIdNameByObjectUuid(objectTable varchar, objectUui
|
|||||||
returns null on null input
|
returns null on null input
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
sql varchar;
|
sql varchar;
|
||||||
idName varchar;
|
idName varchar;
|
||||||
begin
|
begin
|
||||||
objectTable := pureIdentifier(objectTable);
|
objectTable := pureIdentifier(objectTable);
|
||||||
|
@ -4,8 +4,6 @@ import org.junit.jupiter.api.BeforeEach;
|
|||||||
import org.junit.jupiter.api.TestInfo;
|
import org.junit.jupiter.api.TestInfo;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
public class ContextBasedTest {
|
public class ContextBasedTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -18,18 +16,9 @@ public class ContextBasedTest {
|
|||||||
this.test = testInfo;
|
this.test = testInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove the class and check which task is recorded
|
||||||
protected void context(final String currentUser, final String assumedRoles) {
|
protected void context(final String currentUser, final String assumedRoles) {
|
||||||
context.setCurrentTask(test.getDisplayName());
|
context.define(test.getDisplayName(), null, currentUser, assumedRoles);
|
||||||
|
|
||||||
context.setCurrentUser(currentUser);
|
|
||||||
assertThat(context.getCurrentUser()).as("precondition").isEqualTo(currentUser);
|
|
||||||
|
|
||||||
if (assumedRoles != null) {
|
|
||||||
context.assumeRoles(assumedRoles);
|
|
||||||
assertThat(context.getAssumedRoles()).as("precondition").containsExactly(assumedRoles.split(";"));
|
|
||||||
// } else {
|
|
||||||
// context.assumeNoSpecialRole();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void context(final String currentUser) {
|
protected void context(final String currentUser) {
|
||||||
|
@ -20,7 +20,7 @@ class ContextIntegrationTests {
|
|||||||
@Test
|
@Test
|
||||||
void registerWithoutHttpServletRequestUsesCallStack() {
|
void registerWithoutHttpServletRequestUsesCallStack() {
|
||||||
|
|
||||||
context.register("current-user", null);
|
context.define("current-user", null);
|
||||||
|
|
||||||
final var currentTask = context.getCurrentTask();
|
final var currentTask = context.getCurrentTask();
|
||||||
assertThat(currentTask).isEqualTo("ContextIntegrationTests.registerWithoutHttpServletRequestUsesCallStack");
|
assertThat(currentTask).isEqualTo("ContextIntegrationTests.registerWithoutHttpServletRequestUsesCallStack");
|
||||||
@ -29,7 +29,7 @@ class ContextIntegrationTests {
|
|||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
void setCurrentUser() {
|
void setCurrentUser() {
|
||||||
context.setCurrentUser("mike@hostsharing.net");
|
context.define("mike@hostsharing.net");
|
||||||
|
|
||||||
final var currentUser = context.getCurrentUser();
|
final var currentUser = context.getCurrentUser();
|
||||||
assertThat(currentUser).isEqualTo("mike@hostsharing.net");
|
assertThat(currentUser).isEqualTo("mike@hostsharing.net");
|
||||||
@ -41,8 +41,7 @@ class ContextIntegrationTests {
|
|||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
void assumeRoles() {
|
void assumeRoles() {
|
||||||
context.setCurrentUser("mike@hostsharing.net");
|
context.define("mike@hostsharing.net", "customer#xxx.owner;customer#yyy.owner");
|
||||||
context.assumeRoles("customer#xxx.owner;customer#yyy.owner");
|
|
||||||
|
|
||||||
final var currentUser = context.getCurrentUser();
|
final var currentUser = context.getCurrentUser();
|
||||||
assertThat(currentUser).isEqualTo("mike@hostsharing.net");
|
assertThat(currentUser).isEqualTo("mike@hostsharing.net");
|
||||||
|
@ -1,15 +1,25 @@
|
|||||||
package net.hostsharing.hsadminng.context;
|
package net.hostsharing.hsadminng.context;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import org.springframework.web.context.request.RequestAttributes;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.*;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
@ -22,16 +32,156 @@ class ContextUnitTest {
|
|||||||
@Mock
|
@Mock
|
||||||
Query nativeQuery;
|
Query nativeQuery;
|
||||||
|
|
||||||
@InjectMocks
|
@Nested
|
||||||
Context context;
|
class WithoutHttpRequest {
|
||||||
|
|
||||||
@Test
|
@Mock
|
||||||
void registerWithoutHttpServletRequestUsesCallStack() {
|
EntityManager em;
|
||||||
given(em.createNativeQuery(any())).willReturn(nativeQuery);
|
|
||||||
|
|
||||||
context.register("current-user", null);
|
@Mock
|
||||||
|
Query nativeQuery;
|
||||||
|
|
||||||
verify(em).createNativeQuery(
|
@InjectMocks
|
||||||
"set local hsadminng.currentTask = 'ContextUnitTest.registerWithoutHttpServletRequestUsesCallStack';");
|
Context context;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
RequestContextHolder.setRequestAttributes(null);
|
||||||
|
given(em.createNativeQuery(any())).willReturn(nativeQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registerWithoutHttpServletRequestUsesCallStackForTask() {
|
||||||
|
given(em.createNativeQuery(any())).willReturn(nativeQuery);
|
||||||
|
|
||||||
|
context.define("current-user");
|
||||||
|
|
||||||
|
verify(em).createNativeQuery("call defineContext(:currentTask, :currentRequest, :currentUser, :assumedRoles);");
|
||||||
|
verify(nativeQuery).setParameter(
|
||||||
|
"currentTask",
|
||||||
|
"WithoutHttpRequest.registerWithoutHttpServletRequestUsesCallStackForTask");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registerWithoutHttpServletRequestUsesEmptyStringForRequest() {
|
||||||
|
given(em.createNativeQuery(any())).willReturn(nativeQuery);
|
||||||
|
|
||||||
|
context.define("current-user");
|
||||||
|
|
||||||
|
verify(em).createNativeQuery("call defineContext(:currentTask, :currentRequest, :currentUser, :assumedRoles);");
|
||||||
|
verify(nativeQuery).setParameter("currentRequest", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class WithHttpRequest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
EntityManager em;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
Query nativeQuery;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
HttpServletRequest request;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
RequestAttributes requestAttributes;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
BufferedReader requestBodyReader;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
Stream<String> requestBodyLines;
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
Context context;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
RequestContextHolder.setRequestAttributes(requestAttributes);
|
||||||
|
given(em.createNativeQuery(any())).willReturn(nativeQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registerWithHttpServletRequestUsesRequest() throws IOException {
|
||||||
|
givenRequest("POST", "http://localhost:9999/api/endpoint", Map.ofEntries(
|
||||||
|
Map.entry("current-user", "given-user"),
|
||||||
|
Map.entry("content-type", "application/json"),
|
||||||
|
Map.entry("user-agent", "given-user-agent")),
|
||||||
|
"{}");
|
||||||
|
|
||||||
|
context.define("current-user");
|
||||||
|
|
||||||
|
verify(em).createNativeQuery("call defineContext(:currentTask, :currentRequest, :currentUser, :assumedRoles);");
|
||||||
|
verify(nativeQuery).setParameter("currentTask", "POST http://localhost:9999/api/endpoint");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registerWithHttpServletRequestForwardsRequestAsCurl() throws IOException {
|
||||||
|
givenRequest("POST", "http://localhost:9999/api/endpoint", Map.ofEntries(
|
||||||
|
Map.entry("current-user", "given-user"),
|
||||||
|
Map.entry("content-type", "application/json"),
|
||||||
|
Map.entry("user-agent", "given-user-agent")),
|
||||||
|
"{}");
|
||||||
|
|
||||||
|
context.define("current-user");
|
||||||
|
|
||||||
|
verify(em).createNativeQuery("call defineContext(:currentTask, :currentRequest, :currentUser, :assumedRoles);");
|
||||||
|
verify(nativeQuery).setParameter("currentRequest", """
|
||||||
|
curl -0 -v -X POST http://localhost:9999/api/endpoint \\
|
||||||
|
-H 'current-user:given-user' \\
|
||||||
|
-H 'content-type:application/json' \\
|
||||||
|
--data-binary @- << EOF
|
||||||
|
|
||||||
|
{}
|
||||||
|
EOF
|
||||||
|
""".trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shortensCurrentTaskTo96Chars() throws IOException {
|
||||||
|
givenRequest("GET", "http://localhost:9999/api/endpoint/" + "0123456789".repeat(10),
|
||||||
|
Map.ofEntries(
|
||||||
|
Map.entry("current-user", "given-user"),
|
||||||
|
Map.entry("content-type", "application/json"),
|
||||||
|
Map.entry("user-agent", "given-user-agent")),
|
||||||
|
"{}");
|
||||||
|
|
||||||
|
context.define("current-user");
|
||||||
|
|
||||||
|
verify(em).createNativeQuery("call defineContext(:currentTask, :currentRequest, :currentUser, :assumedRoles);");
|
||||||
|
verify(nativeQuery).setParameter(eq("currentTask"), argThat((String t) -> t.length() == 96));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shortensCurrentRequestTo512Chars() throws IOException {
|
||||||
|
givenRequest("GET", "http://localhost:9999/api/endpoint",
|
||||||
|
Map.ofEntries(
|
||||||
|
Map.entry("current-user", "given-user"),
|
||||||
|
Map.entry("content-type", "application/json"),
|
||||||
|
Map.entry("user-agent", "given-user-agent")),
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"dummy": "%s"
|
||||||
|
}
|
||||||
|
""".formatted("0123456789".repeat(60)));
|
||||||
|
|
||||||
|
context.define("current-user");
|
||||||
|
|
||||||
|
verify(em).createNativeQuery("call defineContext(:currentTask, :currentRequest, :currentUser, :assumedRoles);");
|
||||||
|
verify(nativeQuery).setParameter(eq("currentRequest"), argThat((String t) -> t.length() == 512));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void givenRequest(final String method, final String url, final Map<String, String> headers, final String body)
|
||||||
|
throws IOException {
|
||||||
|
given(request.getMethod()).willReturn(method);
|
||||||
|
given(request.getRequestURI()).willReturn(url);
|
||||||
|
given(request.getHeaderNames()).willReturn(Collections.enumeration(headers.keySet()));
|
||||||
|
given(request.getHeader(anyString())).willAnswer(invocation -> headers.get(invocation.getArgument(0).toString()));
|
||||||
|
given(request.getReader()).willReturn(requestBodyReader);
|
||||||
|
given(requestBodyReader.lines()).willReturn(requestBodyLines);
|
||||||
|
given(requestBodyLines.collect(any())).willReturn(body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,111 @@
|
|||||||
|
package net.hostsharing.hsadminng.context;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
|
||||||
|
class HttpServletRequestBodyCacheUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void readsTheStream() {
|
||||||
|
// given
|
||||||
|
try (final var givenBodyCache = new HttpServletRequestBodyCache("Hallo".getBytes())) {
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var actual = new String(givenBodyCache.readAllBytes());
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(actual).isEqualTo("Hallo");
|
||||||
|
|
||||||
|
} catch (final IOException exc) {
|
||||||
|
throw new AssertionError("unexpected IO exception", exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isReadyReturnsTrue() {
|
||||||
|
// given
|
||||||
|
try (final var givenBodyCache = new HttpServletRequestBodyCache("Hallo".getBytes())) {
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var actual = givenBodyCache.isReady();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(actual).isTrue();
|
||||||
|
|
||||||
|
} catch (final IOException exc) {
|
||||||
|
throw new AssertionError("unexpected IO exception", exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isFinishedReturnsTrueWhenNotRead() {
|
||||||
|
// given
|
||||||
|
try (final var givenBodyCache = new HttpServletRequestBodyCache("Hallo".getBytes())) {
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var actual = givenBodyCache.isFinished();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(actual).isFalse();
|
||||||
|
|
||||||
|
} catch (final IOException exc) {
|
||||||
|
throw new AssertionError("unexpected IO exception", exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isFinishedReturnsTrueWhenRead() {
|
||||||
|
// given
|
||||||
|
try (final var givenBodyCache = new HttpServletRequestBodyCache("Hallo".getBytes())) {
|
||||||
|
givenBodyCache.readAllBytes();
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var actual = givenBodyCache.isFinished();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(actual).isTrue();
|
||||||
|
|
||||||
|
} catch (final IOException exc) {
|
||||||
|
throw new AssertionError("unexpected IO exception", exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isFinishedReturnsTrueOnException() {
|
||||||
|
// given
|
||||||
|
try (final var givenBodyCache = spy(new HttpServletRequestBodyCache("".getBytes()))) {
|
||||||
|
given(givenBodyCache.available()).willThrow(new IOException("fake exception"));
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var actual = givenBodyCache.isFinished();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(actual).isTrue();
|
||||||
|
|
||||||
|
} catch (final IOException exc) {
|
||||||
|
throw new AssertionError("unexpected IO exception", exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setReadListenerThrowsNotImplementedException() {
|
||||||
|
// given
|
||||||
|
try (final var givenBodyCache = new HttpServletRequestBodyCache("Hallo".getBytes())) {
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var exception = assertThrows(RuntimeException.class, () -> givenBodyCache.setReadListener(null));
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(exception.getMessage()).isEqualTo("Not implemented");
|
||||||
|
|
||||||
|
} catch (final IOException exc) {
|
||||||
|
throw new AssertionError("unexpected IO exception", exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -57,7 +57,7 @@ class CustomerControllerAcceptanceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void hostsharingAdmin_withoutAssumedRoles_canViewMatchingCustomers_ifCriteriaGiven() throws Exception {
|
void hostsharingAdmin_withoutAssumedRoles_canViewMatchingCustomers_ifCriteriaGiven() {
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
.header("current-user", "mike@hostsharing.net")
|
.header("current-user", "mike@hostsharing.net")
|
||||||
@ -73,7 +73,7 @@ class CustomerControllerAcceptanceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void hostsharingAdmin_withoutAssumedCustomerAdminRole_canOnlyViewOwnCustomer() throws Exception {
|
void hostsharingAdmin_withoutAssumedCustomerAdminRole_canOnlyViewOwnCustomer() {
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
.header("current-user", "mike@hostsharing.net")
|
.header("current-user", "mike@hostsharing.net")
|
||||||
@ -90,14 +90,14 @@ class CustomerControllerAcceptanceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void customerAdmin_withoutAssumedRole_canOnlyViewOwnCustomer() throws Exception {
|
void customerAdmin_withoutAssumedRole_canOnlyViewOwnCustomer() {
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
.header("current-user", "customer-admin@yyy.example.com")
|
.header("current-user", "customer-admin@yyy.example.com")
|
||||||
.port(port)
|
.port(port)
|
||||||
.when()
|
.when()
|
||||||
.get("http://localhost/api/customers")
|
.get("http://localhost/api/customers")
|
||||||
.then().assertThat()
|
.then().assertThat()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.contentType("application/json")
|
.contentType("application/json")
|
||||||
.body("[0].prefix", is("yyy"))
|
.body("[0].prefix", is("yyy"))
|
||||||
@ -107,10 +107,10 @@ class CustomerControllerAcceptanceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
class CreateCustomer {
|
class AddCustomer {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void hostsharingAdmin_withoutAssumedRole_canCreateCustomer() throws Exception {
|
void hostsharingAdmin_withoutAssumedRole_canAddCustomer() {
|
||||||
|
|
||||||
final var location = RestAssured // @formatter:off
|
final var location = RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
@ -136,13 +136,13 @@ class CustomerControllerAcceptanceTest {
|
|||||||
// finally, the new customer can be viewed by its own admin
|
// finally, the new customer can be viewed by its own admin
|
||||||
final var newUserUuid = UUID.fromString(
|
final var newUserUuid = UUID.fromString(
|
||||||
location.substring(location.lastIndexOf('/') + 1));
|
location.substring(location.lastIndexOf('/') + 1));
|
||||||
context.setCurrentUser("customer-admin@ttt.example.com");
|
context.define("customer-admin@ttt.example.com");
|
||||||
assertThat(customerRepository.findByUuid(newUserUuid))
|
assertThat(customerRepository.findByUuid(newUserUuid))
|
||||||
.hasValueSatisfying(c -> assertThat(c.getPrefix()).isEqualTo("ttt"));
|
.hasValueSatisfying(c -> assertThat(c.getPrefix()).isEqualTo("ttt"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void hostsharingAdmin_withoutAssumedRole_canCreateCustomerWithGivenUuid() {
|
void hostsharingAdmin_withoutAssumedRole_canAddCustomerWithGivenUuid() {
|
||||||
|
|
||||||
final var givenUuid = UUID.randomUUID();
|
final var givenUuid = UUID.randomUUID();
|
||||||
|
|
||||||
@ -171,7 +171,7 @@ class CustomerControllerAcceptanceTest {
|
|||||||
// finally, the new customer can be viewed by its own admin
|
// finally, the new customer can be viewed by its own admin
|
||||||
final var newUserUuid = UUID.fromString(
|
final var newUserUuid = UUID.fromString(
|
||||||
location.substring(location.lastIndexOf('/') + 1));
|
location.substring(location.lastIndexOf('/') + 1));
|
||||||
context.setCurrentUser("customer-admin@vvv.example.com");
|
context.define("customer-admin@vvv.example.com");
|
||||||
assertThat(customerRepository.findByUuid(newUserUuid))
|
assertThat(customerRepository.findByUuid(newUserUuid))
|
||||||
.hasValueSatisfying(c -> {
|
.hasValueSatisfying(c -> {
|
||||||
assertThat(c.getPrefix()).isEqualTo("vvv");
|
assertThat(c.getPrefix()).isEqualTo("vvv");
|
||||||
@ -180,7 +180,7 @@ class CustomerControllerAcceptanceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void hostsharingAdmin_withAssumedCustomerAdminRole_canNotCreateCustomer() throws Exception {
|
void hostsharingAdmin_withAssumedCustomerAdminRole_canNotAddCustomer() {
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
@ -205,12 +205,12 @@ class CustomerControllerAcceptanceTest {
|
|||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
// finally, the new customer was not created
|
// finally, the new customer was not created
|
||||||
context.setCurrentUser("sven@hostsharing.net");
|
context.define("sven@hostsharing.net");
|
||||||
assertThat(customerRepository.findCustomerByOptionalPrefixLike("uuu")).hasSize(0);
|
assertThat(customerRepository.findCustomerByOptionalPrefixLike("uuu")).hasSize(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void customerAdmin_withoutAssumedRole_canNotCreateCustomer() throws Exception {
|
void customerAdmin_withoutAssumedRole_canNotAddCustomer() {
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
@ -234,7 +234,7 @@ class CustomerControllerAcceptanceTest {
|
|||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
// finally, the new customer was not created
|
// finally, the new customer was not created
|
||||||
context.setCurrentUser("sven@hostsharing.net");
|
context.define("sven@hostsharing.net");
|
||||||
assertThat(customerRepository.findCustomerByOptionalPrefixLike("uuu")).hasSize(0);
|
assertThat(customerRepository.findCustomerByOptionalPrefixLike("uuu")).hasSize(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ import static org.hamcrest.Matchers.equalTo;
|
|||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
@SpringBootTest(
|
@SpringBootTest(
|
||||||
webEnvironment = WebEnvironment.RANDOM_PORT,
|
webEnvironment = WebEnvironment.RANDOM_PORT,
|
||||||
classes = HsadminNgApplication.class
|
classes = HsadminNgApplication.class
|
||||||
)
|
)
|
||||||
@Transactional
|
@Transactional
|
||||||
class PackageControllerAcceptanceTest {
|
class PackageControllerAcceptanceTest {
|
||||||
@ -86,7 +86,7 @@ class PackageControllerAcceptanceTest {
|
|||||||
void withDescriptionUpdatesDescription() {
|
void withDescriptionUpdatesDescription() {
|
||||||
|
|
||||||
assumeThat(getDescriptionOfPackage("xxx00"))
|
assumeThat(getDescriptionOfPackage("xxx00"))
|
||||||
.isEqualTo("Here can add your own description of package xxx00.");
|
.isEqualTo("Here can add your own description of package xxx00.");
|
||||||
|
|
||||||
final var randomDescription = RandomStringUtils.randomAlphanumeric(80);
|
final var randomDescription = RandomStringUtils.randomAlphanumeric(80);
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ class PackageControllerAcceptanceTest {
|
|||||||
void withNullDescriptionUpdatesDescriptionToNull() {
|
void withNullDescriptionUpdatesDescriptionToNull() {
|
||||||
|
|
||||||
assumeThat(getDescriptionOfPackage("xxx01"))
|
assumeThat(getDescriptionOfPackage("xxx01"))
|
||||||
.isEqualTo("Here can add your own description of package xxx01.");
|
.isEqualTo("Here can add your own description of package xxx01.");
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
RestAssured
|
RestAssured
|
||||||
@ -147,7 +147,7 @@ class PackageControllerAcceptanceTest {
|
|||||||
void withoutDescriptionDoesNothing() {
|
void withoutDescriptionDoesNothing() {
|
||||||
|
|
||||||
assumeThat(getDescriptionOfPackage("xxx02"))
|
assumeThat(getDescriptionOfPackage("xxx02"))
|
||||||
.isEqualTo("Here can add your own description of package xxx02.");
|
.isEqualTo("Here can add your own description of package xxx02.");
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
RestAssured
|
RestAssured
|
||||||
@ -185,8 +185,7 @@ class PackageControllerAcceptanceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String getDescriptionOfPackage(final String packageName) {
|
String getDescriptionOfPackage(final String packageName) {
|
||||||
context.setCurrentUser("mike@hostsharing.net");
|
context.define("mike@hostsharing.net","customer#xxx.admin");
|
||||||
context.assumeRoles("customer#xxx.admin");
|
|
||||||
return packageRepository.findAllByOptionalNameLike(packageName).get(0).getDescription();
|
return packageRepository.findAllByOptionalNameLike(packageName).get(0).getDescription();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ class PackageRepositoryIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void hostsharingAdmin_withoutAssumedRole_canNotViewAnyPackages_becauseThoseGrantsAreNotassumedd() {
|
public void hostsharingAdmin_withoutAssumedRole_canNotViewAnyPackages_becauseThoseGrantsAreNotassumedd() {
|
||||||
// given
|
// given
|
||||||
currentUser("mike@hostsharing.net");
|
context.define("mike@hostsharing.net");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = packageRepository.findAllByOptionalNameLike(null);
|
final var result = packageRepository.findAllByOptionalNameLike(null);
|
||||||
@ -54,8 +54,7 @@ class PackageRepositoryIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void hostsharingAdmin_withAssumedHostsharingAdminRole__canNotViewAnyPackages_becauseThoseGrantsAreNotassumedd() {
|
public void hostsharingAdmin_withAssumedHostsharingAdminRole__canNotViewAnyPackages_becauseThoseGrantsAreNotassumedd() {
|
||||||
given:
|
given:
|
||||||
currentUser("mike@hostsharing.net");
|
context.define("mike@hostsharing.net", "global#hostsharing.admin");
|
||||||
assumedRoles("global#hostsharing.admin");
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = packageRepository.findAllByOptionalNameLike(null);
|
final var result = packageRepository.findAllByOptionalNameLike(null);
|
||||||
@ -67,7 +66,7 @@ class PackageRepositoryIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void customerAdmin_withoutAssumedRole_canViewOnlyItsOwnPackages() {
|
public void customerAdmin_withoutAssumedRole_canViewOnlyItsOwnPackages() {
|
||||||
// given:
|
// given:
|
||||||
currentUser("customer-admin@xxx.example.com");
|
context.define("customer-admin@xxx.example.com");
|
||||||
|
|
||||||
// when:
|
// when:
|
||||||
final var result = packageRepository.findAllByOptionalNameLike(null);
|
final var result = packageRepository.findAllByOptionalNameLike(null);
|
||||||
@ -78,8 +77,7 @@ class PackageRepositoryIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void customerAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyItsOwnPackages() {
|
public void customerAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyItsOwnPackages() {
|
||||||
currentUser("customer-admin@xxx.example.com");
|
context.define("customer-admin@xxx.example.com", "package#xxx00.admin");
|
||||||
assumedRoles("package#xxx00.admin");
|
|
||||||
|
|
||||||
final var result = packageRepository.findAllByOptionalNameLike(null);
|
final var result = packageRepository.findAllByOptionalNameLike(null);
|
||||||
|
|
||||||
@ -89,8 +87,7 @@ class PackageRepositoryIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void customerAdmin_withAssumedAlienPackageAdminRole_cannotViewAnyPackages() {
|
public void customerAdmin_withAssumedAlienPackageAdminRole_cannotViewAnyPackages() {
|
||||||
// given:
|
// given:
|
||||||
currentUser("customer-admin@xxx.example.com");
|
context.define("customer-admin@xxx.example.com", "package#yyy00.admin");
|
||||||
assumedRoles("package#yyy00.admin");
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = attempt(
|
final var result = attempt(
|
||||||
@ -105,7 +102,7 @@ class PackageRepositoryIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void unknownUser_withoutAssumedRole_cannotViewAnyPackages() {
|
void unknownUser_withoutAssumedRole_cannotViewAnyPackages() {
|
||||||
currentUser("unknown@example.org");
|
context.define("unknown@example.org");
|
||||||
|
|
||||||
final var result = attempt(
|
final var result = attempt(
|
||||||
em,
|
em,
|
||||||
@ -119,8 +116,7 @@ class PackageRepositoryIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
void unknownUser_withAssumedCustomerRole_cannotViewAnyPackages() {
|
void unknownUser_withAssumedCustomerRole_cannotViewAnyPackages() {
|
||||||
currentUser("unknown@example.org");
|
context.define("unknown@example.org", "customer#xxx.admin");
|
||||||
assumedRoles("customer#xxx.admin");
|
|
||||||
|
|
||||||
final var result = attempt(
|
final var result = attempt(
|
||||||
em,
|
em,
|
||||||
@ -172,18 +168,7 @@ class PackageRepositoryIntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void hostsharingAdminWithAssumedRole(final String assumedRoles) {
|
private void hostsharingAdminWithAssumedRole(final String assumedRoles) {
|
||||||
currentUser("mike@hostsharing.net");
|
context.define("mike@hostsharing.net", assumedRoles);
|
||||||
assumedRoles(assumedRoles);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 noPackagesAreReturned(final List<PackageEntity> actualResult) {
|
void noPackagesAreReturned(final List<PackageEntity> actualResult) {
|
||||||
|
@ -27,13 +27,14 @@ class RbacRoleRepositoryIntegrationTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
RbacRoleRepository rbacRoleRepository;
|
RbacRoleRepository rbacRoleRepository;
|
||||||
|
|
||||||
@Autowired EntityManager em;
|
@Autowired
|
||||||
|
EntityManager em;
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
class FindAllRbacRoles {
|
class FindAllRbacRoles {
|
||||||
|
|
||||||
private static final String[] ALL_TEST_DATA_ROLES = Array.of(
|
private static final String[] ALL_TEST_DATA_ROLES = Array.of(
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
"global#hostsharing.admin",
|
"global#hostsharing.admin",
|
||||||
"customer#xxx.admin", "customer#xxx.owner", "customer#xxx.tenant",
|
"customer#xxx.admin", "customer#xxx.owner", "customer#xxx.tenant",
|
||||||
"package#xxx00.admin", "package#xxx00.owner", "package#xxx00.tenant",
|
"package#xxx00.admin", "package#xxx00.owner", "package#xxx00.tenant",
|
||||||
@ -53,7 +54,7 @@ class RbacRoleRepositoryIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void hostsharingAdmin_withoutAssumedRole_canViewAllRbacRoles() {
|
public void hostsharingAdmin_withoutAssumedRole_canViewAllRbacRoles() {
|
||||||
// given
|
// given
|
||||||
currentUser("mike@hostsharing.net");
|
context.define("mike@hostsharing.net");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = rbacRoleRepository.findAll();
|
final var result = rbacRoleRepository.findAll();
|
||||||
@ -65,8 +66,7 @@ class RbacRoleRepositoryIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void hostsharingAdmin_withAssumedHostsharingAdminRole_canViewAllRbacRoles() {
|
public void hostsharingAdmin_withAssumedHostsharingAdminRole_canViewAllRbacRoles() {
|
||||||
given:
|
given:
|
||||||
currentUser("mike@hostsharing.net");
|
context.define("mike@hostsharing.net", "global#hostsharing.admin");
|
||||||
assumedRoles("global#hostsharing.admin");
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = rbacRoleRepository.findAll();
|
final var result = rbacRoleRepository.findAll();
|
||||||
@ -78,15 +78,15 @@ class RbacRoleRepositoryIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void customerAdmin_withoutAssumedRole_canViewOnlyItsOwnRbacRole() {
|
public void customerAdmin_withoutAssumedRole_canViewOnlyItsOwnRbacRole() {
|
||||||
// given:
|
// given:
|
||||||
currentUser("customer-admin@xxx.example.com");
|
context.define("customer-admin@xxx.example.com");
|
||||||
|
|
||||||
// when:
|
// when:
|
||||||
final var result = rbacRoleRepository.findAll();
|
final var result = rbacRoleRepository.findAll();
|
||||||
|
|
||||||
// then:
|
// then:
|
||||||
allTheseRbacRolesAreReturned(
|
allTheseRbacRolesAreReturned(
|
||||||
result,
|
result,
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
"customer#xxx.admin",
|
"customer#xxx.admin",
|
||||||
"customer#xxx.tenant",
|
"customer#xxx.tenant",
|
||||||
"package#xxx00.admin",
|
"package#xxx00.admin",
|
||||||
@ -104,8 +104,8 @@ class RbacRoleRepositoryIntegrationTest {
|
|||||||
// @formatter:on
|
// @formatter:on
|
||||||
);
|
);
|
||||||
noneOfTheseRbacRolesIsReturned(
|
noneOfTheseRbacRolesIsReturned(
|
||||||
result,
|
result,
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
"global#hostsharing.admin",
|
"global#hostsharing.admin",
|
||||||
"customer#xxx.owner",
|
"customer#xxx.owner",
|
||||||
"package#yyy00.admin",
|
"package#yyy00.admin",
|
||||||
@ -117,64 +117,61 @@ class RbacRoleRepositoryIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void customerAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyItsOwnRbacRole() {
|
public void customerAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyItsOwnRbacRole() {
|
||||||
currentUser("customer-admin@xxx.example.com");
|
context.define("customer-admin@xxx.example.com", "package#xxx00.admin");
|
||||||
assumedRoles("package#xxx00.admin");
|
|
||||||
|
|
||||||
final var result = rbacRoleRepository.findAll();
|
final var result = rbacRoleRepository.findAll();
|
||||||
|
|
||||||
exactlyTheseRbacRolesAreReturned(
|
exactlyTheseRbacRolesAreReturned(
|
||||||
result,
|
result,
|
||||||
"customer#xxx.tenant",
|
"customer#xxx.tenant",
|
||||||
"package#xxx00.admin",
|
"package#xxx00.admin",
|
||||||
"package#xxx00.tenant",
|
"package#xxx00.tenant",
|
||||||
"unixuser#xxx00-aaaa.admin",
|
"unixuser#xxx00-aaaa.admin",
|
||||||
"unixuser#xxx00-aaaa.owner",
|
"unixuser#xxx00-aaaa.owner",
|
||||||
"unixuser#xxx00-aaab.admin",
|
"unixuser#xxx00-aaab.admin",
|
||||||
"unixuser#xxx00-aaab.owner");
|
"unixuser#xxx00-aaab.owner");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void customerAdmin_withAssumedAlienPackageAdminRole_cannotViewAnyRbacRole() {
|
public void customerAdmin_withAssumedAlienPackageAdminRole_cannotViewAnyRbacRole() {
|
||||||
// given:
|
// given:
|
||||||
currentUser("customer-admin@xxx.example.com");
|
context.define("customer-admin@xxx.example.com", "package#yyy00.admin");
|
||||||
assumedRoles("package#yyy00.admin");
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = attempt(
|
final var result = attempt(
|
||||||
em,
|
em,
|
||||||
() -> rbacRoleRepository.findAll());
|
() -> rbacRoleRepository.findAll());
|
||||||
|
|
||||||
// then
|
// then
|
||||||
result.assertExceptionWithRootCauseMessage(
|
result.assertExceptionWithRootCauseMessage(
|
||||||
JpaSystemException.class,
|
JpaSystemException.class,
|
||||||
"[403] user customer-admin@xxx.example.com", "has no permission to assume role package#yyy00#admin");
|
"[403] user customer-admin@xxx.example.com", "has no permission to assume role package#yyy00#admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void unknownUser_withoutAssumedRole_cannotViewAnyRbacRoles() {
|
void unknownUser_withoutAssumedRole_cannotViewAnyRbacRoles() {
|
||||||
currentUser("unknown@example.org");
|
context.define("unknown@example.org");
|
||||||
|
|
||||||
final var result = attempt(
|
final var result = attempt(
|
||||||
em,
|
em,
|
||||||
() -> rbacRoleRepository.findAll());
|
() -> rbacRoleRepository.findAll());
|
||||||
|
|
||||||
result.assertExceptionWithRootCauseMessage(
|
result.assertExceptionWithRootCauseMessage(
|
||||||
JpaSystemException.class,
|
JpaSystemException.class,
|
||||||
"hsadminng.currentUser defined as unknown@example.org, but does not exists");
|
"hsadminng.currentUser defined as unknown@example.org, but does not exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void unknownUser_withAssumedRbacRoleRole_cannotViewAnyRbacRoles() {
|
void unknownUser_withAssumedRbacRoleRole_cannotViewAnyRbacRoles() {
|
||||||
currentUser("unknown@example.org");
|
context.define("unknown@example.org", "RbacRole#xxx.admin");
|
||||||
assumedRoles("RbacRole#xxx.admin");
|
|
||||||
|
|
||||||
final var result = attempt(
|
final var result = attempt(
|
||||||
em,
|
em,
|
||||||
() -> rbacRoleRepository.findAll());
|
() -> rbacRoleRepository.findAll());
|
||||||
|
|
||||||
result.assertExceptionWithRootCauseMessage(
|
result.assertExceptionWithRootCauseMessage(
|
||||||
JpaSystemException.class,
|
JpaSystemException.class,
|
||||||
"hsadminng.currentUser defined as unknown@example.org, but does not exists");
|
"hsadminng.currentUser defined as unknown@example.org, but does not exists");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +180,7 @@ class RbacRoleRepositoryIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void customerAdmin_withoutAssumedRole_canFindItsOwnRolesByName() {
|
void customerAdmin_withoutAssumedRole_canFindItsOwnRolesByName() {
|
||||||
currentUser("customer-admin@xxx.example.com");
|
context.define("customer-admin@xxx.example.com");
|
||||||
|
|
||||||
final var result = rbacRoleRepository.findByRoleName("customer#xxx.admin");
|
final var result = rbacRoleRepository.findByRoleName("customer#xxx.admin");
|
||||||
|
|
||||||
@ -195,7 +192,7 @@ class RbacRoleRepositoryIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void customerAdmin_withoutAssumedRole_canNotFindAlienRolesByName() {
|
void customerAdmin_withoutAssumedRole_canNotFindAlienRolesByName() {
|
||||||
currentUser("customer-admin@xxx.example.com");
|
context.define("customer-admin@xxx.example.com");
|
||||||
|
|
||||||
final var result = rbacRoleRepository.findByRoleName("customer#bbb.admin");
|
final var result = rbacRoleRepository.findByRoleName("customer#bbb.admin");
|
||||||
|
|
||||||
@ -203,32 +200,22 @@ class RbacRoleRepositoryIntegrationTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 List<RbacRoleEntity> actualResult, final String... expectedRoleNames) {
|
void exactlyTheseRbacRolesAreReturned(final List<RbacRoleEntity> actualResult, final String... expectedRoleNames) {
|
||||||
assertThat(actualResult)
|
assertThat(actualResult)
|
||||||
.extracting(RbacRoleEntity::getRoleName)
|
.extracting(RbacRoleEntity::getRoleName)
|
||||||
.containsExactlyInAnyOrder(expectedRoleNames);
|
.containsExactlyInAnyOrder(expectedRoleNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
void allTheseRbacRolesAreReturned(final List<RbacRoleEntity> actualResult, final String... expectedRoleNames) {
|
void allTheseRbacRolesAreReturned(final List<RbacRoleEntity> actualResult, final String... expectedRoleNames) {
|
||||||
assertThat(actualResult)
|
assertThat(actualResult)
|
||||||
.extracting(RbacRoleEntity::getRoleName)
|
.extracting(RbacRoleEntity::getRoleName)
|
||||||
.contains(expectedRoleNames);
|
.contains(expectedRoleNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
void noneOfTheseRbacRolesIsReturned(final List<RbacRoleEntity> actualResult, final String... unexpectedRoleNames) {
|
void noneOfTheseRbacRolesIsReturned(final List<RbacRoleEntity> actualResult, final String... unexpectedRoleNames) {
|
||||||
assertThat(actualResult)
|
assertThat(actualResult)
|
||||||
.extracting(RbacRoleEntity::getRoleName)
|
.extracting(RbacRoleEntity::getRoleName)
|
||||||
.doesNotContain(unexpectedRoleNames);
|
.doesNotContain(unexpectedRoleNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ class RbacUserControllerAcceptanceTest {
|
|||||||
// finally, the user can view its own record
|
// finally, the user can view its own record
|
||||||
final var newUserUuid = UUID.fromString(
|
final var newUserUuid = UUID.fromString(
|
||||||
location.substring(location.lastIndexOf('/') + 1));
|
location.substring(location.lastIndexOf('/') + 1));
|
||||||
context.setCurrentUser("new-user@example.com");
|
context.define("new-user@example.com");
|
||||||
assertThat(rbacUserRepository.findByUuid(newUserUuid))
|
assertThat(rbacUserRepository.findByUuid(newUserUuid))
|
||||||
.extracting(RbacUserEntity::getName).isEqualTo("new-user@example.com");
|
.extracting(RbacUserEntity::getName).isEqualTo("new-user@example.com");
|
||||||
}
|
}
|
||||||
@ -399,7 +399,7 @@ class RbacUserControllerAcceptanceTest {
|
|||||||
|
|
||||||
RbacUserEntity findRbacUserByName(final String userName) {
|
RbacUserEntity findRbacUserByName(final String userName) {
|
||||||
return jpaAttempt.transacted(() -> {
|
return jpaAttempt.transacted(() -> {
|
||||||
context.setCurrentUser("mike@hostsharing.net");
|
context.define("mike@hostsharing.net");
|
||||||
return rbacUserRepository.findByName(userName);
|
return rbacUserRepository.findByName(userName);
|
||||||
}).returnedValue();
|
}).returnedValue();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user