Skip to content

Commit

Permalink
feat: search for admins by query
Browse files Browse the repository at this point in the history
  • Loading branch information
idriss.naji committed Nov 29, 2022
1 parent 0300c30 commit 4fd6322
Show file tree
Hide file tree
Showing 17 changed files with 639 additions and 83 deletions.
64 changes: 64 additions & 0 deletions api/useradminservice.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,68 @@ paths:
description: INTERNAL SERVER ERROR - server encountered unexpected condition
security:
- Bearer: [ ]

/useradmin/agencyadmins/search:
get:
tags:
- admin-user-controller
summary: 'Get Agency admins matching the given query [Auth: user-admin]'
operationId: searchAgencyAdmins
parameters:
- name: query
in: query
description: URL-encoded infix to search for in first name, last name, or email.
A non-encoded star symbol searches for all.
required: true
schema:
type: string
minLength: 1
- name: page
in: query
description: Page number (first page = 1)
schema:
type: integer
default: 1
minimum: 1
- name: perPage
in: query
description: Number of items returned per page
schema:
type: integer
default: 10
minimum: 1
- name: field
in: query
description: field to sort by
schema:
type: string
enum: [ FIRSTNAME, LASTNAME, EMAIL ]
default: FIRSTNAME
pattern: '^(FIRSTNAME|LASTNAME|EMAIL)$'
- name: order
in: query
description: sort order
schema:
type: string
enum: [ ASC, DESC ]
default: ASC
pattern: '^(ASC|DESC)$'
responses:
200:
description: OK - successful operation
content:
'application/hal+json':
schema:
$ref: '#/components/schemas/AgencyAdminSearchResultDTO'
400:
description: BAD REQUEST - invalid/incomplete request or body object
401:
description: UNAUTHORIZED - no/invalid role/authorization
500:
description: INTERNAL SERVER ERROR - server encountered unexpected condition
security:
- Bearer: [ ]

/useradmin/agencyadmins/{adminId}:
get:
tags:
Expand Down Expand Up @@ -1181,6 +1243,8 @@ components:
$ref: '#/components/schemas/HalLink'
agencies:
$ref: '#/components/schemas/HalLink'
addAgency:
$ref: '#/components/schemas/HalLink'

SessionFilter:
type: object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import com.neovisionaries.i18n.LanguageCode;
import de.caritas.cob.userservice.api.adapters.web.dto.AgencyDTO;
import de.caritas.cob.userservice.api.helper.UsernameTranscoder;
import de.caritas.cob.userservice.api.model.Admin;
import de.caritas.cob.userservice.api.model.Admin.AdminBase;
import de.caritas.cob.userservice.api.model.AdminAgency.AdminAgencyBase;
import de.caritas.cob.userservice.api.model.Appointment;
import de.caritas.cob.userservice.api.model.Appointment.AppointmentStatus;
import de.caritas.cob.userservice.api.model.Consultant;
Expand Down Expand Up @@ -121,6 +124,40 @@ public Map<String, Object> mapOf(
consultants);
}

public Map<String, Object> mapOfAdmin(
Page<AdminBase> adminsPage,
List<Admin> fullAdmins,
List<AgencyDTO> agencyDTOs,
List<AdminAgencyBase> agenciesOfAdmin) {
var agencyLookupMap =
agencyDTOs.stream().collect(Collectors.toMap(AgencyDTO::getId, Function.identity()));

var fullAdminLookupMap =
fullAdmins.stream().collect(Collectors.toMap(Admin::getId, Function.identity()));

var adminAgencyLookupMap =
agenciesOfAdmin.stream().collect(Collectors.groupingBy(AdminAgencyBase::getAdminId));

var admins = new ArrayList<Map<String, Object>>();
adminsPage.forEach(
adminBase -> {
var fullAdmin = fullAdminLookupMap.get(adminBase.getId());
var agencies = mapOfAdmin(fullAdmin, agencyLookupMap, adminAgencyLookupMap);
var consultantMap = mapOfAdmin(adminBase, fullAdmin, agencies);
admins.add(consultantMap);
});

return Map.of(
"totalElements",
(int) adminsPage.getTotalElements(),
"isFirstPage",
adminsPage.isFirst(),
"isLastPage",
adminsPage.isLast(),
"admins",
admins);
}

private List<Map<String, Object>> mapOf(
Consultant consultant,
Map<Long, AgencyDTO> agencyLookupMap,
Expand All @@ -147,6 +184,31 @@ && isAgencyUnique(agencyIdsAdded, agencyId)) {
return agencies;
}

