1. Add log properties. 2. Add swagger. 3. Change Redis Session strategy to use custom header (testing).

This commit is contained in:
kostis30fyllou 2021-07-06 17:47:39 +03:00
parent 6d8dee3a90
commit a3585af683
13 changed files with 419 additions and 64 deletions

12
pom.xml
View File

@ -75,6 +75,18 @@
<artifactId>gson</artifactId>
<version>2.6.2</version>
</dependency>
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<!--swagger official ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -10,6 +10,8 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;
import org.springframework.session.web.http.HeaderHttpSessionStrategy;
import org.springframework.session.web.http.HttpSessionStrategy;
@EnableRedisHttpSession
@Configuration
@ -35,6 +37,13 @@ public class RedisConfig {
}
@Bean
public HttpSessionStrategy httpSessionStrategy(){
HeaderHttpSessionStrategy headerHttpSessionStrategy = new HeaderHttpSessionStrategy();
headerHttpSessionStrategy.setHeaderName("Session");
return headerHttpSessionStrategy;
}
/*@Bean
public CookieSerializer cookieSerializer() {
System.out.println("Cookie Serializer: Domain is " + domain);
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
@ -42,5 +51,5 @@ public class RedisConfig {
serializer.setCookiePath("/"); // <2>
serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
return serializer;
}
}*/
}

View File

