diff --git a/.gitignore b/.gitignore index 2e7c3f6..6a56a29 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,6 @@ fabric.properties # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser +# Local Deployment scripts +make.sh + diff --git a/pom.xml b/pom.xml index d778bbc..79c15d5 100644 --- a/pom.xml +++ b/pom.xml @@ -1,12 +1,11 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.springframework.boot - spring-boot-starter-parent - 2.5.2 - + eu.dnetlib + dnet45-parent + 1.0.0 eu.dnetlib dnet-role-management @@ -17,12 +16,23 @@ 1.8 + + + + org.springframework.boot + spring-boot-dependencies + 1.5.8.RELEASE + pom + import + + + + org.springframework.boot spring-boot-starter-web - org.springframework.boot spring-boot-starter-tomcat @@ -33,15 +43,48 @@ spring-boot-starter-test test + + org.springframework.boot + spring-boot-starter-security + + + + org.springframework.session + spring-session-data-redis + + + biz.paluch.redis + lettuce + 4.3.3.Final + + + + org.mitre + openid-connect-client + 1.3.0 + + + org.bouncycastle + bcprov-jdk15on + + + + + + com.google.code.gson + gson + 2.6.2 + - - org.springframework.boot - spring-boot-maven-plugin + maven-war-plugin + 2.4 + + false + - - + \ No newline at end of file diff --git a/src/main/java/eu/dnetlib/dnetrolemanagement/DnetRoleManagementApplication.java b/src/main/java/eu/dnetlib/dnetrolemanagement/DnetRoleManagementApplication.java index b93f970..fee3b97 100644 --- a/src/main/java/eu/dnetlib/dnetrolemanagement/DnetRoleManagementApplication.java +++ b/src/main/java/eu/dnetlib/dnetrolemanagement/DnetRoleManagementApplication.java @@ -1,9 +1,19 @@ package eu.dnetlib.dnetrolemanagement; +import eu.dnetlib.dnetrolemanagement.config.properties.RedisProperties; +import eu.dnetlib.dnetrolemanagement.config.properties.RegistryProperties; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.PropertySources; -@SpringBootApplication +@SpringBootApplication(scanBasePackages = {"eu.dnetlib.dnetrolemanagement"}) +@PropertySources({ + @PropertySource("classpath:registry.properties"), + @PropertySource(value = "classpath:dnet-override.properties", ignoreResourceNotFound = true) +}) +@EnableConfigurationProperties({RegistryProperties.class, RedisProperties.class}) public class DnetRoleManagementApplication { public static void main(String[] args) { diff --git a/src/main/java/eu/dnetlib/dnetrolemanagement/ServletInitializer.java b/src/main/java/eu/dnetlib/dnetrolemanagement/ServletInitializer.java index 0f8aae6..b926e48 100644 --- a/src/main/java/eu/dnetlib/dnetrolemanagement/ServletInitializer.java +++ b/src/main/java/eu/dnetlib/dnetrolemanagement/ServletInitializer.java @@ -1,7 +1,7 @@ package eu.dnetlib.dnetrolemanagement; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.boot.web.support.SpringBootServletInitializer; public class ServletInitializer extends SpringBootServletInitializer { diff --git a/src/main/java/eu/dnetlib/dnetrolemanagement/config/properties/RedisProperties.java b/src/main/java/eu/dnetlib/dnetrolemanagement/config/properties/RedisProperties.java new file mode 100644 index 0000000..6727502 --- /dev/null +++ b/src/main/java/eu/dnetlib/dnetrolemanagement/config/properties/RedisProperties.java @@ -0,0 +1,37 @@ +package eu.dnetlib.dnetrolemanagement.config.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties("redis") +public class RedisProperties { + private String host = "localhost"; + private String port = "6379"; + private String password; + + public RedisProperties() { + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/src/main/java/eu/dnetlib/dnetrolemanagement/config/properties/RegistryProperties.java b/src/main/java/eu/dnetlib/dnetrolemanagement/config/properties/RegistryProperties.java new file mode 100644 index 0000000..e04ede7 --- /dev/null +++ b/src/main/java/eu/dnetlib/dnetrolemanagement/config/properties/RegistryProperties.java @@ -0,0 +1,56 @@ +package eu.dnetlib.dnetrolemanagement.config.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties("registry") +public class RegistryProperties { + + private String coid; + private String issuer; + private String user; + private String password; + private String version; + + public RegistryProperties() { + } + + public String getCoid() { + return coid; + } + + public void setCoid(String coid) { + this.coid = coid; + } + + public String getIssuer() { + return issuer; + } + + public void setIssuer(String issuer) { + this.issuer = issuer; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } +} diff --git a/src/main/java/eu/dnetlib/dnetrolemanagement/config/security/CorsConfig.java b/src/main/java/eu/dnetlib/dnetrolemanagement/config/security/CorsConfig.java new file mode 100644 index 0000000..facff24 --- /dev/null +++ b/src/main/java/eu/dnetlib/dnetrolemanagement/config/security/CorsConfig.java @@ -0,0 +1,16 @@ +package eu.dnetlib.dnetrolemanagement.config.security; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +public class CorsConfig extends WebMvcConfigurerAdapter { + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS") + .allowCredentials(true); + } +} diff --git a/src/main/java/eu/dnetlib/dnetrolemanagement/config/security/RedisConfig.java b/src/main/java/eu/dnetlib/dnetrolemanagement/config/security/RedisConfig.java new file mode 100644 index 0000000..9a63dd0 --- /dev/null +++ b/src/main/java/eu/dnetlib/dnetrolemanagement/config/security/RedisConfig.java @@ -0,0 +1,46 @@ +package eu.dnetlib.dnetrolemanagement.config.security; + +import eu.dnetlib.dnetrolemanagement.config.properties.RedisProperties; +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +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; + +@EnableRedisHttpSession +@Configuration +public class RedisConfig { + + private static final Logger logger = Logger.getLogger(RedisConfig.class); + private RedisProperties redisProperties; + + @Value("${webbapp.front.domain:openaire.eu}") + private String domain; + + @Autowired + public RedisConfig(RedisProperties redisProperties) { + this.redisProperties = redisProperties; + } + + @Bean + public LettuceConnectionFactory connectionFactory() { + logger.info(String.format("Redis connection listens to %s:%s ", redisProperties.getHost(), redisProperties.getPort())); + LettuceConnectionFactory factory = new LettuceConnectionFactory(redisProperties.getHost(), Integer.parseInt(redisProperties.getPort())); + if (redisProperties.getPassword() != null) factory.setPassword(redisProperties.getPassword()); + return factory; + } + + @Bean + public CookieSerializer cookieSerializer() { + System.out.println("Cookie Serializer: Domain is " + domain); + DefaultCookieSerializer serializer = new DefaultCookieSerializer(); + serializer.setCookieName("openAIRESession"); // <1> + serializer.setCookiePath("/"); // <2> + serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$"); + return serializer; + } +} \ No newline at end of file diff --git a/src/main/java/eu/dnetlib/dnetrolemanagement/config/security/WebSecurityConfig.java b/src/main/java/eu/dnetlib/dnetrolemanagement/config/security/WebSecurityConfig.java new file mode 100644 index 0000000..763b650 --- /dev/null +++ b/src/main/java/eu/dnetlib/dnetrolemanagement/config/security/WebSecurityConfig.java @@ -0,0 +1,20 @@ +package eu.dnetlib.dnetrolemanagement.config.security; + +import eu.dnetlib.dnetrolemanagement.utils.EntryPoint; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) +@EnableWebSecurity +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.csrf(); + http.authorizeRequests().anyRequest().permitAll(); + http.httpBasic().authenticationEntryPoint(new EntryPoint()); + } + +} diff --git a/src/main/java/eu/dnetlib/dnetrolemanagement/controllers/RegistryController.java b/src/main/java/eu/dnetlib/dnetrolemanagement/controllers/RegistryController.java new file mode 100644 index 0000000..291b18a --- /dev/null +++ b/src/main/java/eu/dnetlib/dnetrolemanagement/controllers/RegistryController.java @@ -0,0 +1,35 @@ +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 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; + } +} diff --git a/src/main/java/eu/dnetlib/dnetrolemanagement/dto/Manager.java b/src/main/java/eu/dnetlib/dnetrolemanagement/dto/Manager.java new file mode 100644 index 0000000..58b64a4 --- /dev/null +++ b/src/main/java/eu/dnetlib/dnetrolemanagement/dto/Manager.java @@ -0,0 +1,46 @@ +package eu.dnetlib.dnetrolemanagement.dto; + +import java.util.Date; + +public class Manager { + + private String id; + private String email; + private String name; + private String memberSince; + + public Manager() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getMemberSince() { + return memberSince; + } + + public void setMemberSince(String memberSince) { + this.memberSince = memberSince; + } +} diff --git a/src/main/java/eu/dnetlib/dnetrolemanagement/services/RegistryService.java b/src/main/java/eu/dnetlib/dnetrolemanagement/services/RegistryService.java new file mode 100644 index 0000000..e899979 --- /dev/null +++ b/src/main/java/eu/dnetlib/dnetrolemanagement/services/RegistryService.java @@ -0,0 +1,425 @@ +package eu.dnetlib.dnetrolemanagement.services; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import eu.dnetlib.dnetrolemanagement.config.properties.RegistryProperties; +import eu.dnetlib.dnetrolemanagement.utils.HttpUtils; +import eu.dnetlib.dnetrolemanagement.utils.JsonUtils; +import org.apache.log4j.Logger; +import org.mitre.openid.connect.model.OIDCAuthenticationToken; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class RegistryService { + + private static final Logger logger = Logger.getLogger(RegistryService.class); + + private final String coid; + + public HttpUtils httpUtils; + + public JsonUtils jsonUtils; + + @Autowired + public RegistryService(HttpUtils httpUtils, JsonUtils jsonUtils, RegistryProperties registryProperties) { + this.coid = registryProperties.getCoid(); + this.httpUtils = httpUtils; + 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 + */ + public Integer getCoPersonIdByEmail() { + try { + OIDCAuthenticationToken authentication = (OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); + String email = authentication.getUserInfo().getEmail(); + Map params = new HashMap<>(); + params.put("coid", coid); + params.put("mail", email); + JsonElement response = httpUtils.get("co_people.json", params); + return (response != null) ? response.getAsJsonObject().get("CoPeople").getAsJsonArray().get(0).getAsJsonObject().get("Id").getAsInt() : null; + } catch (Exception e) { + logger.error("Get User info: An error occurred ", e); + return null; + } + } + + public Integer getCoPersonIdByEmail(String email) { + Map params = new HashMap<>(); + params.put("coid", coid); + params.put("mail", email); + JsonElement response = httpUtils.get("co_people.json", params); + if(response != null) { + JsonArray coPeople = response.getAsJsonObject().get("CoPeople").getAsJsonArray(); + if(coPeople.size() > 0) { + return coPeople.get(0).getAsJsonObject().get("Id").getAsInt(); + } + } + return null; + } + + public List getCoPersonIdsByEmail(String email) { + List coPersonIds = new ArrayList<>(); + Map params = new HashMap<>(); + params.put("coid", coid); + params.put("mail", email); + JsonElement response = httpUtils.get("co_people.json", params); + if(response != null) { + JsonArray coPeople = response.getAsJsonObject().get("CoPeople").getAsJsonArray(); + for(int i = 0; i < coPeople.size(); i++) { + coPersonIds.add(coPeople.get(i).getAsJsonObject().get("Id").getAsInt()); + } + } + return coPersonIds; + } + + /** + * 2. Get CoPersonId by AAI identifier + */ + public Integer getCoPersonIdByIdentifier() { + try { + OIDCAuthenticationToken authentication = (OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); + String sub = authentication.getUserInfo().getSub(); + Map params = new HashMap<>(); + params.put("coid", coid); + params.put("search.identifier", sub); + JsonElement response = httpUtils.get("co_people.json", params); + return (response != null) ? response.getAsJsonObject().get("CoPeople").getAsJsonArray().get(0).getAsJsonObject().get("Id").getAsInt() : null; + } catch (Exception e) { + logger.error("Get User info: An error occurred ", e); + return null; + } + } + + public Integer getCoPersonIdByIdentifier(String sub) { + Map params = new HashMap<>(); + params.put("coid", coid); + params.put("search.identifier", sub); + JsonElement response = httpUtils.get("co_people.json", params); + return (response != null) ? response.getAsJsonObject().get("CoPeople").getAsJsonArray().get(0).getAsJsonObject().get("Id").getAsInt() : null; + } + + /** + * 3.1 Get OpenAIRE cous with a specific name(or substring) + */ + public JsonArray getCous(String name) { + Map params = new HashMap<>(); + params.put("coid", coid); + if(name != null) { + params.put("name", name.toLowerCase()); + } + JsonElement response = httpUtils.get("cous.json", params); + return (response != null) ? response.getAsJsonObject().get("Cous").getAsJsonArray() : new JsonArray(); + } + + /** + * 3.2 Get all OpenAIRE cous + */ + public JsonArray getCous() { + return getCous(null); + } + + /** + * 4.1 Get a couId by name + * + * @param name + * @return + */ + public Integer getCouId(String name) { + JsonArray cous = getCous(name); + for (JsonElement cou : cous) { + if (cou.getAsJsonObject().get("Name").getAsString().toLowerCase().equals(name.toLowerCase())) { + return cou.getAsJsonObject().get("Id").getAsInt(); + } + } + return null; + } + + /** + * 4.2 Get a couId by type.id with/without mapping type + * + * @param type + * @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); + } + + /** + * 5. Get User non admin roles + */ + public JsonArray getRoles(Integer coPersonId) { + Map params = new HashMap<>(); + params.put("copersonid", coPersonId.toString()); + JsonElement response = httpUtils.get("co_person_roles.json", params); + return (response != null) ? response.getAsJsonObject().get("CoPersonRoles").getAsJsonArray() : new JsonArray(); + } + + /** + * 6. Get Role id of User base on couId. + */ + public Integer getRoleId(Integer coPersonId, Integer couId) { + JsonArray roles = getRoles(coPersonId); + for (JsonElement role : roles) { + JsonObject object = role.getAsJsonObject(); + if (object.get("CouId").getAsInt() == couId && !object.get("Status").getAsString().equals("Deleted")) { + return object.get("Id").getAsInt(); + } + } + return null; + } + + /** + * 7. Get User Groups + */ + public JsonArray getUserGroups(Integer coPersonId) { + Map params = new HashMap<>(); + params.put("copersonid", coPersonId.toString()); + JsonElement response = httpUtils.get("co_groups.json", params); + return (response != null) ? response.getAsJsonObject().get("CoGroups").getAsJsonArray() : new JsonArray(); + } + + /** + * 8. Get User Admin Group of a Cou + */ + public JsonObject getUserAdminGroup(Integer coPersonId, Integer couId) { + Map params = new HashMap<>(); + params.put("copersonid", coPersonId.toString()); + JsonElement response = httpUtils.get("co_groups.json", params); + JsonArray roles = (response != null) ? response.getAsJsonObject().get("CoGroups").getAsJsonArray() : new JsonArray(); + for (JsonElement role : roles) { + JsonObject object = role.getAsJsonObject(); + if (object.get("CouId") != null && object.get("CouId").getAsInt() == couId) { + if (object.get("Name").getAsString().contains("admins")) { + return object; + } + } + } + return null; + } + + /** + * 9. Get Groups of a Cou + */ + public JsonArray getCouGroups(Integer couId) { + Map params = new HashMap<>(); + params.put("coid", coid); + params.put("couid", couId.toString()); + JsonElement response = httpUtils.get("co_groups.json", params); + return (response != null) ? response.getAsJsonObject().get("CoGroups").getAsJsonArray() : new JsonArray(); + } + + /** + * 10. Get Admin Group of a Cou + */ + public JsonObject getCouAdminGroup(Integer couId) { + JsonArray groups = getCouGroups(couId); + for (JsonElement group : groups) { + if (group.getAsJsonObject().get("Name").getAsString().contains("admins")) { + return group.getAsJsonObject(); + } + } + return null; + } + + /** + * 11. Get users of a group + */ + public JsonArray getGroupMembers(Integer coGroupId) { + Map params = new HashMap<>(); + params.put("cogroupid", coGroupId.toString()); + JsonElement response = httpUtils.get("co_group_members.json", params); + return (response != null) ? response.getAsJsonObject().get("CoGroupMembers").getAsJsonArray() : new JsonArray(); + } + + + /** + * 12. Get Users' email of a Cou + */ + public JsonArray getUserEmailByCouId(Integer couId, boolean admin) { + Map params = new HashMap<>(); + params.put("couid", couId.toString()); + if (admin) { + params.put("admin", "true"); + } + JsonElement response = httpUtils.get("email_addresses.json", params); + JsonArray infos = (response != null) ? response.getAsJsonObject().get("EmailAddresses").getAsJsonArray() : new JsonArray(); + JsonArray emails = new JsonArray(); + infos.forEach(info -> { + JsonObject user = new JsonObject(); + boolean add = true; + String email = info.getAsJsonObject().get("Mail").getAsString(); + for(JsonElement element : emails) { + if(element.getAsJsonObject().get("email").getAsString().equals(email)) { + add = false; + } + } + if(add) { + user.addProperty("email", email); + user.addProperty("memberSince", info.getAsJsonObject().get("Created").getAsString()); + emails.add(user); + } + }); + return emails; + } + + /** + * 13. Get Users' names of a Cou + */ + public JsonArray getUserNamesByCouId(Integer couId, boolean admin) { + Map params = new HashMap<>(); + params.put("couid", couId.toString()); + if (admin) { + params.put("admin", "true"); + } + JsonElement response = httpUtils.get("names.json", params); + JsonArray infos = (response != null) ? response.getAsJsonObject().get("Names").getAsJsonArray() : new JsonArray(); + JsonArray names = new JsonArray(); + infos.forEach(info -> { + JsonObject user = new JsonObject(); + user.addProperty("name", info.getAsJsonObject().get("Given").getAsString() + " " + info.getAsJsonObject().get("Family").getAsString()); + user.addProperty("memberSince", info.getAsJsonObject().get("Created").getAsString()); + names.add(user); + }); + return names; + } + + /** + * 14. Get Users' identifiers of a Cou + */ + public JsonArray getUserIdByCouId(Integer couId, boolean admin) { + Map params = new HashMap<>(); + params.put("couid", couId.toString()); + if (admin) { + params.put("admin", "true"); + } + JsonElement response = httpUtils.get("identifiers.json", params); + JsonArray infos = (response != null) ? response.getAsJsonObject().get("Identifiers").getAsJsonArray() : new JsonArray(); + JsonArray emails = 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); + }); + return emails; + } + + /** + * 15. Assign a member role to a User + */ + public void assignMemberRole(Integer coPersonId, Integer couId, Integer id) { + if (id != null) { + httpUtils.put("co_person_roles/" + id.toString() + ".json", jsonUtils.coPersonRoles(coPersonId, couId, "Active")); + } else { + httpUtils.post("co_person_roles.json", jsonUtils.coPersonRoles(coPersonId, couId, "Active")); + } + } + + /** + * 16. Remove a member role from a User + */ + public void removeMemberRole(Integer coPersonId, Integer couId, Integer id) { + if(id != null) { + httpUtils.put("co_person_roles/" + id.toString() + ".json", jsonUtils.coPersonRoles(coPersonId, couId, "Deleted")); + } + } + + /** + * 17. Create a new role + */ + public Integer createRole(String name, String description) { + JsonElement element = httpUtils.post("cous.json", jsonUtils.createNewCou(name, description)); + return element.getAsJsonObject().get("Id").getAsInt(); + } + + /** + * 18. Get User's email + */ + public String getUserEmail(Integer coPersonId) { + Map params = new HashMap<>(); + params.put("copersonid", coPersonId.toString()); + JsonElement response = httpUtils.get("email_addresses.json", params); + JsonObject info = (response != null) ? response.getAsJsonObject().get("EmailAddresses").getAsJsonArray().get(0).getAsJsonObject() : null; + return (info != null) ? info.getAsJsonObject().get("Mail").getAsString() : null; + } + + /** + * 19. Get User's names + */ + public String getUserNames(Integer coPersonId) { + Map params = new HashMap<>(); + params.put("copersonid", coPersonId.toString()); + JsonElement response = httpUtils.get("names.json", params); + JsonObject info = (response != null) ? response.getAsJsonObject().get("Names").getAsJsonArray().get(0).getAsJsonObject() : null; + return (info != null) ? info.getAsJsonObject().get("Given").getAsString() + " " + info.getAsJsonObject().get("Family").getAsString() : null; + } + + /** + * 20. Get User's identifier + */ + public String getUserId(Integer coPersonId) { + Map params = new HashMap<>(); + params.put("copersonid", coPersonId.toString()); + JsonElement response = httpUtils.get("identifiers.json", params); + JsonObject info = (response != null) ? response.getAsJsonObject().get("Identifiers").getAsJsonArray().get(0).getAsJsonObject() : null; + return (info != null) ? info.getAsJsonObject().get("Identifier").getAsString() : null; + } + + /** + * 21. Assign an admin role to a User + */ + public void assignAdminRole(Integer coPersonId, Integer couId) { + JsonObject group = getCouAdminGroup(couId); + if (group != null) { + httpUtils.post("co_group_members.json", jsonUtils.coGroupMembers(group.get("Id").getAsInt(), coPersonId, true)); + } + } + + /** + * 22. Remove an admin role from a User + */ + public void removeAdminRole(Integer coPersonId, Integer couId) { + JsonObject adminGroup = this.getCouAdminGroup(couId); + JsonArray admins = this.getGroupMembers(adminGroup.get("Id").getAsInt()); + Integer id = null; + for (JsonElement admin : admins) { + if (admin.getAsJsonObject().get("Person").getAsJsonObject().get("Id").getAsInt() == coPersonId) { + id = admin.getAsJsonObject().get("Id").getAsInt(); + } + } + if (id != null) { + httpUtils.delete("co_group_members/" + id.toString() + ".json"); + } + } +} diff --git a/src/main/java/eu/dnetlib/dnetrolemanagement/utils/EntryPoint.java b/src/main/java/eu/dnetlib/dnetrolemanagement/utils/EntryPoint.java new file mode 100644 index 0000000..0f91a17 --- /dev/null +++ b/src/main/java/eu/dnetlib/dnetrolemanagement/utils/EntryPoint.java @@ -0,0 +1,19 @@ +package eu.dnetlib.dnetrolemanagement.utils; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class EntryPoint implements AuthenticationEntryPoint { + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, + AuthenticationException authException) throws IOException { + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); + } + +} + diff --git a/src/main/java/eu/dnetlib/dnetrolemanagement/utils/HttpUtils.java b/src/main/java/eu/dnetlib/dnetrolemanagement/utils/HttpUtils.java new file mode 100644 index 0000000..86a7520 --- /dev/null +++ b/src/main/java/eu/dnetlib/dnetrolemanagement/utils/HttpUtils.java @@ -0,0 +1,103 @@ +package eu.dnetlib.dnetrolemanagement.utils; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import eu.dnetlib.dnetrolemanagement.config.properties.RegistryProperties; +import org.apache.log4j.Logger; +import org.apache.tomcat.util.codec.binary.Base64; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.*; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.nio.charset.Charset; +import java.util.Map; + +@Component +public class HttpUtils { + + private static final Logger logger = Logger.getLogger(eu.dnetlib.dnetrolemanagement.utils.HttpUtils.class); + + private RegistryProperties registryProperties; + + @Autowired + public HttpUtils(RegistryProperties registryProperties) { + this.registryProperties = registryProperties; + } + + public JsonElement post(String path, JsonObject body) { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = createHeaders(registryProperties.getUser(), registryProperties.getPassword()); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity request = new HttpEntity<>(body.toString(), headers); + ResponseEntity responseEntity = restTemplate.exchange(registryProperties.getIssuer() + path, HttpMethod.POST, request, String.class); + if (responseEntity.getBody() != null) { + return new JsonParser().parse(responseEntity.getBody()); + } else { + return null; + } + } + + public JsonElement put(String path, JsonObject body) { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = createHeaders(registryProperties.getUser(), registryProperties.getPassword()); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity request = new HttpEntity<>(body.toString(), headers); + ResponseEntity responseEntity = restTemplate.exchange(registryProperties.getIssuer() + path, HttpMethod.PUT, request, String.class); + if (responseEntity.getBody() != null) { + return new JsonParser().parse(responseEntity.getBody()); + } else { + return null; + } + } + + public JsonElement get(String path, Map params) { + RestTemplate restTemplate = new RestTemplate(); + String url = registryProperties.getIssuer() + path + ((params != null) ? createParams(params) : null); + ResponseEntity responseEntity = restTemplate.exchange + (url, HttpMethod.GET, new HttpEntity<>(createHeaders(registryProperties.getUser(), registryProperties.getPassword())), String.class); + if (responseEntity.getBody() != null) { + return new JsonParser().parse(responseEntity.getBody()); + } else { + return null; + } + } + + public JsonElement delete(String path) { + RestTemplate restTemplate = new RestTemplate(); + String url = registryProperties.getIssuer() + path; + ResponseEntity responseEntity = restTemplate.exchange + (url, HttpMethod.DELETE, new HttpEntity<>(createHeaders(registryProperties.getUser(), registryProperties.getPassword())), String.class); + if (responseEntity.getBody() != null) { + return new JsonParser().parse(responseEntity.getBody()); + } else { + return null; + } + } + + + private String createParams(Map params) { + StringBuilder ret = new StringBuilder("?"); + int count = 0; + for (Map.Entry param : params.entrySet()) { + ret.append(param.getKey()).append("="); + ret.append(param.getValue()); + count++; + if (count != params.entrySet().size()) { + ret.append("&"); + } + } + return ret.toString(); + } + + private HttpHeaders createHeaders(String username, String password) { + return new HttpHeaders() {{ + String auth = username + ":" + password; + byte[] encodedAuth = Base64.encodeBase64( + auth.getBytes(Charset.forName("US-ASCII"))); + String authHeader = "Basic " + new String(encodedAuth); + set("Authorization", authHeader); + }}; + } +} diff --git a/src/main/java/eu/dnetlib/dnetrolemanagement/utils/JsonUtils.java b/src/main/java/eu/dnetlib/dnetrolemanagement/utils/JsonUtils.java new file mode 100644 index 0000000..cd3483d --- /dev/null +++ b/src/main/java/eu/dnetlib/dnetrolemanagement/utils/JsonUtils.java @@ -0,0 +1,110 @@ +package eu.dnetlib.dnetrolemanagement.utils; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import eu.dnetlib.dnetrolemanagement.config.properties.RegistryProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class JsonUtils { + + private final String version; + private final String coid; + + @Autowired + public JsonUtils(RegistryProperties registryProperties) { + this.version = registryProperties.getVersion(); + this.coid = registryProperties.getCoid(); + } + + public JsonObject coPersonRoles(Integer coPersonId, Integer couId, String status) { + JsonObject role = new JsonObject(); + JsonArray coPersonRoles = new JsonArray(); + JsonObject coPersonRole = new JsonObject(); + JsonObject person = new JsonObject(); + person.addProperty("Type", "CO"); + person.addProperty("Id", coPersonId.toString()); + coPersonRole.addProperty("Version", version); + coPersonRole.add("Person", person); + coPersonRole.addProperty("CouId", couId.toString()); + coPersonRole.addProperty("Affiliation", "member"); + coPersonRole.addProperty("Title", ""); + coPersonRole.addProperty("O", "Openaire"); + coPersonRole.addProperty("Status", status); + coPersonRole.addProperty("ValidFrom", ""); + coPersonRole.addProperty("ValidThrough", ""); + coPersonRoles.add(coPersonRole); + role.addProperty("RequestType", "CoPersonRoles"); + role.addProperty("Version", version); + role.add("CoPersonRoles", coPersonRoles); + return role; + } + + public JsonObject coGroupMembers(Integer coGroupId, Integer coPersonId, boolean member) { + JsonObject coGroup = new JsonObject(); + JsonArray coGroupMembers = new JsonArray(); + JsonObject coGroupMember = new JsonObject(); + JsonObject person = new JsonObject(); + person.addProperty("Type", "CO"); + person.addProperty("Id", coPersonId.toString()); + coGroupMember.addProperty("Version", version); + coGroupMember.add("Person", person); + coGroupMember.addProperty("CoGroupId", coGroupId.toString()); + coGroupMember.addProperty("Member", member); + coGroupMember.addProperty("Owner", false); + coGroupMember.addProperty("ValidFrom", ""); + coGroupMember.addProperty("ValidThrough", ""); + coGroupMembers.add(coGroupMember); + coGroup.addProperty("RequestType", "CoGroupMembers"); + coGroup.addProperty("Version", version); + coGroup.add("CoGroupMembers", coGroupMembers); + return coGroup; + } + + public JsonObject createNewCou(String name, String description) { + JsonObject cou = new JsonObject(); + JsonArray cous = new JsonArray(); + JsonObject newCou = new JsonObject(); + newCou.addProperty("Version", version); + newCou.addProperty("CoId", coid); + newCou.addProperty("Name",name); + newCou.addProperty("Description", description); + cous.add(newCou); + cou.addProperty("RequestType", "Cous"); + cou.addProperty("Version", version); + cou.add("Cous", cous); + return cou; + } + + public JsonObject createResponse(JsonElement response) { + JsonObject json = new JsonObject(); + json.add("response", response); + return json; + } + + public JsonObject createResponse(String response) { + JsonObject json = new JsonObject(); + json.addProperty("response", response); + return json; + } + + public JsonObject createResponse(Number response) { + JsonObject json = new JsonObject(); + json.addProperty("response", response); + return json; + } + + public JsonObject createResponse(Boolean response) { + JsonObject json = new JsonObject(); + json.addProperty("response", response); + return json; + } + + public JsonObject createResponse(Character response) { + JsonObject json = new JsonObject(); + json.addProperty("response", response); + return json; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 70d7c93..8b13789 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1 @@ -server.port = 8090 + diff --git a/src/main/resources/registry.properties b/src/main/resources/registry.properties new file mode 100644 index 0000000..c518b17 --- /dev/null +++ b/src/main/resources/registry.properties @@ -0,0 +1,7 @@ +registry.coid=2 +registry.issuer=https://openaire-dev.aai-dev.grnet.gr/registry/ +registry.user=***REMOVED*** +registry.password=***REMOVED*** +registry.version=1.0 +server.port=8090 +webbapp.front.domain=.di.uoa.gr \ No newline at end of file diff --git a/src/test/java/eu/dnetlib/dnetrolemanagement/DnetRoleManagementApplicationTests.java b/src/test/java/eu/dnetlib/dnetrolemanagement/DnetRoleManagementApplicationTests.java index 3c5ecf4..1149500 100644 --- a/src/test/java/eu/dnetlib/dnetrolemanagement/DnetRoleManagementApplicationTests.java +++ b/src/test/java/eu/dnetlib/dnetrolemanagement/DnetRoleManagementApplicationTests.java @@ -1,6 +1,6 @@ package eu.dnetlib.dnetrolemanagement; -import org.junit.jupiter.api.Test; +import org.junit.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest