package it.inaf.ia2.gms.controller; import com.fasterxml.jackson.databind.ObjectMapper; import com.opencsv.CSVWriter; import it.inaf.ia2.gms.manager.GroupStatusManager; import it.inaf.ia2.gms.manager.GroupsManager; import it.inaf.ia2.gms.model.request.AddGroupRequest; import it.inaf.ia2.gms.model.GroupNode; import it.inaf.ia2.gms.model.response.PaginatedData; import it.inaf.ia2.gms.model.request.PaginatedModelRequest; import it.inaf.ia2.gms.model.request.DeleteGroupRequest; import it.inaf.ia2.gms.model.request.GroupsRequest; import it.inaf.ia2.gms.model.request.RenameGroupRequest; import it.inaf.ia2.gms.model.request.SearchFilterRequest; import it.inaf.ia2.gms.persistence.model.GroupEntity; import it.inaf.ia2.gms.service.GroupNameService; import it.inaf.ia2.gms.service.GroupsService; import it.inaf.ia2.gms.service.GroupsTreeBuilder; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.security.Principal; import java.util.List; import java.util.Optional; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class GroupsController { private static final ObjectMapper MAPPER = new ObjectMapper(); @Autowired private HttpServletRequest servletRequest; @Autowired private GroupsManager groupsManager; @Autowired private GroupsService groupsService; @Autowired private GroupsTreeBuilder groupsTreeBuilder; @Autowired private GroupsTabResponseBuilder groupsTabResponseBuilder; @Autowired private GroupStatusManager groupStatusManager; @Autowired protected GroupNameService groupNameService; @GetMapping(value = "/groups", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity getGroupsTab(@Valid GroupsRequest request) { if (request.isOnlyPanel()) { // Only groupsPanel GroupEntity group = groupsManager.getGroupById(request.getGroupId()); return ResponseEntity.ok(getGroupsPanel(group, request)); } else { // Complete GroupsTabResponse return ResponseEntity.ok(groupsTabResponseBuilder.getGroupsTab(request)); } } @PostMapping(value = "/group", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity> createGroup(@Valid @RequestBody AddGroupRequest request) { GroupEntity parent = groupsManager.getGroupById(request.getParentGroupId()); groupsManager.createGroup(parent, request.getNewGroupName(), request.isLeaf()); PaginatedData groupsPanel = getGroupsPanel(parent, request); return new ResponseEntity<>(groupsPanel, HttpStatus.CREATED); } @PutMapping(value = "/group/{groupId}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity> updateGroup(@PathVariable("groupId") String groupId, @Valid @RequestBody RenameGroupRequest request) { GroupEntity updatedGroup = groupsManager.updateGroup(groupId, request.getNewGroupName(), request.isLeaf()); GroupEntity parent = groupsManager.getGroupByPath(updatedGroup.getParentPath()); PaginatedData groupsPanel = getGroupsPanel(parent, request); return ResponseEntity.ok(groupsPanel); } @DeleteMapping(value = "/group/{groupId}", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity deleteGroup(@PathVariable("groupId") String groupId, DeleteGroupRequest request) { GroupEntity parent = groupsManager.deleteGroup(groupId); PaginatedData groupsPanel = getGroupsPanel(parent, request); return ResponseEntity.ok(groupsPanel); } @GetMapping(value = "/group/status", produces = {MediaType.APPLICATION_OCTET_STREAM_VALUE, MediaType.APPLICATION_JSON_VALUE}) public void downloadStatus(@RequestParam(value = "groupId", required = false) String groupId, @RequestParam(value = "groupName", required = false) String groupName, HttpServletRequest request, HttpServletResponse response) throws Exception { if (groupId == null && groupName == null) { response.sendError(400, "Parameter groupId or groupName is required"); return; } if (groupId == null) { GroupEntity group = groupNameService.getGroupFromNames(Optional.of(groupName)); groupId = group.getId(); } List status = groupStatusManager.generateStatus(groupId); try ( OutputStream out = response.getOutputStream()) { if ("application/json".equals(request.getHeader("Accept"))) { MAPPER.writeValue(out, status); } else { try ( CSVWriter writer = new CSVWriter(new OutputStreamWriter(out))) { writer.writeNext(new String[]{"program", "email"}); for (String[] row : status) { writer.writeNext(row); } } } } } private PaginatedData getGroupsPanel(GroupEntity parentGroup, T request) { return groupsTreeBuilder.listSubGroups(parentGroup, request, servletRequest.getUserPrincipal().getName()); } @GetMapping(value = "/groups", produces = MediaType.TEXT_PLAIN_VALUE) public void listChildGroups(@RequestParam("parent") Optional groupNames, @RequestParam(value = "recursive", defaultValue = "false") boolean recursive, Principal principal, HttpServletResponse response) throws IOException { GroupEntity parentGroup = groupNameService.getGroupFromNames(groupNames); List visibleSubgroups = groupsManager.getChildGroups(parentGroup, recursive); try ( PrintWriter pw = new PrintWriter(response.getOutputStream())) { for (String groupName : groupNameService.getGroupsNames(visibleSubgroups)) { pw.println(groupNameService.getShortGroupName(groupName, groupNames)); } } } /** * Creates a group and its ancestors if they are missing. It doesn't fail if * the last group already exists. For CLI/API usage. */ @PostMapping(value = "/group", produces = MediaType.TEXT_PLAIN_VALUE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) public void createGroup(@RequestParam("name") String groupParam, @RequestParam(value = "leaf", required = false, defaultValue = "false") boolean leaf, HttpServletResponse response) throws IOException { List groupNames = groupNameService.extractGroupNames(groupParam); GroupEntity group = groupsManager.getRoot(); for (int i = 0; i < groupNames.size(); i++) { String name = groupNames.get(i); Optional optGroup = groupsService.findGroupByParentAndName(group, name); if (optGroup.isPresent()) { group = optGroup.get(); } else { group = groupsManager.createGroup(group, name, i == groupNames.size() - 1 ? leaf : false); } } response.setStatus(HttpServletResponse.SC_CREATED); try ( PrintWriter pw = new PrintWriter(response.getOutputStream())) { pw.println(groupParam); } } @DeleteMapping(value = "/group", produces = MediaType.TEXT_PLAIN_VALUE) public ResponseEntity deleteGroup(@RequestParam("name") String groupParam) { GroupEntity group = groupNameService.getGroupFromNames(Optional.of(groupParam)); groupsManager.deleteGroup(group.getId()); return ResponseEntity.noContent().build(); } }