Skip to content
Snippets Groups Projects
Commit 8a72ad86 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Implemented basic hook functionality

parent 3aac16a7
No related branches found
No related tags found
No related merge requests found
......@@ -28,6 +28,12 @@ The first super admin user must be added manually, then he/she will be able to a
The value `user_id` is the RAP user id.
## Hooks
It is possible to load external jar files in order to extend the GMS with custom functionalities (implementing the *Hook interfaces and annotating the class with `@org.springframework.stereotype.Component`). Currently only the `GroupsHook` is available.
External jar files need to be specified at application startup using the `LOADER_PATH` environment variable (this is a Spring feature).
## Developer notes
Backend and frontend are 2 separate applications:
......
......@@ -114,6 +114,26 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
<phase>package</phase>
<configuration>
<!-- creates a gms-lib jar that can be included as dependency in other projects -->
<classifier>lib</classifier>
<includes>
<include>**/**</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
......@@ -130,6 +150,8 @@
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<!-- layout ZIP is necessary for loading external jar using PropertiesLauncher (used for hooks) -->
<layout>ZIP</layout>
</configuration>
</plugin>
<plugin>
......
......@@ -193,7 +193,7 @@ public class JWTWebServiceController {
@DeleteMapping(value = "/{group:.+}", produces = MediaType.TEXT_PLAIN_VALUE)
public void deleteGroup(@PathVariable("group") String groupParam, HttpServletResponse response) {
GroupEntity group = getGroupFromNames(extractGroupNames(groupParam));
groupsDAO.deleteGroupById(group.getId());
groupsDAO.deleteGroup(group);
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
......
......@@ -2,6 +2,7 @@ package it.inaf.ia2.gms.persistence;
import it.inaf.ia2.gms.model.GroupBreadcrumb;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
import it.inaf.ia2.gms.service.hook.GroupsHook;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
......@@ -21,6 +22,9 @@ import org.springframework.stereotype.Component;
@Component
public class GroupsDAO {
@Autowired(required = false)
protected GroupsHook groupsHook;
private final JdbcTemplate jdbcTemplate;
@Autowired
......@@ -30,6 +34,10 @@ public class GroupsDAO {
public GroupEntity createGroup(GroupEntity group) {
if (groupsHook != null) {
groupsHook.beforeCreate(group);
}
String sql = "INSERT INTO gms_group (id, name, path, is_leaf) VALUES (?, ?, ?, ?)";
jdbcTemplate.update(conn -> {
......@@ -46,6 +54,10 @@ public class GroupsDAO {
public GroupEntity updateGroup(GroupEntity group) {
if (groupsHook != null) {
groupsHook.beforeUpdate(group);
}
String sql = "UPDATE gms_group SET name = ?, path = ?, is_leaf = ? WHERE id = ?";
jdbcTemplate.update(conn -> {
......@@ -60,9 +72,14 @@ public class GroupsDAO {
return group;
}
public void deleteGroupById(String groupId) {
public void deleteGroup(GroupEntity group) {
if (groupsHook != null) {
groupsHook.beforeDelete(group);
}
String sql = "DELETE FROM gms_group WHERE id = ?";
jdbcTemplate.update(sql, groupId);
jdbcTemplate.update(sql, group.getId());
}
public Optional<GroupEntity> findGroupById(String groupId) {
......
......@@ -3,6 +3,7 @@ package it.inaf.ia2.gms.service;
import it.inaf.ia2.gms.persistence.GroupsDAO;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
......@@ -26,6 +27,10 @@ public class GroupNameService {
return getGroupsNames(groupsDAO.findGroupsByIds(groupIdentifiers));
}
public String getGroupCompleteName(GroupEntity group) {
return getGroupsNames(Collections.singletonList(group)).get(0);
}
/**
* Returns the list of the group complete names, given a list of GroupEntity
* objects.
......
......@@ -108,8 +108,8 @@ public class GroupsService {
membershipsDAO.deleteAllGroupsMembership(groupsToDeleteIds);
permissionsDAO.deleteAllGroupsPermissions(groupsToDeleteIds);
for (String groupId : groupsToDeleteIds) {
groupsDAO.deleteGroupById(groupId);
for (GroupEntity g : groupsToDelete) {
groupsDAO.deleteGroup(g);
}
loggingDAO.logAction("Group deleted, group_id=" + group.getId());
......
package it.inaf.ia2.gms.service.hook;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
public interface GroupsHook {
void beforeCreate(GroupEntity group);
void beforeUpdate(GroupEntity group);
void beforeDelete(GroupEntity group);
}
package it.inaf.ia2.gms;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
import it.inaf.ia2.gms.service.hook.GroupsHook;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HooksConfig {
@Bean
public GroupsHook groupsHook() {
return new GroupsHookTestImpl();
}
public static class GroupsHookTestImpl implements GroupsHook {
@Override
public void beforeCreate(GroupEntity group) {
}
@Override
public void beforeUpdate(GroupEntity group) {
}
@Override
public void beforeDelete(GroupEntity group) {
}
}
}
......@@ -151,7 +151,7 @@ public class JWTWebServiceControllerTest {
mockMvc.perform(delete("/ws/jwt/LBT.INAF"))
.andExpect(status().isNoContent());
verify(groupsDAO, times(1)).deleteGroupById(eq(inaf.getId()));
verify(groupsDAO, times(1)).deleteGroup(eq(inaf));
}
@Test
......
package it.inaf.ia2.gms.persistence;
import it.inaf.ia2.gms.DataSourceConfig;
import it.inaf.ia2.gms.HooksConfig;
import it.inaf.ia2.gms.model.GroupBreadcrumb;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
import it.inaf.ia2.gms.service.hook.GroupsHook;
import java.util.List;
import java.util.Map;
import java.util.Optional;
......@@ -14,23 +16,32 @@ import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.mockito.internal.util.collections.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = DataSourceConfig.class)
@ContextConfiguration(classes = {DataSourceConfig.class, HooksConfig.class})
public class GroupsDAOTest {
@Autowired
private DataSource dataSource;
@Autowired
@SpyBean
private GroupsHook groupsHook;
private GroupsDAO dao;
@Before
public void setUp() {
dao = new GroupsDAO(dataSource);
dao.groupsHook = groupsHook;
}
@Test
......@@ -43,6 +54,8 @@ public class GroupsDAOTest {
root.setPath("");
dao.createGroup(root);
verify(groupsHook, times(1)).beforeCreate(eq(root));
GroupEntity lbt = new GroupEntity();
lbt.setId(getNewGroupId());
lbt.setName("LBT");
......@@ -118,6 +131,8 @@ public class GroupsDAOTest {
tng = dao.findGroupById(tng.getId()).get();
assertEquals(newName, tng.getName());
verify(groupsHook, times(1)).beforeUpdate(eq(tng));
// Breadcrumbs
List<GroupBreadcrumb> breadcrumbs = dao.getBreadcrumbs(lbt.getId() + "." + lbtInaf.getId());
assertEquals(3, breadcrumbs.size());
......@@ -126,9 +141,11 @@ public class GroupsDAOTest {
assertEquals(lbtInaf.getName(), breadcrumbs.get(2).getGroupName());
// Delete
dao.deleteGroupById(lbtInaf.getId());
dao.deleteGroup(lbtInaf);
groups = dao.getDirectSubGroups(lbt.getId());
assertTrue(groups.isEmpty());
verify(groupsHook, times(1)).beforeDelete(eq(lbtInaf));
}
private String getNewGroupId() {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment