ResourceController.java
package no.nav.data.team.resource;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import no.nav.data.common.exceptions.ValidationException;
import no.nav.data.common.rest.RestResponsePage;
import no.nav.data.common.security.SecurityUtils;
import no.nav.data.common.validator.Validator;
import no.nav.data.team.resource.domain.Resource;
import no.nav.data.team.resource.dto.ResourceResponse;
import no.nav.data.team.resource.dto.ResourceUnitsResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toList;
@Slf4j
@RestController
@RequestMapping("/resource")
@Tag(name = "Resource")
public class ResourceController {
private final NomClient nomClient;
private final NomGraphClient nomGraphClient;
private final NomAzurePictureService nomAzurePictureService;
private final SecurityUtils securityUtils;
public ResourceController(NomClient nomClient, NomGraphClient nomGraphClient, NomAzurePictureService nomAzurePictureService, SecurityUtils securityUtils) {
this.nomClient = nomClient;
this.nomGraphClient = nomGraphClient;
this.nomAzurePictureService = nomAzurePictureService;
this.securityUtils = securityUtils;
}
@Operation(summary = "Search resources")
@ApiResponse(description = "Resources fetched")
@GetMapping("/search/{name}")
public ResponseEntity<RestResponsePage<ResourceResponse>> searchResourceName(@PathVariable String name) {
log.debug("Resource search '{}'", name);
if (Stream.of(name.split(" ")).sorted().distinct().collect(Collectors.joining("")).length() < 3) {
throw new ValidationException("Search resource must be at least 3 characters");
}
var navidentSearchlist = nomGraphClient.searchForNavidentByName(name);
var ressurserStream = navidentSearchlist.stream().map(nomClient::getByNavIdent).filter(Optional::isPresent).map(Optional::get);
var ressursSearchlist = ressurserStream.map(Resource::convertToResponse).toList();
var responsePage = new RestResponsePage<>(ressursSearchlist, ressursSearchlist.size());
return new ResponseEntity<>(responsePage, HttpStatus.OK);
}
@Operation(summary = "Get Resource")
@ApiResponse(description = "ok")
@GetMapping("/{id}")
public ResponseEntity<ResourceResponse> getById(@PathVariable String id) {
log.info("Resource get id={}", id);
var resource = nomClient.getByNavIdent(id);
return resource.map(value -> ResponseEntity.ok(value.convertToResponse())).orElseGet(() -> ResponseEntity.notFound().build());
}
@Operation(summary = "Get Resource Units", description = "Only for team-catalog-frackend")
@ApiResponse(description = "ok")
@GetMapping("/{id}/units")
public ResponseEntity<ResourceUnitsResponse> getUnitsById(@PathVariable String id) {
securityUtils.assertAuthIsPermittedApp("org","team-catalog-frackend");
log.info("Resource get units id={}", id);
try {
var units = nomGraphClient.getUnits(id);
return units.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
} catch (Exception e) {
log.error("Failed to get units for " + id, e);
return ResponseEntity.ok(null);
}
}
@Operation(summary = "Get all underlying Ressurser Units for leader", description = "Only for team-catalog-frackend")
@ApiResponse(description = "OK")
@GetMapping("/{id}/all-underlying-units")
public ResponseEntity<ResourceUnitsResponse> allUnderlyingUnits(@PathVariable String id, @RequestParam boolean includeMembers) {
securityUtils.assertAuthIsPermittedApp("org","team-catalog-frackend");
try {
var units = nomGraphClient.getLeaderMembersActiveOnlyV2(id, includeMembers);
return units.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
} catch (Exception e) {
log.error("Failed to get units for leader", e);
return ResponseEntity.ok(null);
}
}
@Operation(summary = "Get Resources")
@ApiResponse(description = "ok")
@PostMapping("/multi")
public ResponseEntity<RestResponsePage<ResourceResponse>> getById(@RequestBody List<String> ids) {
log.info("Resource get ids={}", ids);
var resources = ids.stream()
.map(nomClient::getByNavIdent)
.filter(Optional::isPresent)
.map(Optional::get)
.map(Resource::convertToResponse)
.collect(toList());
return ResponseEntity.ok(new RestResponsePage<>(resources));
}
@Operation(summary = "Get Resource Photo")
@ApiResponse(description = "ok")
@GetMapping(value = "/{id}/photo", produces = MediaType.IMAGE_JPEG_VALUE)
public ResponseEntity<byte[]> getPhoto(
@PathVariable String id,
@RequestParam(name = "forceUpdate", required = false, defaultValue = "false") boolean forceUpdate
) {
id = StringUtils.upperCase(id);
if (!Validator.NAV_IDENT_PATTERN.matcher(id).matches()) {
log.info("Resource get photo id={} invalid id", id);
return ResponseEntity.notFound().build();
}
var photo = nomAzurePictureService.getPhoto(id, forceUpdate);
if (photo.isEmpty()) {
log.info("Resource get photo id={} not found", id);
return ResponseEntity.notFound().build();
}
log.info("Resource get photo id={}", id);
return ResponseEntity.ok(photo.get());
}
static class ResourcePageResponse extends RestResponsePage<ResourceResponse> {
}
}