Skip to content
JWTWebServiceController.java 3.95 KiB
Newer Older
package it.inaf.ia2.gms.controller;

Sonia Zorba's avatar
Sonia Zorba committed
import it.inaf.ia2.gms.authn.RapPrincipal;
import it.inaf.ia2.gms.exception.BadRequestException;
import it.inaf.ia2.gms.persistence.GroupsDAO;
import it.inaf.ia2.gms.persistence.MembershipsDAO;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
Sonia Zorba's avatar
Sonia Zorba committed
import it.inaf.ia2.gms.service.JoinService;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
Sonia Zorba's avatar
Sonia Zorba committed
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
Sonia Zorba's avatar
Sonia Zorba committed
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Web service called by other web applications using JWT (delegation).
 */
@RestController
@RequestMapping("/ws/jwt")
public class JWTWebServiceController {

    @Autowired
    private MembershipsDAO membershipsDAO;

Sonia Zorba's avatar
Sonia Zorba committed
    @Autowired
    private JoinService joinService;

    @Autowired
    private GroupsDAO groupsDAO;

    /**
     * This endpoint is compliant with the IVOA GMS standard.
     */
    @GetMapping(value = "/search", produces = MediaType.TEXT_PLAIN_VALUE)
    public void getGroups(Principal principal, HttpServletResponse response) throws IOException {

        List<GroupEntity> memberships = membershipsDAO.getUserMemberships(principal.getName());

        // We need to return the complete group name, so it is necessary to load
        // all the parents too.
        Map<String, String> idNameMap = new HashMap<>();
        Set<String> allIdentifiers = getAllIdentifiers(memberships);
        for (GroupEntity group : groupsDAO.findGroupsByIds(allIdentifiers)) {
            idNameMap.put(group.getId(), group.getName());
        }

        try (PrintWriter pw = new PrintWriter(response.getOutputStream())) {

            for (GroupEntity group : memberships) {
                pw.println(getGroupCompleteName(group, idNameMap));
            }
        }
    }

    private Set<String> getAllIdentifiers(List<GroupEntity> groups) {

        Set<String> allIdentifiers = new HashSet<>();
        for (GroupEntity group : groups) {
            if (!"".equals(group.getPath())) {
                String[] ids = group.getPath().split("\\.");
                for (String id : ids) {
                    allIdentifiers.add(id);
                }
            }
        }

        return allIdentifiers;
    }

    private String getGroupCompleteName(GroupEntity group, Map<String, String> idNameMap) {

Sonia Zorba's avatar
Sonia Zorba committed
        if ("ROOT".equals(group.getId())) {
            return group.getName();
        }

        List<String> names = new ArrayList<>();

        for (String groupId : group.getPath().split("\\.")) {

            String groupName = idNameMap.get(groupId);

            // Dot inside names is considered a special character (because it is
            // used to separate the group from its parents), so we use a
            // backslash to escape it (client apps need to be aware of this).
            groupName = groupName.replace("\\.", "\\\\.");

            names.add(groupName);
        }

        return String.join(".", names);
    }
Sonia Zorba's avatar
Sonia Zorba committed

    @PostMapping(value = "/join", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<?> join(RapPrincipal principal) {

        String fromUser = principal.getName();
        String toUser = principal.getAlternativeName();

        if (toUser == null) {
            throw new BadRequestException("Missing alternative subject");
        }

        joinService.join(fromUser, toUser);

        Map<String, String> responseBody = new HashMap<>();
        responseBody.put("mergedId", fromUser);
        return ResponseEntity.ok(responseBody);
    }