@ -0,0 +1,68 @@
package eu.dnetlib.dnetrolemanagement.config.security;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.Collections;
import java.util.List;
/**
* Swagger configuration class
*/
@Configuration
@Profile({"swagger"})
@EnableSwagger2
public class SwaggerConfig {
private Logger logger = LoggerFactory.getLogger(SwaggerConfig.class);
@Bean
public Docket createRestApi() {
logger.info("SwaggerConfig for Dnet Role Management");
return new Docket(DocumentationType.SWAGGER_2)
.globalOperationParameters(globalParameterList())
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("eu.dnetlib.dnetrolemanagement.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
logger.info("SwaggerConfig Dnet Role Management API information");
return new ApiInfoBuilder()
.title("Dnet Role Management Document") // title
.description("Api documentation") // description
.version("1.0") // version
.contact(new Contact("Konstantinos Triantafyllou",
"https://code-repo.d4science.org/k.triantafyllou/dnet-role-management", "k.triantafyllou@di.uoa.gr")) // contact information
.build();
}
private List<Parameter> globalParameterList() {
Parameter authTokenHeader = new ParameterBuilder()
.name("Session") // name of the header
.modelRef(new ModelRef("string")) // data-type of the header
.required(false)
.parameterType("header")
.description("Session ID")
.build();
return Collections.singletonList(authTokenHeader);
}
}

View File

@ -0,0 +1,89 @@
package eu.dnetlib.dnetrolemanagement.controllers;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import eu.dnetlib.dnetrolemanagement.dto.User;
import eu.dnetlib.dnetrolemanagement.exception.ResourceNotFoundException;
import eu.dnetlib.dnetrolemanagement.services.RegistryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/admin")
public class AdminController {
private final RegistryService registryService;
private final Gson gson;
@Autowired
public AdminController(RegistryService registryService) {
this.gson = new Gson();
this.registryService = registryService;
}
/**
* Get the user info of the managers of a type(Community, etc.) with id(ee, egi, etc.)
*/
@RequestMapping(value = "/{type}/{id}", method = RequestMethod.GET)
public ResponseEntity<User[]> getInfos(@PathVariable("type") String type, @PathVariable("id") String id) {
Integer couId = registryService.getCouId(type, id);
if(couId != null) {
JsonArray users = registryService.getUserIdByCouId(couId, true);
JsonArray emails = registryService.getUserEmailByCouId(couId, true);
JsonArray names = registryService.getUserNamesByCouId(couId, true);
for (int i = 0; i < users.size(); i++) {
users.get(i).getAsJsonObject().addProperty("email", emails.get(i).getAsJsonObject().get("email").getAsString());
users.get(i).getAsJsonObject().addProperty("name", names.get(i).getAsJsonObject().get("name").getAsString());
}
return ResponseEntity.ok(gson.fromJson(users, User[].class));
}
throw new ResourceNotFoundException("Role has not been found");
}
/**
* Get the names of the managers of a type(Community, etc.) with id(ee, egi, etc.)
*/
@RequestMapping(value = "/{type}/{id}/name", method = RequestMethod.GET)
public ResponseEntity<User[]> getNames(@PathVariable("type") String type, @PathVariable("id") String id) {
Integer couId = registryService.getCouId(type, id);
if(couId != null) {
JsonArray users = registryService.getUserNamesByCouId(couId, true);
return ResponseEntity.ok(gson.fromJson(users, User[].class));
}
throw new ResourceNotFoundException("Role has not been found");
}
/**
* Get the Identifiers of the managers of a type(Community, etc.) with id(ee, egi, etc.)
*/
@RequestMapping(value = "/{type}/{id}/id", method = RequestMethod.GET)
public ResponseEntity<User[]> getIds(@PathVariable("type") String type, @PathVariable("id") String id) {
Integer couId = registryService.getCouId(type, id);
if(couId != null) {
JsonArray users = registryService.getUserIdByCouId(couId, true);
return ResponseEntity.ok(gson.fromJson(users, User[].class));
}
throw new ResourceNotFoundException("Role has not been found");
}
/**
* Get the emails of the managers of a type(Community, etc.) with id(ee, egi, etc.)
*/
@RequestMapping(value = "/{type}/{id}/email", method = RequestMethod.GET)
public ResponseEntity<User[]> getEmails(@PathVariable("type") String type, @PathVariable("id") String id) {
Integer couId = registryService.getCouId(type, id);
if(couId != null) {
JsonArray users = registryService.getUserEmailByCouId(couId, true);
return ResponseEntity.ok(gson.fromJson(users, User[].class));
}
throw new ResourceNotFoundException("Role has not been found");
}
}

View File

@ -0,0 +1,119 @@
package eu.dnetlib.dnetrolemanagement.controllers;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import eu.dnetlib.dnetrolemanagement.dto.User;
import eu.dnetlib.dnetrolemanagement.exception.ResourceNotFoundException;
import eu.dnetlib.dnetrolemanagement.services.RegistryService;
import eu.dnetlib.dnetrolemanagement.utils.AuthoritiesUpdater;
import eu.dnetlib.dnetrolemanagement.utils.AuthoritiesUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
import java.util.HashSet;
@RestController
@RequestMapping("/member")
public class MemberController {
private final RegistryService registryService;
private final AuthoritiesUpdater authoritiesUpdater;
private final Gson gson;
@Autowired
public MemberController(RegistryService registryService, AuthoritiesUpdater authoritiesUpdater) {
this.registryService = registryService;
this.authoritiesUpdater = authoritiesUpdater;
this.gson = new Gson();
}
/**
* Get the user info of the members of a type(Community, etc.) with id(ee, egi, etc.)
*/
@PreAuthorize("hasAuthority('REGISTERED_USER')")
@RequestMapping(value = "/{type}/{id}", method = RequestMethod.GET)
public ResponseEntity<User[]> getInfos(@PathVariable("type") String type, @PathVariable("id") String id) {
Integer couId = registryService.getCouId(type, id);
if(couId != null) {
JsonArray users = registryService.getUserIdByCouId(couId, false);
JsonArray emails = registryService.getUserEmailByCouId(couId, false);
JsonArray names = registryService.getUserNamesByCouId(couId, false);
for (int i = 0; i < users.size(); i++) {
users.get(i).getAsJsonObject().addProperty("email", emails.get(i).getAsJsonObject().get("email").getAsString());
users.get(i).getAsJsonObject().addProperty("name", names.get(i).getAsJsonObject().get("name").getAsString());
}
return ResponseEntity.ok(gson.fromJson(users, User[].class));
}
throw new ResourceNotFoundException("Role has not been found");
}
/**
* Get the names of the members of a type(Community, etc.) with id(ee, egi, etc.)
*/
@RequestMapping(value = "/{type}/{id}/name", method = RequestMethod.GET)
public ResponseEntity<User[]> getNames(@PathVariable("type") String type, @PathVariable("id") String id) {
Integer couId = registryService.getCouId(type, id);
if(couId != null) {
JsonArray users = registryService.getUserNamesByCouId(couId, false);
return ResponseEntity.ok(gson.fromJson(users, User[].class));
}
throw new ResourceNotFoundException("Role has not been found");
}
/**
* Get the Identifiers of the members of a type(Community, etc.) with id(ee, egi, etc.)
*/
@RequestMapping(value = "/{type}/{id}/id", method = RequestMethod.GET)
public ResponseEntity<User[]> getIds(@PathVariable("type") String type, @PathVariable("id") String id) {
Integer couId = registryService.getCouId(type, id);
if(couId != null) {
JsonArray users = registryService.getUserIdByCouId(couId, false);
return ResponseEntity.ok(gson.fromJson(users, User[].class));
}
throw new ResourceNotFoundException("Role has not been found");
}
/**
* Get the emails of the members of a type(Community, etc.) with id(ee, egi, etc.)
*/
@RequestMapping(value = "/{type}/{id}/email", method = RequestMethod.GET)
public ResponseEntity<User[]> getEmails(@PathVariable("type") String type, @PathVariable("id") String id) {
Integer couId = registryService.getCouId(type, id);
if(couId != null) {
JsonArray users = registryService.getUserEmailByCouId(couId, false);
return ResponseEntity.ok(gson.fromJson(users, User[].class));
}
throw new ResourceNotFoundException("Role has not been found");
}
/**
* Assign member role to logged in user
*/
@RequestMapping(value = "/{type}/{id}", method = RequestMethod.POST)
@PreAuthorize("hasAuthority('REGISTRED_USER')")
public ResponseEntity<User[]> assignRole(@PathVariable("type") String type, @PathVariable("id") String id) {
Integer coPersonId = registryService.getCoPersonIdByIdentifier();
if (coPersonId != null) {
Integer couId = registryService.getCouId(type, id);
if (couId != null) {
Integer role = registryService.getRoleId(coPersonId, couId);
registryService.assignMemberRole(coPersonId, couId, role);
authoritiesUpdater.update(AuthoritiesUtils.getAaiId(), old -> {
HashSet<SimpleGrantedAuthority> authorities = new HashSet<>((Collection<? extends SimpleGrantedAuthority>) old);
authorities.add(new SimpleGrantedAuthority(AuthoritiesUtils.member(type, id)));
return authorities;
});
}
throw new ResourceNotFoundException("Role has not been found");
}
throw new ResourceNotFoundException("Role has not been found");
}
}

View File

@ -1,35 +0,0 @@
package eu.dnetlib.dnetrolemanagement.controllers;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import eu.dnetlib.dnetrolemanagement.dto.Manager;
import eu.dnetlib.dnetrolemanagement.services.RegistryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/registry")
public class RegistryController {
private RegistryService registryService;
Gson gson = new Gson();
@Autowired
public RegistryController(RegistryService registryService) {
this.registryService = registryService;
}
@RequestMapping(value = "/{type}/{id}/managers/id", method = RequestMethod.GET)
public ResponseEntity<Manager[]> getManagers(@PathVariable("type") String type, @PathVariable("id") String id) {
Integer couId = registryService.getCouId(type, id);
if(couId != null) {
JsonArray managers = registryService.getUserIdByCouId(couId, true);
return ResponseEntity.ok(gson.fromJson(managers, Manager[].class));
}
return null;
}
}

View File

@ -1,15 +1,13 @@
package eu.dnetlib.dnetrolemanagement.dto;
import java.util.Date;
public class Manager {
public class User {
private String id;
private String email;
private String name;
private String memberSince;
public Manager() {
public User() {
}
public String getId() {

View File

@ -0,0 +1,20 @@
package eu.dnetlib.dnetrolemanagement.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value = HttpStatus.NOT_FOUND) // 404
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
public ResourceNotFoundException(String message, Throwable err) {
super(message, err);
}
public HttpStatus getStatus() {
return HttpStatus.NOT_FOUND;
}
}

View File

@ -35,15 +35,6 @@ public class RegistryService {
this.jsonUtils = jsonUtils;
}
private String mapType(String type, boolean communityMap) {
if(type.equals("organization")) {
type = "institution";
} else if(type.equals("ri") && communityMap) {
type = "community";
}
return type;
}
/**
* 1. Get CoPersonId by Email
*/
@ -160,19 +151,8 @@ public class RegistryService {
* @param id
* @return
*/
public Integer getCouId(String type, String id, boolean communityMap) {
return getCouId(mapType(type, communityMap) + "." + id);
}
/**
* 4.3 Get a couId by type.id with mapping type
*
* @param type
* @param id
* @return
*/
public Integer getCouId(String type, String id) {
return getCouId(type, id, true);
return getCouId(type+ "." + id);
}
/**
@ -325,14 +305,14 @@ public class RegistryService {
}
JsonElement response = httpUtils.get("identifiers.json", params);
JsonArray infos = (response != null) ? response.getAsJsonObject().get("Identifiers").getAsJsonArray() : new JsonArray();
JsonArray emails = new JsonArray();
JsonArray ids = new JsonArray();
infos.forEach(info -> {
JsonObject user = new JsonObject();
user.addProperty("id", info.getAsJsonObject().get("Identifier").getAsString());
user.addProperty("memberSince", info.getAsJsonObject().get("Created").getAsString());
emails.add(user);
ids.add(user);
});
return emails;
return ids;
}
/**

View File

@ -0,0 +1,55 @@
package eu.dnetlib.dnetrolemanagement.utils;
import org.apache.log4j.Logger;
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.session.ExpiringSession;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Map;
@Service
public class AuthoritiesUpdater extends HttpSessionSecurityContextRepository {
private static final Logger logger = Logger.getLogger(AuthoritiesUpdater.class);
@Autowired
FindByIndexNameSessionRepository sessions;
public void update(String id, Update update) {
if (sessions != null) {
Map<String, ExpiringSession> map = sessions.
findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, id);
logger.debug(map.values().toArray().length);
for (ExpiringSession session : map.values()) {
logger.debug(session.getId());
if (!session.isExpired()) {
SecurityContext securityContext = session.getAttribute(SPRING_SECURITY_CONTEXT_KEY);
Authentication authentication = securityContext.getAuthentication();
if (authentication instanceof OIDCAuthenticationToken) {
OIDCAuthenticationToken authOIDC = (OIDCAuthenticationToken) authentication;
Collection<? extends GrantedAuthority> authorities = update.authorities(authentication.getAuthorities());
logger.debug(authorities);
securityContext.setAuthentication(new OIDCAuthenticationToken(authOIDC.getSub(), authOIDC.getIssuer(),
authOIDC.getUserInfo(), authorities, authOIDC.getIdToken(),
authOIDC.getAccessTokenValue(), authOIDC.getRefreshTokenValue()));
logger.debug("Update authorities");
session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, securityContext);
sessions.save(session);
}
}
}
}
}
public interface Update {
Collection<? extends GrantedAuthority> authorities(Collection<? extends GrantedAuthority> old);
}
}

View File

@ -0,0 +1,17 @@
package eu.dnetlib.dnetrolemanagement.utils;
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
public class AuthoritiesUtils {
public static String member(String type, String id) {
return type.toUpperCase() + "_" + id.toUpperCase();
}
public static String getAaiId() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return authentication instanceof OIDCAuthenticationToken ? ((OIDCAuthenticationToken)authentication).getSub() : null;
}
}

View File

@ -0,0 +1,20 @@
log4j.rootLogger = DEBUG, R
log4j.logger.eu.dnetlib = DEBUG
log4j.logger.org.springframework = DEBUG, S
log4j.additivity.org.springframework = false
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=/var/log/dnet/dnet-role-management/dnet-role-management.log
log4j.appender.R.MaxFileSize=10MB
log4j.appender.R.MaxBackupIndex=10
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern= %d %p %t [%c] - %m%n
log4j.appender.S=org.apache.log4j.RollingFileAppender
log4j.appender.S.File=/var/log/dnet/dnet-role-management/dnet-role-management-spring.log
log4j.appender.S.MaxFileSize=10MB
log4j.appender.S.MaxBackupIndex=10
log4j.appender.S.layout=org.apache.log4j.PatternLayout
log4j.appender.S.layout.ConversionPattern= %d %p %t [%c] - %m%n

View File

@ -4,4 +4,7 @@ registry.user=***REMOVED***
registry.password=***REMOVED***
registry.version=1.0
server.port=8090
redis.host = localhost
redis.port = 6379
redis.password =
webbapp.front.domain=.di.uoa.gr