Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Experimentation] Added very basic functionality related to foreign experts #436

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import static com.softserveinc.dokazovi.controller.EndPoints.DIRECTION;
import static com.softserveinc.dokazovi.controller.EndPoints.FOREIGN_EXPERT;
import static com.softserveinc.dokazovi.controller.EndPoints.ORIGIN;
import static com.softserveinc.dokazovi.controller.EndPoints.PLATFORM_INFORMATION;
import static com.softserveinc.dokazovi.controller.EndPoints.POST;
Expand Down Expand Up @@ -117,7 +118,8 @@ protected void configure(HttpSecurity http) throws Exception {
"/auth/**", "/oauth2/**")
.permitAll()
.antMatchers(openApi(USER), openApi(POST), openApi(TAG), openApi(DIRECTION), openApi(REGION),
openApi(VERSION), openApi(POST_TYPES), openApi(ORIGIN), openApi(PLATFORM_INFORMATION))
openApi(VERSION), openApi(POST_TYPES), openApi(ORIGIN), openApi(PLATFORM_INFORMATION),
openApi(FOREIGN_EXPERT))
.permitAll()
.anyRequest()
.authenticated()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public final class EndPoints {
public static final String POST_LATEST_BY_DIRECTION = "/latest-by-direction";
public static final String POST_LATEST_BY_EXPERT = "/latest-by-expert";
public static final String POST_LATEST_BY_EXPERT_AND_STATUS = "/latest-by-expert-and-status";
public static final String POST_LATEST_TRANSLATION_BY_EXPERT = "/latest-translation-by-expert";
public static final String POST_LATEST_TRANSLATION_BY_EXPERT_AND_STATUS = "/latest-translation-by-expert-and-status";
public static final String POST_VIEW_COUNT = "/post-view-count";
public static final String DIRECTION = "/direction";
public static final String ORIGIN = "/origin";
Expand All @@ -48,6 +50,8 @@ public final class EndPoints {
public static final String PLATFORM_INFORMATION = "/platform-information";
public static final String PLATFORM_INFORMATION_BY_ID = "/{infoId}";
public static final String POST_GET_BY_IMPORTANT_IMAGE = "/get-by-important-image";
public static final String FOREIGN_EXPERT = "/foreign-expert";
public static final String FOREIGN_EXPERT_SEARCH = "/search";

/**
* Method that adds slash after each endpoint while calling
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.softserveinc.dokazovi.controller;

import com.softserveinc.dokazovi.annotations.ApiPageable;
import com.softserveinc.dokazovi.dto.foreignexpert.ForeignExpertDTO;
import com.softserveinc.dokazovi.dto.foreignexpert.ForeignExpertSaveDTO;
import com.softserveinc.dokazovi.dto.foreignexpert.ForeignExpertSearchResultDTO;
import com.softserveinc.dokazovi.security.UserPrincipal;
import com.softserveinc.dokazovi.service.ForeignExpertService;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
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 javax.validation.Valid;

@RestController
@RequestMapping(EndPoints.FOREIGN_EXPERT)
@RequiredArgsConstructor
public class ForeignExpertController {
private final ForeignExpertService foreignExpertService;

/**
* Saves (creates) a foreign expert entry.
*
* <p>Checks if user has authority to perform the request</p>
* @param saveDTO DTO of the foreign expert
* @param userPrincipal authorized user data
*
* @return HttpStatus 'CREATED' and saves the foreign expert entry to the DB
*/
@PostMapping
@PreAuthorize("hasAuthority('SAVE_FOREIGN_EXPERT')")
@ApiOperation(value = "Save a foreign expert", authorizations = {@Authorization(value = "Authorization")})
@ApiResponses(value = {
@ApiResponse(code = 201, message = HttpStatuses.CREATED, response = ForeignExpertDTO.class),
@ApiResponse(code = 400, message = HttpStatuses.BAD_REQUEST)
})
public ResponseEntity<ForeignExpertDTO> save(
@Valid @RequestBody ForeignExpertSaveDTO saveDTO,
@AuthenticationPrincipal UserPrincipal userPrincipal
) {
return ResponseEntity
.status(HttpStatus.CREATED)
.body(foreignExpertService.save(saveDTO, userPrincipal));
}

@GetMapping(EndPoints.FOREIGN_EXPERT_SEARCH)
@ApiOperation(value = "Search for foreign experts")
@ApiPageable()
public ResponseEntity<Page<ForeignExpertSearchResultDTO>> search(
@RequestParam String query,
@PageableDefault(sort = {"full_name"}, direction = Sort.Direction.ASC)
Pageable pageable
) {
return ResponseEntity
.status(HttpStatus.OK)
.body(foreignExpertService.search(query, pageable));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
import static com.softserveinc.dokazovi.controller.EndPoints.POST_LATEST_BY_EXPERT;
import static com.softserveinc.dokazovi.controller.EndPoints.POST_LATEST_BY_EXPERT_AND_STATUS;
import static com.softserveinc.dokazovi.controller.EndPoints.POST_LATEST_BY_POST_TYPES_AND_ORIGINS;
import static com.softserveinc.dokazovi.controller.EndPoints.POST_LATEST_TRANSLATION_BY_EXPERT;
import static com.softserveinc.dokazovi.controller.EndPoints.POST_LATEST_TRANSLATION_BY_EXPERT_AND_STATUS;
import static com.softserveinc.dokazovi.controller.EndPoints.POST_SET_IMPORTANT;
import static com.softserveinc.dokazovi.controller.EndPoints.POST_TYPE;
import static com.softserveinc.dokazovi.controller.EndPoints.POST_VIEW_COUNT;
Expand Down Expand Up @@ -188,7 +190,8 @@ public ResponseEntity<Page<PostDTO>> findLatestByExpert(
@ApiParam(value = "Post type id")
@RequestParam(required = false) Set<Integer> type,
@ApiParam(value = "Direction id")
@RequestParam(required = false) Set<Integer> direction) {
@RequestParam(required = false) Set<Integer> direction
) {
return ResponseEntity
.status(HttpStatus.OK)
.body(postService.findAllByExpertAndTypeAndDirections(expert, type, direction, pageable));
Expand Down Expand Up @@ -218,6 +221,55 @@ public ResponseEntity<Page<PostDTO>> findLatestByExpert(
.body(postService.findAllByExpertAndTypeAndStatus(expert, types, status, pageable));
}

/**
* Finds post by foreign expert id, type and status
*
* @param pageable interface for pagination information
* @param expert foreign expert id
* @param types the type's ids by which the search is performed
* @return page with found posts and HttpStatus 'OK'
*/
@GetMapping(POST_LATEST_TRANSLATION_BY_EXPERT_AND_STATUS)
@ApiPageable
@ApiOperation(value = "Find latest posts by some foreign expert and status")
public ResponseEntity<Page<PostDTO>> findLatestTranslationByExpert(
@PageableDefault Pageable pageable,
@ApiParam(value = "Foreign expert's id")
@RequestParam Integer expert,
@ApiParam(value = "Multiple comma-separated post types IDs, e.g. ?types=1,2,3,4", type = "string")
@RequestParam(required = false) Set<Integer> types,
@ApiParam(value = "Status")
@RequestParam PostStatus status) {
return ResponseEntity
.status(HttpStatus.OK)
.body(postService.findAllTranslationsByExpertAndTypeAndStatus(expert, types, status, pageable));
}

/**
* findLatestByExpert method returns latest post by foreign expert id.
*
* @param pageable interface for pagination information
* @param expert foreign expert id
* @param type post type id
* @return page with found posts and HttpStatus 'OK'
*/
@GetMapping(POST_LATEST_TRANSLATION_BY_EXPERT)
@ApiPageable
@ApiOperation(value = "Find latest posts by some foreign expert")
public ResponseEntity<Page<PostDTO>> findLatestTranslationByExpert(
@PageableDefault Pageable pageable,
@ApiParam(value = "Foreign expert's id")
@RequestParam Integer expert,
@ApiParam(value = "Post type id")
@RequestParam(required = false) Set<Integer> type,
@ApiParam(value = "Direction id")
@RequestParam(required = false) Set<Integer> direction
) {
return ResponseEntity
.status(HttpStatus.OK)
.body(postService.findAllTranslationsByExpertAndTypeAndDirections(expert, type, direction, pageable));
}

/**
* Gets all post types from db.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.softserveinc.dokazovi.dto.foreignexpert;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ForeignExpertDTO {
private Integer id;
private String fullName;
private String bio;
private String avatar;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.softserveinc.dokazovi.dto.foreignexpert;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotBlank;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ForeignExpertSaveDTO {
private Integer id;

@NotBlank(message = "Full name must be present")
private String fullName;

private String bio;

private String avatar;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.softserveinc.dokazovi.dto.foreignexpert;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ForeignExpertSearchResultDTO {
private Integer id;

private String fullName;

private String avatar;
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ public class PostDTO {
private Timestamp publishedAt;
private Integer importanceOrder;
private String importantImageUrl;
private Integer foreignAuthorId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.softserveinc.dokazovi.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "foreign_expert_entity")
@Table(name = "foreign_experts")
public class ForeignExpertEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "foreign_expert_id")
private Integer id;

@Column(name = "full_name")
private String fullName;

@Column(name = "bio")
private String bio;

@Column(name = "avatar")
private String avatar;
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,8 @@ public class PostEntity {

@Column(name = "important_image_url")
private String importantImageUrl;

@ManyToOne(cascade = {CascadeType.REFRESH, CascadeType.MERGE})
@JoinColumn(name = "foreign_expert_id")
private ForeignExpertEntity foreignAuthor;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ public enum RolePermission implements GrantedAuthority {
SAVE_PUBLICATION,
SET_IMPORTANCE,
SAVE_PLATFORM_INFORMATION,
UPDATE_PLATFORM_INFORMATION;
UPDATE_PLATFORM_INFORMATION,
SAVE_FOREIGN_EXPERT;

@Override
public String getAuthority() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.softserveinc.dokazovi.mapper;

import com.softserveinc.dokazovi.dto.foreignexpert.ForeignExpertDTO;
import com.softserveinc.dokazovi.dto.foreignexpert.ForeignExpertSaveDTO;
import com.softserveinc.dokazovi.dto.foreignexpert.ForeignExpertSearchResultDTO;
import com.softserveinc.dokazovi.entity.ForeignExpertEntity;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.ReportingPolicy;

@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface ForeignExpertMapper {
ForeignExpertDTO toForeignExpertDTO(ForeignExpertEntity entity);

ForeignExpertEntity toForeignExpertEntity(ForeignExpertSearchResultDTO saveDTO);

ForeignExpertEntity toForeignExpertEntity(ForeignExpertSaveDTO saveDTO);

ForeignExpertEntity updateForeignExpertEntityFromDTO(
ForeignExpertSearchResultDTO saveDTO,
@MappingTarget ForeignExpertEntity entity
);

ForeignExpertEntity updateForeignExpertEntityFromDTO(
ForeignExpertSaveDTO saveDTO,
@MappingTarget ForeignExpertEntity entity
);

ForeignExpertSearchResultDTO toForeignExpertSearchResultDTO(ForeignExpertEntity entity);
}
15 changes: 14 additions & 1 deletion src/main/java/com/softserveinc/dokazovi/mapper/PostMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,20 @@ public interface PostMapper {

@Mapping(target = "author.mainInstitution", source = "author.doctor.mainInstitution")
@Mapping(target = "author.bio", source = "author.doctor.bio")
PostDTO toPostDTO(PostEntity postEntity);
PostDTO simpleToPostDTO(PostEntity postEntity);

@Mapping(target = "author.firstName", source = "foreignAuthor.fullName")
@Mapping(target = "author.bio", source = "foreignAuthor.bio")
@Mapping(target = "author.avatar", source = "foreignAuthor.avatar")
@Mapping(target = "foreignAuthorId", source = "foreignAuthor.id")
PostDTO translationToPostDTO(PostEntity postEntity);

default PostDTO toPostDTO(PostEntity postEntity) {
if (postEntity.getForeignAuthor() != null) {
return translationToPostDTO(postEntity);
}
return simpleToPostDTO(postEntity);
}

PostEntity toPostEntity(PostSaveFromUserDTO postSaveFromUserDTO);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.softserveinc.dokazovi.repositories;

import com.softserveinc.dokazovi.entity.ForeignExpertEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface ForeignExpertRepository extends JpaRepository<ForeignExpertEntity, Integer> {
@Query(
nativeQuery = true,
value = "SELECT e.* FROM FOREIGN_EXPERTS e " +
"WHERE e.full_name LIKE :searchQuery || '%'",
countQuery = "SELECT count(*) FROM FOREIGN_EXPERTS " +
"WHERE full_name LIKE :searchQuery || '%'"
)
Page<ForeignExpertEntity> searchByFullName(String searchQuery, Pageable pageable);
}
Loading