private List<Map<String, Object>> mapOfAdmin(
Admin admin,
Map<Long, AgencyDTO> agencyLookupMap,
Map<String, List<AdminAgencyBase>> aaLookupMap) {
var agencies = new ArrayList<Map<String, Object>>();
var agencyIdsAdded = new HashSet<Long>();

if (aaLookupMap.containsKey(admin.getId())) {
aaLookupMap
.get(admin.getId())
.forEach(
adminAgency -> {
var agencyId = adminAgency.getAgencyId();
if (agencyLookupMap.containsKey(agencyId)
&& isAgencyUnique(agencyIdsAdded, agencyId)) {
var agencyDTO = agencyLookupMap.get(agencyId);
agencies.add(mapOf(agencyDTO));
agencyIdsAdded.add(agencyId);
}
});
}

return agencies;
}

private Map<String, Object> mapOf(AgencyDTO agencyDTO) {
Map<String, Object> agencyMap = new HashMap<>();
agencyMap.put("id", agencyDTO.getId());
Expand Down Expand Up @@ -195,6 +257,26 @@ public Map<String, Object> mapOf(
return map;
}

public Map<String, Object> mapOfAdmin(
AdminBase adminBase, Admin fullAdmin, List<Map<String, Object>> agencies) {

Map<String, Object> map = new HashMap<>();
map.put("id", adminBase.getId());
map.put("email", adminBase.getEmail());
map.put("firstName", adminBase.getFirstName());
map.put("lastName", adminBase.getLastName());
map.put("username", fullAdmin.getUsername());
map.put(
"createdAt",
nonNull(fullAdmin.getCreateDate()) ? fullAdmin.getCreateDate().toString() : null);
map.put(
"updatedAt",
nonNull(fullAdmin.getUpdateDate()) ? fullAdmin.getUpdateDate().toString() : null);
map.put("agencies", agencies);

return map;
}

public Optional<Map<String, String>> mapOf(Optional<Session> optionalSession) {
if (optionalSession.isEmpty()) {
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,19 @@
import de.caritas.cob.userservice.api.adapters.web.dto.UpdateAdminConsultantDTO;
import de.caritas.cob.userservice.api.adapters.web.dto.UpdateAgencyAdminDTO;
import de.caritas.cob.userservice.api.adapters.web.dto.ViolationDTO;
import de.caritas.cob.userservice.api.adapters.web.mapping.AdminAgencyDtoMapper;
import de.caritas.cob.userservice.api.admin.facade.AdminAgencyFacade;
import de.caritas.cob.userservice.api.admin.facade.ConsultantAdminFacade;
import de.caritas.cob.userservice.api.admin.facade.UserAdminFacade;
import de.caritas.cob.userservice.api.admin.hallink.RootDTOBuilder;
import de.caritas.cob.userservice.api.admin.report.service.ViolationReportGenerator;
import de.caritas.cob.userservice.api.admin.service.session.SessionAdminService;
import de.caritas.cob.userservice.api.helper.AuthenticatedUser;
import de.caritas.cob.userservice.api.service.appointment.AppointmentService;
import de.caritas.cob.userservice.generated.api.adapters.web.controller.UseradminApi;
import io.swagger.annotations.Api;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import javax.validation.Valid;
Expand All @@ -53,6 +57,8 @@ public class UserAdminController implements UseradminApi {
private final @NonNull UserAdminFacade userAdminFacade;
private final @NonNull AdminAgencyFacade adminAgencyFacade;
private final @NonNull AppointmentService appointmentService;
private final @NonNull AdminAgencyDtoMapper adminAgencyDtoMapper;
private final @NotNull AuthenticatedUser authenticatedUser;

/**
* Creates the root hal based navigation entity.
Expand Down Expand Up @@ -317,4 +323,25 @@ public ResponseEntity<Void> setAdminAgenciesRelation(
this.adminAgencyFacade.setAdminAgenciesRelation(adminId, newAdminAgencyRelationDTOs);
return new ResponseEntity<>(HttpStatus.OK);
}

@Override
public ResponseEntity<AgencyAdminSearchResultDTO> searchAgencyAdmins(
String query, Integer page, Integer perPage, String field, String order) {
var decodedInfix = URLDecoder.decode(query, StandardCharsets.UTF_8).trim();
var isAscending = order.equalsIgnoreCase("asc");
var mappedField = adminAgencyDtoMapper.mappedFieldOf(field);
var resultMap =
adminAgencyFacade.findAgencyAdminsByInfix(
decodedInfix,
authenticatedUser.getUserId(),
page - 1,
perPage,
mappedField,
isAscending);
var result =
adminAgencyDtoMapper.agencyAdminSearchResultOf(
resultMap, query, page, perPage, field, order);

return ResponseEntity.ok(result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package de.caritas.cob.userservice.api.adapters.web.mapping;

import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;

import de.caritas.cob.userservice.api.adapters.web.controller.UserAdminController;
import de.caritas.cob.userservice.api.adapters.web.dto.AdminDTO;
import de.caritas.cob.userservice.api.adapters.web.dto.AdminLinks;
import de.caritas.cob.userservice.api.adapters.web.dto.AdminResponseDTO;
import de.caritas.cob.userservice.api.adapters.web.dto.AgencyAdminResponseDTO;
import de.caritas.cob.userservice.api.adapters.web.dto.AgencyAdminSearchResultDTO;
import de.caritas.cob.userservice.api.adapters.web.dto.HalLink;
import de.caritas.cob.userservice.api.adapters.web.dto.HalLink.MethodEnum;
import de.caritas.cob.userservice.api.adapters.web.dto.PaginationLinks;
import de.caritas.cob.userservice.generated.api.adapters.web.controller.UseradminApi;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Service;

@Service
public class AdminAgencyDtoMapper implements DtoMapperUtils {

public AgencyAdminSearchResultDTO agencyAdminSearchResultOf(
Map<String, Object> resultMap,
String query,
Integer page,
Integer perPage,
String field,
String order) {
var admins = new ArrayList<AdminResponseDTO>();

var adminMaps = (List<Map<String, Object>>) resultMap.get("admins");
adminMaps.forEach(
adminMap -> {
var response = new AdminResponseDTO();
response.setEmbedded(adminDtoOf(adminMap));
response.setLinks(consultantLinksOf(adminMap));
admins.add(response);
});

var result = new AgencyAdminSearchResultDTO();
result.setTotal((Integer) resultMap.get("totalElements"));
result.setEmbedded(admins);

var pagination = new PaginationLinks().self(pageLinkOf(query, page, perPage, field, order));
if (!(boolean) resultMap.get("isFirstPage")) {
pagination.previous(pageLinkOf(query, page - 1, perPage, field, order));
}
if (!(boolean) resultMap.get("isLastPage")) {
pagination.next(pageLinkOf(query, page + 1, perPage, field, order));
}
result.setLinks(pagination);

return result;
}

public AdminLinks consultantLinksOf(Map<String, Object> adminMap) {
var id = (String) adminMap.get("id");

return new AdminLinks()
.self(adminLinkOf(id, MethodEnum.GET))
.update(adminLinkOf(id, MethodEnum.PUT))
.delete(adminLinkOf(id, MethodEnum.DELETE))
.agencies(adminAgencyLinkOf(id, MethodEnum.GET))
.addAgency(adminAgencyLinkOf(id, MethodEnum.POST));
}

public HalLink adminAgencyLinkOf(String id, MethodEnum method) {
var userAdminApi = methodOn(UseradminApi.class);
HttpEntity<?> httpEntity;
if (method == MethodEnum.POST) {
httpEntity = userAdminApi.createAdminAgencyRelation(id, null);
} else {
httpEntity = userAdminApi.getAdminAgencies(id);
}

return halLinkOf(httpEntity, method);
}

private HalLink pageLinkOf(String query, int page, int perPage, String field, String order) {
var httpEntity =
methodOn(UserAdminController.class).searchAgencyAdmins(query, page, perPage, field, order);

return halLinkOf(httpEntity, MethodEnum.GET);
}

public HalLink adminLinkOf(String id, MethodEnum method) {
var userAdminApi = methodOn(UseradminApi.class);
HttpEntity<?> httpEntity;
switch (method) {
case PUT:
httpEntity = userAdminApi.updateAgencyAdmin(id, null);
break;
case DELETE:
httpEntity = userAdminApi.deleteAgencyAdmin(id);
break;
default:
httpEntity = userAdminApi.getAgencyAdmin(id);
}

return halLinkOf(httpEntity, method);
}

private AdminDTO adminDtoOf(Map<String, Object> consultantMap) {
var adminDTO = new AdminDTO();
adminDTO.setId((String) consultantMap.get("id"));
adminDTO.setEmail((String) consultantMap.get("email"));
adminDTO.setFirstname((String) consultantMap.get("firstName"));
adminDTO.setLastname((String) consultantMap.get("lastName"));
adminDTO.setUsername((String) consultantMap.get("username"));
adminDTO.setCreateDate((String) consultantMap.get("createdAt"));
adminDTO.setUpdateDate((String) consultantMap.get("updatedAt"));

var agencies = new ArrayList<AgencyAdminResponseDTO>();
var agencyMaps = (ArrayList<Map<String, Object>>) consultantMap.get("agencies");
agencyMaps.forEach(
agencyMap -> {
var agency = new AgencyAdminResponseDTO();
agency.setId((Long) agencyMap.get("id"));
agency.setName((String) agencyMap.get("name"));
agency.setPostcode((String) agencyMap.get("postcode"));
agency.setCity((String) agencyMap.get("city"));
agency.setDescription((String) agencyMap.get("description"));
agency.setTeamAgency((Boolean) agencyMap.get("isTeamAgency"));
agency.setOffline((Boolean) agencyMap.get("isOffline"));
agency.setConsultingType((Integer) agencyMap.get("consultingType"));
agencies.add(agency);
});
adminDTO.setAgencies(agencies);

return adminDTO;
}
}
Loading

0 comments on commit 4fd6322

Please sign in to comment.