diff --git a/pom.xml b/pom.xml index 5672e7b40..f0e791901 100644 --- a/pom.xml +++ b/pom.xml @@ -69,6 +69,7 @@ 2.0.1 0.9.9 4.3.7.RELEASE + 5.5.1 3.9 1.13 2.0.1 @@ -213,6 +214,11 @@ spring-web ${springframework.version} + + org.springframework.security + spring-security-core + ${springframework.security.version} + com.fasterxml.jackson.core jackson-core diff --git a/src/main/java/com/github/kongchen/swagger/docgen/reader/SpringMvcApiWithAuthorizationReader.java b/src/main/java/com/github/kongchen/swagger/docgen/reader/SpringMvcApiWithAuthorizationReader.java new file mode 100644 index 000000000..53f198101 --- /dev/null +++ b/src/main/java/com/github/kongchen/swagger/docgen/reader/SpringMvcApiWithAuthorizationReader.java @@ -0,0 +1,79 @@ +package com.github.kongchen.swagger.docgen.reader; + +import com.github.kongchen.swagger.docgen.spring.SpringResource; +import io.swagger.models.Operation; +import io.swagger.models.Path; +import io.swagger.models.Swagger; +import org.apache.maven.plugin.logging.Log; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; + +import static org.apache.commons.lang3.ObjectUtils.allNotNull; +import static org.apache.commons.lang3.StringUtils.isBlank; +import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation; + +/** + * Extends rest api endpoint description with the permissions details that given endpoint requires. + * + * This swagger reader is used as {@code swaggerApiReader} property of the {@code swagger-maven-plugin}. + */ +public class SpringMvcApiWithAuthorizationReader extends SpringMvcApiReader { + + private static final String PERMISSIONS_LABEL = "\n\n**Required Permissions**:\n\n"; + + public SpringMvcApiWithAuthorizationReader(Swagger swagger, Log log) { + super(swagger, log); + } + + @Override + public Swagger read(SpringResource resource) { + Swagger extSwagger = super.read(resource); + + List methods = resource.getMethods(); + for (Method method : methods) { + PreAuthorize preAuthorize = findMergedAnnotation(method, PreAuthorize.class); + RequestMapping requestMapping = findMergedAnnotation(method, RequestMapping.class); + String resourcePathKey = resource.getControllerMapping() + resource.getResourceName(); + Path path = extSwagger.getPath(resourcePathKey); + String permissions = preAuthorize.value(); + if (!allNotNull(preAuthorize, requestMapping, path) || isBlank(permissions)) continue; // nothing to update + + Arrays.stream(requestMapping.method()) + .map(reqMethod -> operation(path, reqMethod)) + .forEach(operation -> updateOperation(operation, permissions)); + } + + return extSwagger; + } + + private static Operation operation(Path path, RequestMethod method) { + switch (method) { + case POST: + return path.getPost(); + case GET: + return path.getGet(); + case PUT: + return path.getPut(); + case DELETE: + return path.getDelete(); + case HEAD: + return path.getHead(); + case OPTIONS: + return path.getOptions(); + case PATCH: + return path.getPatch(); + default: + throw new IllegalArgumentException("could not find operation for method " + method); + } + } + + private static void updateOperation(Operation operation, String permissions) { + String updatedDescription = operation.getDescription() + PERMISSIONS_LABEL + permissions; + operation.description(updatedDescription); + } +}