diff --git a/pom.xml b/pom.xml index 21dd489..54591a1 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,6 @@ 17 - org.springdoc @@ -98,7 +97,6 @@ 4.21.1 - @@ -133,5 +131,4 @@ - - + \ No newline at end of file diff --git a/src/main/java/com/provedcode/ProvedCodeApplication.java b/src/main/java/com/provedcode/ProvedCodeApplication.java index 78360e0..58b471f 100644 --- a/src/main/java/com/provedcode/ProvedCodeApplication.java +++ b/src/main/java/com/provedcode/ProvedCodeApplication.java @@ -3,13 +3,13 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @ConfigurationPropertiesScan +@EnableScheduling public class ProvedCodeApplication { - public static void main(String[] args) { SpringApplication.run(ProvedCodeApplication.class, args); } - -} +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java index 64141d0..926e991 100644 --- a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java +++ b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java @@ -1,12 +1,16 @@ package com.provedcode.aws.controller; import com.provedcode.aws.service.FileService; +import com.provedcode.util.annotations.doc.controller.aws.GetAllAWSBucketFilesDevApiDoc; +import com.provedcode.util.annotations.doc.controller.aws.GetFileInfoDevApiDoc; +import com.provedcode.util.annotations.doc.controller.aws.PostSetNewUserImageApiDoc; import lombok.AllArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import java.util.Arrays; import java.util.List; @RestController @@ -15,6 +19,7 @@ public class AWSS3BucketController { FileService fileService; + @PostSetNewUserImageApiDoc @PreAuthorize("hasRole('TALENT')") @PostMapping("/image/upload") public void setNewUserImage(@RequestParam("file") MultipartFile file, @@ -22,9 +27,19 @@ public void setNewUserImage(@RequestParam("file") MultipartFile file, fileService.setNewUserImage(file, authentication); } + @GetAllAWSBucketFilesDevApiDoc @PreAuthorize("hasRole('TALENT')") @GetMapping("/files") List getAllFiles() { return fileService.listAllFiles(); } + + @GetFileInfoDevApiDoc + @PreAuthorize("hasRole('TALENT')") + @PostMapping("/aws/test-of-filetype") + String testTypeOfFile(@RequestParam("file") MultipartFile file, + Authentication authentication) { + return Arrays.stream(file.getContentType().split("/")).toList().get(1) + " " + file.getOriginalFilename() + + " " + file.getName() + " " + file.getResource(); + } } diff --git a/src/main/java/com/provedcode/aws/scheduler/UpdateScheduler.java b/src/main/java/com/provedcode/aws/scheduler/UpdateScheduler.java new file mode 100644 index 0000000..c9988dc --- /dev/null +++ b/src/main/java/com/provedcode/aws/scheduler/UpdateScheduler.java @@ -0,0 +1,30 @@ +package com.provedcode.aws.scheduler; + +import com.provedcode.aws.service.FileService; +import com.provedcode.talent.repo.TalentRepository; +import lombok.AllArgsConstructor; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +@Transactional +@AllArgsConstructor +public class UpdateScheduler { + + FileService fileService; + TalentRepository talentRepository; + + @Scheduled(cron = "0 0 13 * * SAT") + public void updateTalentsImages() { + + talentRepository.findAll().stream() + .map(i -> { + if (i.getImageName() != null) { + i.setImage(fileService.generetePresingedUrlFor7Days(i.getImageName()).toString()); + } + return i; + }).forEach(talentRepository::save); + } + +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/aws/service/FileService.java b/src/main/java/com/provedcode/aws/service/FileService.java index 78d722b..1c1d9e6 100644 --- a/src/main/java/com/provedcode/aws/service/FileService.java +++ b/src/main/java/com/provedcode/aws/service/FileService.java @@ -3,14 +3,20 @@ import org.springframework.security.core.Authentication; import org.springframework.web.multipart.MultipartFile; +import java.net.URL; import java.util.List; public interface FileService { String saveFile(MultipartFile file); + byte[] downloadFile(String filename); + String deleteFile(String filename); + List listAllFiles(); void setNewUserImage(MultipartFile file, Authentication authentication); + + URL generetePresingedUrlFor7Days(String fileFullPath); } diff --git a/src/main/java/com/provedcode/aws/service/S3Service.java b/src/main/java/com/provedcode/aws/service/S3Service.java index 679c443..e961c20 100644 --- a/src/main/java/com/provedcode/aws/service/S3Service.java +++ b/src/main/java/com/provedcode/aws/service/S3Service.java @@ -1,6 +1,7 @@ package com.provedcode.aws.service; +import com.amazonaws.HttpMethod; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.model.*; import com.amazonaws.util.IOUtils; @@ -8,37 +9,42 @@ import com.provedcode.talent.repo.TalentRepository; import com.provedcode.user.model.entity.UserInfo; import com.provedcode.user.repo.UserInfoRepository; +import com.provedcode.util.PhotoService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.server.ResponseStatusException; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.net.URL; +import java.time.Instant; +import java.util.Date; import java.util.List; -import static org.apache.http.entity.ContentType.*; -import static org.springframework.http.HttpStatus.NOT_FOUND; -import static org.springframework.http.HttpStatus.NOT_IMPLEMENTED; +import static org.springframework.http.HttpStatus.*; @Service @AllArgsConstructor @Slf4j +@Transactional public class S3Service implements FileService { AWSProperties awsProperties; - AmazonS3 s3; + AmazonS3 amazonS3; UserInfoRepository userInfoRepository; TalentRepository talentRepository; + PhotoService photoService; @Override public String saveFile(MultipartFile file) { String originalFilename = file.getOriginalFilename(); try { File file1 = convertMultiPartToFile(file); - PutObjectResult objectResult = s3.putObject(awsProperties.bucket(), originalFilename, file1); + PutObjectResult objectResult = amazonS3.putObject(awsProperties.bucket(), originalFilename, file1); return objectResult.getContentMd5(); } catch (IOException e) { throw new ResponseStatusException(NOT_IMPLEMENTED); @@ -46,8 +52,8 @@ public String saveFile(MultipartFile file) { } @Override - public byte[] downloadFile(String filename) { - S3Object object = s3.getObject(awsProperties.bucket(), filename); + public byte[] downloadFile(String fullFilePath) { + S3Object object = amazonS3.getObject(awsProperties.bucket(), fullFilePath); S3ObjectInputStream objectContent = object.getObjectContent(); try { return IOUtils.toByteArray(objectContent); @@ -57,43 +63,70 @@ public byte[] downloadFile(String filename) { } @Override - public String deleteFile(String filename) { - s3.deleteObject(awsProperties.bucket(), filename); + public String deleteFile(String fullFilePath) { + amazonS3.deleteObject(awsProperties.bucket(), fullFilePath); return "file deleted"; } @Override public List listAllFiles() { - ListObjectsV2Result listObjectsV2Result = s3.listObjectsV2(awsProperties.bucket()); + ListObjectsV2Result listObjectsV2Result = amazonS3.listObjectsV2(awsProperties.bucket()); return listObjectsV2Result.getObjectSummaries().stream().map(S3ObjectSummary::getKey).toList(); } @Override public void setNewUserImage(MultipartFile file, Authentication authentication) { if (file.isEmpty()) { - throw new ResponseStatusException(NOT_IMPLEMENTED, "file must be not empty, actual file-size: %s".formatted(file.getSize())); + throw new ResponseStatusException(BAD_REQUEST, "file must be not empty, actual file-size: %s".formatted(file.getSize())); } - if (!List.of(IMAGE_JPEG.getMimeType(), IMAGE_PNG.getMimeType(), IMAGE_GIF.getMimeType()).contains(file.getContentType())) { - throw new ResponseStatusException(NOT_IMPLEMENTED, "not supported type: %s".formatted(file.getContentType())); + if (photoService.isFileImage(file)) { + throw new ResponseStatusException(BAD_REQUEST, "not supported type: %s".formatted(file.getContentType())); } UserInfo user = userInfoRepository.findByLogin(authentication.getName()) .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "user with login = {%s} not found".formatted(authentication.getName()))); - String fileName = file.getOriginalFilename(); - - String userLogin = authentication.getName(); - String fullPath = "%s/%s".formatted(userLogin, fileName); try { - File f = convertMultiPartToFile(file); + String fileType = getFileType(file); + String fullPath = getFullPath(fileType, authentication.getName()); + File degradePhoto = photoService.degradePhoto(convertMultiPartToFile(file)); + + if (user.getTalent().getImageName() != null) // delete old user image + amazonS3.deleteObject(awsProperties.bucket(), user.getTalent().getImageName()); + + amazonS3.putObject(awsProperties.bucket(), fullPath, degradePhoto); + + user.getTalent().setImageName(fullPath); - s3.putObject(awsProperties.bucket(), fullPath, f); + URL url = generetePresingedUrlFor7Days(fullPath); // generation url with expiration + + log.info("image = {}", amazonS3.getUrl(awsProperties.bucket(), fullPath).toString()); + log.info("image-url = {}", url); + + user.getTalent().setImage(url.toString()); - log.info("image = {}", s3.getUrl(awsProperties.bucket(), fullPath).toString()); - user.getTalent().setImage(s3.getUrl(awsProperties.bucket(), fullPath).toString()); talentRepository.save(user.getTalent()); - } catch (RuntimeException | IOException e) { - throw new ResponseStatusException(NOT_IMPLEMENTED); + } catch (AmazonS3Exception | IOException e) { + throw new ResponseStatusException(SERVICE_UNAVAILABLE, "problems with connection to aws s3"); } + + } + + public URL generetePresingedUrlFor7Days(String fileFullPath) { + GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(awsProperties.bucket(), fileFullPath) + .withMethod(HttpMethod.GET); + + Instant expiration = Instant.now().plusMillis(1000L * 60 * 60 * 24 * 7); // expiration time + urlRequest.setExpiration(Date.from(expiration)); + return amazonS3.generatePresignedUrl(urlRequest); // generation url with expiration + } + + private String getFullPath(String fileType, String userLogin) { + return "%s/%s".formatted(userLogin, "image.%s".formatted(fileType)); + } + + private String getFileType(MultipartFile file) { + String fileName = file.getOriginalFilename(); + return fileName.substring(fileName.lastIndexOf('.') + 1); } private File convertMultiPartToFile(MultipartFile file) diff --git a/src/main/java/com/provedcode/config/SecurityConfig.java b/src/main/java/com/provedcode/config/SecurityConfig.java index 67c7c98..1997071 100644 --- a/src/main/java/com/provedcode/config/SecurityConfig.java +++ b/src/main/java/com/provedcode/config/SecurityConfig.java @@ -51,7 +51,8 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .requestMatchers("/actuator/health").permitAll() // for DevOps .requestMatchers(antMatcher("/h2/**")).permitAll() .requestMatchers(antMatcher("/api/*/talents/**")).permitAll() - .requestMatchers(antMatcher("/api/*/talent/**")).permitAll() + .requestMatchers(antMatcher("/api/*/sponsors/**")).permitAll() + .requestMatchers(antMatcher("/api/*/login")).permitAll() .requestMatchers(antMatcher("/error")).permitAll() .requestMatchers(antMatcher("/v3/api-docs/**")).permitAll() // for openAPI .requestMatchers(antMatcher("/swagger-ui/**")).permitAll() // for openAPI diff --git a/src/main/java/com/provedcode/handlers/ApiError.java b/src/main/java/com/provedcode/handlers/ApiError.java new file mode 100644 index 0000000..5326437 --- /dev/null +++ b/src/main/java/com/provedcode/handlers/ApiError.java @@ -0,0 +1,28 @@ +package com.provedcode.handlers; + +import lombok.Getter; +import org.springframework.http.HttpStatus; + +import java.util.Arrays; +import java.util.List; + +@Getter +public class ApiError { + private HttpStatus status; + private String message; + private List errors; + + public ApiError(HttpStatus status, String message, List errors) { + super(); + this.status = status; + this.message = message; + this.errors = errors; + } + + public ApiError(HttpStatus status, String message, String error) { + super(); + this.status = status; + this.message = message; + errors = Arrays.asList(error); + } +} diff --git a/src/main/java/com/provedcode/handlers/AwsS3ExceptionHandler.java b/src/main/java/com/provedcode/handlers/AwsS3ExceptionHandler.java new file mode 100644 index 0000000..a77af66 --- /dev/null +++ b/src/main/java/com/provedcode/handlers/AwsS3ExceptionHandler.java @@ -0,0 +1,17 @@ +package com.provedcode.handlers; + +import com.provedcode.handlers.dto.ErrorDTO; +import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; + +@ControllerAdvice +public class AwsS3ExceptionHandler { + @ExceptionHandler(FileSizeLimitExceededException.class) + public ResponseEntity fileSizeLimitExceededExceptionHandler(FileSizeLimitExceededException e) { + return ResponseEntity.status(BAD_REQUEST).body(new ErrorDTO("file size is too large")); + } +} diff --git a/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java b/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java index 1c63234..7da4cc8 100644 --- a/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java +++ b/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java @@ -1,14 +1,106 @@ package com.provedcode.handlers; +import jakarta.validation.ConstraintViolationException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.server.ResponseStatusException; +import java.sql.SQLException; + @ControllerAdvice public class TalentExceptionHandler { + public static boolean ignoreSQLException(String sqlState) { + + if (sqlState == null) { + System.out.println("The SQL state is not defined!"); + return false; + } + + // X0Y32: Jar file already exists in schema + if (sqlState.equalsIgnoreCase("X0Y32")) + return true; + + // 42Y55: Table already exists in schema + if (sqlState.equalsIgnoreCase("42Y55")) + return true; + + return false; + } + + @ExceptionHandler({SQLException.class}) + public void printSQLException(SQLException ex) { + for (Throwable e : ex) { + if (e instanceof SQLException) { + if (ignoreSQLException(((SQLException) e).getSQLState()) == false) { + + e.printStackTrace(System.err); + System.err.println("SQLState: " + + ((SQLException) e).getSQLState()); + + System.err.println("Error Code: " + + ((SQLException) e).getErrorCode()); + + System.err.println("Message: " + e.getMessage()); + + Throwable t = ex.getCause(); + while (t != null) { + System.out.println("Cause: " + t); + t = t.getCause(); + } + } + } + } + } + @ExceptionHandler(ResponseStatusException.class) private ResponseEntity responseStatusExceptionHandler(ResponseStatusException exception) { return ResponseEntity.status(exception.getStatusCode()).body(exception.getBody()); } + + @ExceptionHandler(ConstraintViolationException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + private ResponseEntity responseStatusExceptionHandler(ConstraintViolationException exception) { + ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, exception.getMessage(), exception.toString()); + return new ResponseEntity<>(apiError, new HttpHeaders(), apiError.getStatus()); + } + +// @ExceptionHandler({ Exception.class }) +// public ResponseEntity handleAll(Exception ex, WebRequest request) { +// ApiError apiError = new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, ex.getLocalizedMessage(), "error occurred"); +// return new ResponseEntity<>(apiError, new HttpHeaders(), apiError.getStatus()); +// } + +//MethodArgumentNotValidException – This exception is thrown +// when an argument annotated with @Valid failed validation: +// @ResponseStatus(HttpStatus.BAD_REQUEST) +// @ExceptionHandler(MethodArgumentNotValidException.class) +// public Map handleValidationExceptions(MethodArgumentNotValidException ex) { +// Map errors = new HashMap<>(); +// ex.getBindingResult().getAllErrors().forEach( +// (error) -> { +// String fieldName = ((FieldError) error).getField(); +// String errorMessage = error.getDefaultMessage(); +// errors.put(fieldName, errorMessage); +// }); +// return errors; +// } + +// @ExceptionHandler({ ConstraintViolationException.class }) +// public ResponseEntity handleConstraintViolation( +// ConstraintViolationException ex, WebRequest request) { +// List errors = new ArrayList<>(); +// for (ConstraintViolation violation : ex.getConstraintViolations()) { +// errors.add(violation.getRootBeanClass().getName() + " " + +// violation.getPropertyPath() + ": " + violation.getMessage()); +// } +// +// ApiError apiError = +// new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors); +// return new ResponseEntity( +// apiError, new HttpHeaders(), apiError.getStatus()); +// } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/handlers/dto/ErrorDTO.java b/src/main/java/com/provedcode/handlers/dto/ErrorDTO.java new file mode 100644 index 0000000..8269a4c --- /dev/null +++ b/src/main/java/com/provedcode/handlers/dto/ErrorDTO.java @@ -0,0 +1,7 @@ +package com.provedcode.handlers.dto; + +import lombok.Builder; + +@Builder +public record ErrorDTO (String message) { +} diff --git a/src/main/java/com/provedcode/kudos/controller/KudosController.java b/src/main/java/com/provedcode/kudos/controller/KudosController.java index 2f2605c..7f18175 100644 --- a/src/main/java/com/provedcode/kudos/controller/KudosController.java +++ b/src/main/java/com/provedcode/kudos/controller/KudosController.java @@ -1,32 +1,48 @@ package com.provedcode.kudos.controller; -import com.provedcode.kudos.service.KudosService; +import com.provedcode.kudos.model.request.SetAmountKudos; import com.provedcode.kudos.model.response.KudosAmount; +import com.provedcode.kudos.model.response.KudosAmountWithSponsor; +import com.provedcode.kudos.service.KudosService; +import com.provedcode.util.annotations.doc.controller.kudos.GetAmountOfKudosApiDoc; +import com.provedcode.util.annotations.doc.controller.kudos.GetKudosForSponsorApiDoc; +import com.provedcode.util.annotations.doc.controller.kudos.PostAddKudosToProofApiDoc; +import jakarta.validation.Valid; import lombok.AllArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.Optional; + @RestController @AllArgsConstructor -@RequestMapping("/api/v3/talent") +@Validated +@RequestMapping("/api/v3/") public class KudosController { KudosService kudosService; - @GetMapping("/proofs/{proof-id}/kudos") - KudosAmount getKudosProof(@PathVariable("proof-id") long id, Authentication authentication) { - return kudosService.getAmountKudosProof(id, authentication); + @GetKudosForSponsorApiDoc + @PreAuthorize("hasRole('SPONSOR')") + @GetMapping("/sponsors/{sponsor-id}/kudos") + KudosAmount getKudosForSponsor(@PathVariable("sponsor-id") long sponsorId, Authentication authentication) { + return kudosService.getKudosForSponsor(sponsorId, authentication); } + @GetAmountOfKudosApiDoc @PreAuthorize("hasRole('TALENT')") - @PostMapping("/proofs/{proof-id}/kudos") - void addKudosToProof(@PathVariable("proof-id") long id, Authentication authentication) { - kudosService.addKudosToProof(id, authentication); + @GetMapping("/proofs/{proof-id}/kudos") + KudosAmountWithSponsor getProofKudos(@PathVariable("proof-id") long proofId, Authentication authentication) { + return kudosService.getProofKudos(proofId, authentication); } - @PreAuthorize("hasRole('TALENT')") - @DeleteMapping("/proofs/{proof-id}/kudos") - void deleteKudosFromProof(@PathVariable("proof-id") long id, Authentication authentication) { - kudosService.deleteKudosFromProof(id, authentication); + @PostAddKudosToProofApiDoc + @PreAuthorize("hasRole('SPONSOR')") + @PostMapping("/proofs/{proof-id}/kudos") + void addKudosToProof(@PathVariable("proof-id") long proofId, + @RequestBody @Valid Optional amount, + Authentication authentication) { + kudosService.addKudosToProof(proofId, amount, authentication); } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/kudos/model/entity/Kudos.java b/src/main/java/com/provedcode/kudos/model/entity/Kudos.java index e73bbea..259c387 100644 --- a/src/main/java/com/provedcode/kudos/model/entity/Kudos.java +++ b/src/main/java/com/provedcode/kudos/model/entity/Kudos.java @@ -1,12 +1,10 @@ package com.provedcode.kudos.model.entity; -import com.provedcode.talent.model.entity.Talent; +import com.provedcode.sponsor.model.entity.Sponsor; import com.provedcode.talent.model.entity.TalentProof; import jakarta.persistence.*; import lombok.*; -import java.util.List; - @Getter @Setter @Entity @@ -19,10 +17,12 @@ public class Kudos { @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; - @ManyToOne(cascade = CascadeType.ALL) - @JoinColumn(name = "talent_id") - private Talent talent; + @Column(name = "amount") + private Long amount; @ManyToOne + @JoinColumn(name = "sponsor_id") + private Sponsor sponsor; + @ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "proof_id") private TalentProof proof; } \ No newline at end of file diff --git a/src/main/java/com/provedcode/kudos/model/request/SetAmountKudos.java b/src/main/java/com/provedcode/kudos/model/request/SetAmountKudos.java new file mode 100644 index 0000000..3d7bbd2 --- /dev/null +++ b/src/main/java/com/provedcode/kudos/model/request/SetAmountKudos.java @@ -0,0 +1,9 @@ +package com.provedcode.kudos.model.request; + +import jakarta.validation.constraints.PositiveOrZero; + +public record SetAmountKudos( + @PositiveOrZero + Long amount +) { +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/kudos/model/response/KudosAmountWithSponsor.java b/src/main/java/com/provedcode/kudos/model/response/KudosAmountWithSponsor.java new file mode 100644 index 0000000..75b80f9 --- /dev/null +++ b/src/main/java/com/provedcode/kudos/model/response/KudosAmountWithSponsor.java @@ -0,0 +1,13 @@ +package com.provedcode.kudos.model.response; + +import com.provedcode.sponsor.model.dto.SponsorDTO; +import lombok.Builder; + +import java.util.Map; + +@Builder +public record KudosAmountWithSponsor( + Long allKudosOnProof, + Map kudosFromSponsor +) { +} diff --git a/src/main/java/com/provedcode/kudos/repository/KudosRepository.java b/src/main/java/com/provedcode/kudos/repository/KudosRepository.java index f908ba9..3b0f629 100644 --- a/src/main/java/com/provedcode/kudos/repository/KudosRepository.java +++ b/src/main/java/com/provedcode/kudos/repository/KudosRepository.java @@ -1,13 +1,10 @@ package com.provedcode.kudos.repository; import com.provedcode.kudos.model.entity.Kudos; -import com.provedcode.talent.model.entity.Talent; import org.springframework.data.jpa.repository.JpaRepository; public interface KudosRepository extends JpaRepository { - long countByProof_Id(Long id); + long countByProofId(Long id); - boolean existsByTalent(Talent talent); - - boolean existsByTalentAndProof_Id(Talent talent, Long id); + boolean existsBySponsorIdAndProofId(Long sponsorId, Long proofId); } \ No newline at end of file diff --git a/src/main/java/com/provedcode/kudos/service/KudosService.java b/src/main/java/com/provedcode/kudos/service/KudosService.java index 4bb8d30..f506391 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -1,8 +1,14 @@ package com.provedcode.kudos.service; import com.provedcode.kudos.model.entity.Kudos; +import com.provedcode.kudos.model.request.SetAmountKudos; import com.provedcode.kudos.model.response.KudosAmount; +import com.provedcode.kudos.model.response.KudosAmountWithSponsor; import com.provedcode.kudos.repository.KudosRepository; +import com.provedcode.sponsor.mapper.SponsorMapper; +import com.provedcode.sponsor.model.dto.SponsorDTO; +import com.provedcode.sponsor.model.entity.Sponsor; +import com.provedcode.sponsor.repository.SponsorRepository; import com.provedcode.talent.model.ProofStatus; import com.provedcode.talent.model.entity.Talent; import com.provedcode.talent.model.entity.TalentProof; @@ -16,7 +22,10 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.server.ResponseStatusException; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; import static org.springframework.http.HttpStatus.*; @@ -25,87 +34,99 @@ @Transactional public class KudosService { KudosRepository kudosRepository; - TalentRepository talentRepository; TalentProofRepository talentProofRepository; UserInfoRepository userInfoRepository; - - @Transactional(readOnly = true) - public KudosAmount getAmountKudosProof(long id, Authentication authentication) { - TalentProof talentProof = talentProofRepository.findById(id) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "proof with id = %s not found".formatted(id))); - - if (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { - throw new ResponseStatusException(FORBIDDEN); - } - long count = kudosRepository.countByProof_Id(id); - if (authentication == null) { - return new KudosAmount(count, false); - } - - Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); - - if (userInfo.isPresent()) { - Talent talent = userInfo.get().getTalent(); - if (talent.getCudoses().stream().anyMatch(i -> i.getProof().equals(talentProof))) { - return new KudosAmount(count, true); - } + SponsorRepository sponsorRepository; + TalentRepository talentRepository; + SponsorMapper sponsorMapper; + + public void addKudosToProof(long proofId, Optional setAmountKudos, Authentication authentication) { + String login = authentication.getName(); + UserInfo userInfo = userInfoRepository.findByLogin(login) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "User with login = %s not found".formatted( + login))); + Sponsor sponsor = sponsorRepository.findById(userInfo.getSponsor().getId()).orElseThrow( + () -> new ResponseStatusException(NOT_FOUND, + "Sponsor with login = %s not found".formatted(login))); + TalentProof talentProof = talentProofRepository.findById(proofId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Proof with id = %d not found".formatted( + proofId))); + + if (kudosRepository.existsBySponsorIdAndProofId(sponsor.getId(), talentProof.getId())) + throw new ResponseStatusException(FORBIDDEN, "The sponsor has already set kudos to this proof"); + if (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) + throw new ResponseStatusException(FORBIDDEN, "Proof that was kudosed does not have the PUBLISHED status"); + + long obtainedAmount = setAmountKudos.orElse(new SetAmountKudos(1L)).amount(); + if (sponsor.getAmountKudos() < obtainedAmount) { + throw new ResponseStatusException(FORBIDDEN, "The sponsor cannot give more kudos than he has"); } - return new KudosAmount(count, false); + sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); + kudosRepository.save(Kudos.builder() + .amount(obtainedAmount) + .proof(talentProof) + .sponsor(sponsor) + .build()); } - public void addKudosToProof(long id, Authentication authentication) { - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Talent with id = %s not found".formatted( - id))); - - Talent talent = userInfo.getTalent(); - - TalentProof talentProof = talentProofRepository.findById(id) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Proof with id = %s not found".formatted( - id))); - - if (talent.getId().equals(talentProof.getTalent().getId())) { - throw new ResponseStatusException(FORBIDDEN, "Talent can’t give `kudos` to himself"); - } - if (kudosRepository.existsByTalentAndProof_Id(talent, id)) { - throw new ResponseStatusException(CONFLICT, "Talent can give only one `kudos` for one proof"); - } - if (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { - throw new ResponseStatusException(FORBIDDEN); + @Transactional(readOnly = true) + public KudosAmount getKudosForSponsor(long sponsorId, Authentication authentication) { + String login = authentication.getName(); + UserInfo userInfo = userInfoRepository.findByLogin(login) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "User with login = %s not found".formatted( + login))); + if (!userInfo.getSponsor().getId().equals(sponsorId)) { + throw new ResponseStatusException(FORBIDDEN, "Only the account owner can view the number of kudos"); } - - kudosRepository.save(Kudos.builder() - .proof(talentProof) - .talent(talent) - .build()); + Sponsor sponsor = sponsorRepository.findById(sponsorId).orElseThrow( + () -> new ResponseStatusException(NOT_FOUND, + String.format("Sponsor with id = %d not found", sponsorId))); + return new KudosAmount(sponsor.getAmountKudos()); } - public void deleteKudosFromProof(long id, Authentication authentication) { - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Talent with id = %s not found".formatted( - id))); - Talent talent = userInfo.getTalent(); - - TalentProof talentProof = talentProofRepository.findById(id) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Proof with id = %s not found".formatted( - id))); + @Transactional(readOnly = true) + public KudosAmountWithSponsor getProofKudos(long proofId, Authentication authentication) { + String login = authentication.getName(); + UserInfo userInfo = userInfoRepository.findByLogin(login) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "User with login = %s not found".formatted( + login))); + Talent talent = talentRepository.findById(userInfo.getId()) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Talent with login = %s not found".formatted( + login))); + TalentProof talentProof = talentProofRepository.findById(proofId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Proof with id = %s not found".formatted( + proofId))); + + Long countOfAllKudos = talentProof.getKudos().stream() + .map(Kudos::getAmount) + .reduce(0L, (prev, next) -> prev + next); - if (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { - throw new ResponseStatusException(FORBIDDEN); - } - if (!kudosRepository.existsByTalent(talent)) { - throw new ResponseStatusException(CONFLICT, "kudos don`t exist"); + if (talent.getId().equals(talentProof.getTalent().getId())) { + Map kudosFromSponsor = talentProof.getKudos().stream() + .collect(Collectors.toMap( + Kudos::getAmount, + proof -> proof.getSponsor() != null + ? sponsorMapper.toDto( + proof.getSponsor()) + : SponsorDTO.builder().build(), + (prev, next) -> next, + HashMap::new + )); + + return KudosAmountWithSponsor.builder() + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(kudosFromSponsor) + .build(); + } else { + return KudosAmountWithSponsor.builder() + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(null).build(); } - - Kudos kudos = talent.getCudoses().stream().filter(i -> i.getProof().getId().equals(id)).findFirst() - .orElseThrow(); - talentProof.getKudos().remove(kudos); - talent.getCudoses().remove(kudos); - - talentRepository.save(talent); } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/sponsor/controller/SponsorController.java b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java new file mode 100644 index 0000000..39c5bad --- /dev/null +++ b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java @@ -0,0 +1,60 @@ +package com.provedcode.sponsor.controller; + +import com.provedcode.sponsor.mapper.SponsorMapper; +import com.provedcode.sponsor.model.dto.SponsorDTO; +import com.provedcode.sponsor.model.request.EditSponsor; +import com.provedcode.sponsor.service.SponsorService; +import com.provedcode.util.annotations.doc.controller.sponsor.DeleteSponsorApiDoc; +import com.provedcode.util.annotations.doc.controller.sponsor.GetAllSponsorsApiDoc; +import com.provedcode.util.annotations.doc.controller.sponsor.GetSponsorApiDoc; +import com.provedcode.util.annotations.doc.controller.sponsor.PatchEditSponsorApiDoc; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.PositiveOrZero; +import lombok.AllArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Optional; + +@RestController +@AllArgsConstructor +@Validated +@RequestMapping("/api/v3") +public class SponsorController { + SponsorService sponsorService; + SponsorMapper sponsorMapper; + + @GetAllSponsorsApiDoc + @GetMapping("/sponsors") + Page getSponsors(@RequestParam(value = "page", defaultValue = "0") @PositiveOrZero Integer page, + @RequestParam(value = "size", defaultValue = "5") @Min(1) @Max(1000) Integer size) { + return sponsorService.getAllSponsors(page, size).map(sponsorMapper::toDto); + } + + @GetSponsorApiDoc + @PreAuthorize("hasRole('SPONSOR')") + @GetMapping("/sponsors/{id}") + SponsorDTO getSponsor(@PathVariable("id") long id, Authentication authentication) { + return sponsorMapper.toDto(sponsorService.getSponsorById(id, authentication)); + } + + @PatchEditSponsorApiDoc + @PreAuthorize("hasRole('SPONSOR')") + @PatchMapping("/sponsors/{id}") + SponsorDTO editSponsor(@PathVariable("id") long id, + @RequestBody EditSponsor editSponsor, + Authentication authentication) { + return sponsorMapper.toDto(sponsorService.editSponsorById(id, editSponsor, authentication)); + } + + @DeleteSponsorApiDoc + @PreAuthorize("hasRole('SPONSOR')") + @DeleteMapping("/sponsors/{id}") + void deleteSponsor(@PathVariable("id") long id, Authentication authentication) { + sponsorService.deleteSponsor(id, authentication); + } +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/sponsor/mapper/SponsorMapper.java b/src/main/java/com/provedcode/sponsor/mapper/SponsorMapper.java new file mode 100644 index 0000000..67a0a71 --- /dev/null +++ b/src/main/java/com/provedcode/sponsor/mapper/SponsorMapper.java @@ -0,0 +1,14 @@ +package com.provedcode.sponsor.mapper; + +import com.provedcode.sponsor.model.dto.SponsorDTO; +import com.provedcode.sponsor.model.entity.Sponsor; +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.mapstruct.ReportingPolicy; + +@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING) +public interface SponsorMapper { + SponsorDTO toDto(Sponsor sponsor); + + Sponsor toEntity(SponsorDTO sponsorDTO); +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java b/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java new file mode 100644 index 0000000..62c3b62 --- /dev/null +++ b/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java @@ -0,0 +1,15 @@ +package com.provedcode.sponsor.model.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Builder; + +@Builder +public record SponsorDTO( + Long id, + @JsonProperty("first_name") + String firstName, + @JsonProperty("last_name") + String lastName, + String image +) { +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java b/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java new file mode 100644 index 0000000..662de41 --- /dev/null +++ b/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java @@ -0,0 +1,39 @@ +package com.provedcode.sponsor.model.entity; + +import com.provedcode.kudos.model.entity.Kudos; +import jakarta.persistence.*; +import jakarta.validation.constraints.NotEmpty; +import lombok.*; +import org.hibernate.validator.constraints.URL; + +import java.util.ArrayList; +import java.util.List; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +@Entity +@Table(name = "sponsor") +public class Sponsor { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", nullable = false) + private Long id; + @Column(name = "amount_kudos") + private Long amountKudos; + @NotEmpty + @Column(name = "first_name", length = 20) + private String firstName; + @NotEmpty + @Column(name = "last_name", length = 20) + private String lastName; + @URL + @Column(name = "image", length = 1000) + private String image; + @Column(name = "image_name", length = 100) + private String imageName; + @OneToMany(mappedBy = "sponsor") + private List kudoses = new ArrayList<>(); +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/sponsor/model/request/EditSponsor.java b/src/main/java/com/provedcode/sponsor/model/request/EditSponsor.java new file mode 100644 index 0000000..55bf951 --- /dev/null +++ b/src/main/java/com/provedcode/sponsor/model/request/EditSponsor.java @@ -0,0 +1,17 @@ +package com.provedcode.sponsor.model.request; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Builder; + +@Builder +public record EditSponsor( + Long id, + @JsonProperty("first_name") + String firstName, + @JsonProperty("last_name") + String lastName, + String image, + @JsonProperty("count_of_kudos") + Long countOfKudos +) { +} diff --git a/src/main/java/com/provedcode/sponsor/repository/SponsorRepository.java b/src/main/java/com/provedcode/sponsor/repository/SponsorRepository.java new file mode 100644 index 0000000..cc91652 --- /dev/null +++ b/src/main/java/com/provedcode/sponsor/repository/SponsorRepository.java @@ -0,0 +1,7 @@ +package com.provedcode.sponsor.repository; + +import com.provedcode.sponsor.model.entity.Sponsor; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface SponsorRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/sponsor/service/SponsorService.java b/src/main/java/com/provedcode/sponsor/service/SponsorService.java new file mode 100644 index 0000000..8beaba7 --- /dev/null +++ b/src/main/java/com/provedcode/sponsor/service/SponsorService.java @@ -0,0 +1,92 @@ +package com.provedcode.sponsor.service; + +import com.provedcode.config.PageProperties; +import com.provedcode.kudos.model.entity.Kudos; +import com.provedcode.sponsor.model.entity.Sponsor; +import com.provedcode.sponsor.model.request.EditSponsor; +import com.provedcode.sponsor.repository.SponsorRepository; +import com.provedcode.sponsor.utill.ValidateSponsorForCompliance; +import com.provedcode.user.model.entity.UserInfo; +import com.provedcode.user.repo.UserInfoRepository; +import lombok.AllArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.server.ResponseStatusException; + +import java.util.List; +import java.util.Optional; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.FORBIDDEN; + +@Service +@AllArgsConstructor +@Transactional +public class SponsorService { + PageProperties pageProperties; + SponsorRepository sponsorRepository; + UserInfoRepository userInfoRepository; + ValidateSponsorForCompliance validateSponsorForCompliance; + + @Transactional(readOnly = true) + public Page getAllSponsors(Integer page, Integer size) { + return sponsorRepository.findAll(PageRequest.of(page, size)); + } + + @Transactional(readOnly = true) + public Sponsor getSponsorById(long id, Authentication authentication) { + Optional user = userInfoRepository.findByLogin(authentication.getName()); + Optional sponsor = sponsorRepository.findById(id); + validateSponsorForCompliance.userVerification(sponsor, user, id); + return sponsor.get(); + } + + public Sponsor editSponsorById(long id, EditSponsor editSponsor, Authentication authentication) { + Optional user = userInfoRepository.findByLogin(authentication.getName()); + Optional sponsor = sponsorRepository.findById(id); + validateSponsorForCompliance.userVerification(sponsor, user, id); + checkEditSponsorNull(editSponsor); + + Sponsor editableSponsor = sponsor.get(); + if (editSponsor.firstName() != null) { + editableSponsor.setFirstName(editSponsor.firstName()); + } + if (editSponsor.lastName() != null) { + editableSponsor.setLastName(editSponsor.lastName()); + } + if (editSponsor.image() != null) { + editableSponsor.setImage(editSponsor.image()); + } + if (editSponsor.countOfKudos() != null) { + if (editSponsor.countOfKudos() > 0) { + editableSponsor.setAmountKudos(editableSponsor.getAmountKudos() + editSponsor.countOfKudos()); + } else { + throw new ResponseStatusException(BAD_REQUEST, "count of kudos must be greater than 0"); + } + } + return sponsorRepository.save(editableSponsor); + } + + public void deleteSponsor(long id, Authentication authentication) { + Optional user = userInfoRepository.findByLogin(authentication.getName()); + Optional sponsor = sponsorRepository.findById(id); + validateSponsorForCompliance.userVerification(sponsor, user, id); + + Sponsor deletableSponsor = sponsor.get(); + List kudosList = deletableSponsor.getKudoses().stream().map(i -> { + i.setSponsor(null); + return i; + }).toList(); + deletableSponsor.setKudoses(kudosList); + userInfoRepository.delete(user.get()); + } + + private void checkEditSponsorNull(EditSponsor editSponsor) { + if (editSponsor.firstName() == null && editSponsor.lastName() == null && editSponsor.image() == null && + editSponsor.countOfKudos() == null) + throw new ResponseStatusException(FORBIDDEN, "you did not provide information to make changes"); + } +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/sponsor/utill/ValidateSponsorForCompliance.java b/src/main/java/com/provedcode/sponsor/utill/ValidateSponsorForCompliance.java new file mode 100644 index 0000000..ce8a6d0 --- /dev/null +++ b/src/main/java/com/provedcode/sponsor/utill/ValidateSponsorForCompliance.java @@ -0,0 +1,24 @@ +package com.provedcode.sponsor.utill; + +import com.provedcode.sponsor.model.entity.Sponsor; +import com.provedcode.user.model.entity.UserInfo; +import org.springframework.stereotype.Service; +import org.springframework.web.server.ResponseStatusException; + +import java.util.Optional; + +import static org.springframework.http.HttpStatus.FORBIDDEN; +import static org.springframework.http.HttpStatus.NOT_FOUND; + +@Service +public class ValidateSponsorForCompliance { + + public void userVerification(Optional sponsor, Optional userInfo, long sponsorId) { + if (sponsor.isEmpty() || userInfo.isEmpty()) { + throw new ResponseStatusException(NOT_FOUND, String.format("sponsor with id = %d not found", sponsorId)); + } + if (userInfo.get().getSponsor().getId() != sponsorId) { + throw new ResponseStatusException(FORBIDDEN); + } + } +} diff --git a/src/main/java/com/provedcode/talent/controller/TalentController.java b/src/main/java/com/provedcode/talent/controller/TalentController.java index 4c8ea81..1b9e20d 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentController.java @@ -1,25 +1,28 @@ package com.provedcode.talent.controller; +import com.provedcode.config.PageProperties; import com.provedcode.talent.mapper.TalentMapper; import com.provedcode.talent.model.dto.FullTalentDTO; import com.provedcode.talent.model.dto.ShortTalentDTO; import com.provedcode.talent.model.request.EditTalent; import com.provedcode.talent.service.TalentService; import com.provedcode.user.model.dto.SessionInfoDTO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; +import com.provedcode.util.annotations.doc.controller.talent.DeleteTalentApiDoc; +import com.provedcode.util.annotations.doc.controller.talent.GetAllTalentsApiDoc; +import com.provedcode.util.annotations.doc.controller.talent.GetTalentApiDoc; +import com.provedcode.util.annotations.doc.controller.talent.PatchEditTalentApiDoc; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.PositiveOrZero; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.Optional; @@ -29,47 +32,20 @@ @AllArgsConstructor @RequestMapping("/api/v2") @Tag(name = "talent", description = "Talent API") +@Validated public class TalentController { TalentService talentService; TalentMapper talentMapper; - @Operation(summary = "Get all talents", - description = "As a guest I want to see a page with a list of all “talents” cards displayed with a short description about them") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "SUCCESS", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = Page.class, subTypes = {ShortTalentDTO.class}))), - @ApiResponse(responseCode = "404", - description = "NOT FOUND", - content = @Content), - @ApiResponse( - responseCode = "400", - description = "BAD_REQUEST (parameter: page or size are incorrect)", - content = @Content) - }) + @GetAllTalentsApiDoc @GetMapping("/talents") - @ResponseStatus(HttpStatus.OK) - Page getTalents(@RequestParam(value = "page") Optional page, - @RequestParam(value = "size") Optional size) { + @Validated + Page getTalents(@RequestParam(value = "page", defaultValue = "0") @PositiveOrZero Integer page, + @RequestParam(value = "size", defaultValue = "5") @Min(1) @Max(1000) Integer size) { return talentService.getTalentsPage(page, size).map(talentMapper::talentToShortTalentDTO); } - @Operation(summary = "Get talent", - description = "As a talent I want to have an opportunity to see the full information about the talent") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "SUCCESS", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = FullTalentDTO.class))), - @ApiResponse(responseCode = "404", - description = "NOT FOUND", - content = @Content), - @ApiResponse( - responseCode = "401", - description = "UNAUTHORIZED", - content = @Content), - }) + @GetTalentApiDoc @PreAuthorize("hasRole('TALENT')") @GetMapping("/talents/{id}") FullTalentDTO getTalent(@PathVariable("id") long id, Authentication authentication) { @@ -78,29 +54,7 @@ FullTalentDTO getTalent(@PathVariable("id") long id, Authentication authenticati return talentMapper.talentToFullTalentDTO(talentService.getTalentById(id)); } - @Operation(summary = "Edit information about talent", - description = "As a talent I want to have an opportunity to edit my personal profile by adding new information, changing already existing information") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "SUCCESS", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = FullTalentDTO.class))), - @ApiResponse(responseCode = "404", - description = "NOT FOUND", - content = @Content), - @ApiResponse( - responseCode = "401", - description = "UNAUTHORIZED", - content = @Content), - @ApiResponse( - responseCode = "403", - description = "FORBIDDEN (if not the owner wants to change the talent)", - content = @Content), - @ApiResponse( - responseCode = "400", - description = "BAD REQUEST", - content = @Content) - }) + @PatchEditTalentApiDoc @PreAuthorize("hasRole('TALENT')") @PatchMapping("/talents/{talent-id}") FullTalentDTO editTalent(@PathVariable("talent-id") long id, @@ -109,29 +63,7 @@ FullTalentDTO editTalent(@PathVariable("talent-id") long id, return talentMapper.talentToFullTalentDTO(talentService.editTalent(id, editTalent, authentication)); } - @Operation(summary = "Delete talent", - description = "As a talent I want to have an opportunity to delete personal accounts") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "SUCCESS", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = FullTalentDTO.class))), - @ApiResponse(responseCode = "404", - description = "NOT FOUND ", - content = @Content), - @ApiResponse( - responseCode = "401", - description = "UNAUTHORIZED", - content = @Content), - @ApiResponse( - responseCode = "403", - description = "FORBIDDEN (if not the owner wants to delete the talent)", - content = @Content), - @ApiResponse( - responseCode = "400", - description = "BAD REQUEST (incorrect id)", - content = @Content) - }) + @DeleteTalentApiDoc @PreAuthorize("hasRole('TALENT')") @DeleteMapping("/talents/{id}") SessionInfoDTO deleteTalent(@PathVariable("id") long id, Authentication authentication) { diff --git a/src/main/java/com/provedcode/talent/controller/TalentProofController.java b/src/main/java/com/provedcode/talent/controller/TalentProofController.java index 7cff2be..2b5e769 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentProofController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentProofController.java @@ -6,71 +6,42 @@ import com.provedcode.talent.model.dto.StatusDTO; import com.provedcode.talent.model.request.AddProof; import com.provedcode.talent.service.TalentProofService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.headers.Header; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; +import com.provedcode.util.annotations.doc.controller.proof.*; import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.PositiveOrZero; import lombok.AllArgsConstructor; import org.springframework.data.domain.Page; -import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.Optional; - @RestController @AllArgsConstructor @RequestMapping("/api/v2/talents") +@Validated public class TalentProofController { TalentProofService talentProofService; TalentProofMapper talentProofMapper; - @Operation(summary = "Get all proofs", - description = "As a guest I want to see a list of all proofs displayed anonymously") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "SUCCESS", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = Page.class, subTypes = {ProofDTO.class}))), - @ApiResponse(responseCode = "404", - description = "NOT FOUND", - content = @Content), - @ApiResponse( - responseCode = "400", - description = "BAD REQUEST, parameter: page, size or order-by are incorrect", - content = @Content) - }) + @GetAllProofsApiDoc @GetMapping("/proofs") - Page getAllProofs(@RequestParam(value = "page") Optional page, - @RequestParam(value = "size") Optional size, - @RequestParam(value = "order-by") Optional orderBy, + Page getAllProofs(@RequestParam(value = "page", defaultValue = "0") @PositiveOrZero Integer page, + @RequestParam(value = "size", defaultValue = "5") @Min(1) @Max(1000) Integer size, + @RequestParam(value = "order-by", defaultValue = "ASC") + @Pattern(regexp = "asc|desc", + flags = {Pattern.Flag.CASE_INSENSITIVE}, + message = "'direction' query param must be equals ASC or DESC") + String orderBy, @RequestParam(value = "sort-by", defaultValue = "created") String... sortBy) { return talentProofService.getAllProofsPage(page, size, orderBy, sortBy).map(talentProofMapper::toProofDTO); } - @Operation(summary = "Get proof") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "SUCCESS", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = ProofDTO.class))), - @ApiResponse(responseCode = "404", - description = "NOT FOUND", - content = @Content), - @ApiResponse( - responseCode = "401", - description = "UNAUTHORIZED", - content = @Content), - @ApiResponse( - responseCode = "400", - description = "BAD REQUEST, parameter: page, proof-id or size are incorrect", - content = @Content) - }) + @GetTalentProofByProofIdApiDoc @GetMapping("/proofs/{proof-id}") @PreAuthorize("hasRole('TALENT')") ProofDTO getTalentProof(@PathVariable(value = "proof-id") long proofId, @@ -78,63 +49,23 @@ ProofDTO getTalentProof(@PathVariable(value = "proof-id") long proofId, return talentProofMapper.toProofDTO(talentProofService.getTalentProof(proofId, authentication)); } - @Operation(summary = "Get all talent proofs", - description = "As a talent I want to see all proofs in personal profile page") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "SUCCESS", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = FullProofDTO.class))), - @ApiResponse(responseCode = "404", - description = "NOT FOUND", - content = @Content), - @ApiResponse( - responseCode = "401", - description = "UNAUTHORIZED", - content = @Content), - @ApiResponse( - responseCode = "400", - description = "BAD REQUEST, wrong @RequestParam like page, size, order-by, sort-by or incorrect talent-id", - content = @Content) - }) + @GetTalentInformationWithProofsApiDoc @GetMapping("/{talent-id}/proofs") @PreAuthorize("hasRole('TALENT')") FullProofDTO getTalentInformationWithProofs(Authentication authentication, @PathVariable("talent-id") Long talentId, - @RequestParam(value = "page") Optional page, - @RequestParam(value = "size") Optional size, - @RequestParam(value = "order-by") Optional orderBy, + @RequestParam(value = "page", defaultValue = "0") @PositiveOrZero Integer page, + @RequestParam(value = "size", defaultValue = "5") @Min(1) @Max(1000) Integer size, + @RequestParam(value = "order-by", defaultValue = "ASC") + @Pattern(regexp = "asc|desc", + flags = {Pattern.Flag.CASE_INSENSITIVE}, + message = "'direction' query param must be equals ASC or DESC") + String orderBy, @RequestParam(value = "sort-by", defaultValue = "created") String... sortBy) { return talentProofService.getTalentProofs(talentId, page, size, orderBy, authentication, sortBy); } - @Operation(summary = "Add proof", - description = "As a talent I want to have an opportunity to add my personal proof") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "SUCCESS", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = ProofDTO.class)), - headers = {@Header(name = "Location", - description = "The URI of the created proof", - schema = @Schema(type = "string"))} - ), - @ApiResponse(responseCode = "404", - description = "NOT FOUND", - content = @Content), - @ApiResponse( - responseCode = "401", - description = "Unauthorized", - content = @Content), - @ApiResponse( - responseCode = "400", - description = "BAD REQUEST, (wrong data to add or incorrect talent-id)", - content = @Content), - @ApiResponse( - responseCode = "403", - description = "FORBIDDEN (if not the owner wants to add the proof)", - content = @Content) - }) + @PostAddProofApiDoc @PostMapping("/{talent-id}/proofs") @PreAuthorize("hasRole('TALENT')") ResponseEntity addProof(@PathVariable(value = "talent-id") long talentId, @@ -143,29 +74,7 @@ ResponseEntity addProof(@PathVariable(value = "talent-id") long talentId, return talentProofService.addProof(addProof, talentId, authentication); } - @Operation(summary = "Edit information about proof", - description = "As a talent I want to have an opportunity to edit my personal proofs") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "SUCCESS", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = ProofDTO.class))), - @ApiResponse(responseCode = "404", - description = "NOT FOUND", - content = @Content), - @ApiResponse( - responseCode = "401", - description = "Unauthorized", - content = @Content), - @ApiResponse( - responseCode = "400", - description = "BAD REQUEST, (wrong data to edit or incorrect talent-id, proof-id)", - content = @Content), - @ApiResponse( - responseCode = "403", - description = "FORBIDDEN (if not the owner wants to edit the proof)", - content = @Content) - }) + @PatchEditProofApiDoc @PatchMapping("/{talent-id}/proofs/{proof-id}") @PreAuthorize("hasRole('TALENT')") ProofDTO editProof(Authentication authentication, @@ -176,30 +85,7 @@ ProofDTO editProof(Authentication authentication, talentProofService.editTalentProof(talentId, proofId, proof, authentication)); } - @Operation(summary = "Delete proof", - description = "As a talent I want to have an opportunity to delete my personal proofs") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "SUCCESS", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = StatusDTO.class))), - @ApiResponse(responseCode = "404", - description = "NOT FOUND", - content = @Content), - @ApiResponse( - responseCode = "401", - description = "UNAUTHORIZED", - content = @Content), - @ApiResponse( - responseCode = "400", - description = "BAD_REQUEST, (incorrect talent-id,proof-id)", - content = @Content), - @ApiResponse( - responseCode = "403", - description = "FORBIDDEN (if not the owner wants to delete the proof or " + - "impossible change proofs status from DRAFT to HIDDEN, it should be PUBLISHED)", - content = @Content) - }) + @DeleteProofApiDoc @DeleteMapping("/{talent-id}/proofs/{proof-id}") @PreAuthorize("hasRole('TALENT')") StatusDTO deleteProof(@PathVariable(value = "talent-id") long talentId, diff --git a/src/main/java/com/provedcode/talent/model/dto/FullTalentDTO.java b/src/main/java/com/provedcode/talent/model/dto/FullTalentDTO.java index 10d8885..b67b317 100644 --- a/src/main/java/com/provedcode/talent/model/dto/FullTalentDTO.java +++ b/src/main/java/com/provedcode/talent/model/dto/FullTalentDTO.java @@ -1,7 +1,7 @@ package com.provedcode.talent.model.dto; import com.fasterxml.jackson.annotation.JsonProperty; -import com.provedcode.annotations.UrlList; +import com.provedcode.util.annotations.UrlList; import jakarta.validation.constraints.NotEmpty; import lombok.Builder; diff --git a/src/main/java/com/provedcode/talent/model/entity/Talent.java b/src/main/java/com/provedcode/talent/model/entity/Talent.java index 8a0f294..49fdcbf 100644 --- a/src/main/java/com/provedcode/talent/model/entity/Talent.java +++ b/src/main/java/com/provedcode/talent/model/entity/Talent.java @@ -33,8 +33,11 @@ public class Talent { @Column(name = "specialization", length = 30) private String specialization; @URL - @Column(name = "image", length = 100) + @Column(name = "image", length = 1000) private String image; + @Column(name = "image_name", length = 100) + private String imageName; + @OneToOne(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) private TalentDescription talentDescription; @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) @@ -47,6 +50,4 @@ public class Talent { private List talentAttachedFiles = new ArrayList<>(); @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) private List talentProofs = new ArrayList<>(); - @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) - private List cudoses = new ArrayList<>(); } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/model/request/EditTalent.java b/src/main/java/com/provedcode/talent/model/request/EditTalent.java index 1014536..cc3dbc1 100644 --- a/src/main/java/com/provedcode/talent/model/request/EditTalent.java +++ b/src/main/java/com/provedcode/talent/model/request/EditTalent.java @@ -1,8 +1,7 @@ package com.provedcode.talent.model.request; import com.fasterxml.jackson.annotation.JsonProperty; -import com.provedcode.annotations.UrlList; -import jakarta.validation.constraints.NotEmpty; +import com.provedcode.util.annotations.UrlList; import lombok.Builder; import java.util.List; diff --git a/src/main/java/com/provedcode/talent/service/TalentProofService.java b/src/main/java/com/provedcode/talent/service/TalentProofService.java index ce4f605..3880350 100644 --- a/src/main/java/com/provedcode/talent/service/TalentProofService.java +++ b/src/main/java/com/provedcode/talent/service/TalentProofService.java @@ -31,7 +31,8 @@ import java.time.format.DateTimeFormatter; import java.util.Optional; -import static org.springframework.http.HttpStatus.*; +import static org.springframework.http.HttpStatus.FORBIDDEN; +import static org.springframework.http.HttpStatus.NOT_FOUND; @Service @AllArgsConstructor @@ -45,33 +46,15 @@ public class TalentProofService { ValidateTalentForCompliance validateTalentForCompliance; @Transactional(readOnly = true) - public Page getAllProofsPage(Optional page, Optional size, Optional orderBy, + public Page getAllProofsPage(Integer page, Integer size, String orderBy, String... sortBy) { - PageRequest pageRequest; - String sortDirection = orderBy.orElseGet(Sort.DEFAULT_DIRECTION::name); - - if (page.orElse(pageProperties.defaultPageNum()) < 0) { - throw new ResponseStatusException(BAD_REQUEST, "'page' query parameter must be greater than or equal to 0"); - } - if (size.orElse(pageProperties.defaultPageSize()) <= 0) { - throw new ResponseStatusException(BAD_REQUEST, "'size' query parameter must be greater than or equal to 1"); - } - if (!sortDirection.equalsIgnoreCase(Sort.Direction.ASC.name()) && - !sortDirection.equalsIgnoreCase(Sort.Direction.DESC.name())) { - throw new ResponseStatusException(BAD_REQUEST, "'direction' query param must be equals ASC or DESC"); - } - - try { - pageRequest = PageRequest.of( - page.orElse(pageProperties.defaultPageNum()), - size.orElse(pageProperties.defaultPageSize()), - Sort.Direction.valueOf(sortDirection.toUpperCase()), - sortBy - ); - return talentProofRepository.findByStatus(ProofStatus.PUBLISHED, pageRequest); - } catch (RuntimeException exception) { - throw new ResponseStatusException(BAD_REQUEST, exception.getMessage()); - } + PageRequest pageRequest = PageRequest.of( + page, + size, + Sort.Direction.valueOf(orderBy.toUpperCase()), + sortBy + ); + return talentProofRepository.findByStatus(ProofStatus.PUBLISHED, pageRequest); } @Transactional(readOnly = true) @@ -90,53 +73,23 @@ public TalentProof getTalentProof(long proofId, Authentication authentication) { } @Transactional(readOnly = true) - public FullProofDTO getTalentProofs(Long talentId, Optional page, Optional size, - Optional direction, Authentication authentication, - String... sortProperties) { + public FullProofDTO getTalentProofs(Long talentId, Integer page, Integer size, String direction, + Authentication authentication, String... sortProperties) { Talent talent = talentRepository.findById(talentId) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, - "Talent with id = %s not found".formatted( + "Talent with id = %d not found".formatted( talentId))); - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); - Page proofs; - PageRequest pageRequest; - String sortDirection = direction.orElseGet(Sort.DEFAULT_DIRECTION::name); - - if (page.orElse(pageProperties.defaultPageNum()) < 0) { - throw new ResponseStatusException(BAD_REQUEST, "'page' query parameter must be greater than or equal to 0"); - } - if (size.orElse(pageProperties.defaultPageSize()) <= 0) { - throw new ResponseStatusException(BAD_REQUEST, "'size' query parameter must be greater than or equal to 1"); - } - if (!sortDirection.equalsIgnoreCase(Sort.Direction.ASC.name()) && - !sortDirection.equalsIgnoreCase(Sort.Direction.DESC.name())) { - throw new ResponseStatusException(BAD_REQUEST, "'direction' query param must be equals ASC or DESC"); - } - - try { - pageRequest = PageRequest.of( - page.orElse(pageProperties.defaultPageNum()), - size.orElse(pageProperties.defaultPageSize()), - Sort.Direction.valueOf(sortDirection.toUpperCase()), - sortProperties - ); - if (!userInfo.getTalent().getId().equals(talentId)) { - proofs = talentProofRepository.findByTalentIdAndStatus(talentId, ProofStatus.PUBLISHED, pageRequest); - } else { - proofs = talentProofRepository.findByTalentId(talentId, pageRequest); - } -// if (!userInfo.getLogin().equals(authentication.getName())) { -// proofs = talentProofRepository.findByTalentIdAndStatus(talentId, ProofStatus.PUBLISHED, pageRequest); -// } else { -// proofs = talentProofRepository.findByTalentId(talentId, pageRequest); -// } - } catch (RuntimeException exception) { - throw new ResponseStatusException(BAD_REQUEST, exception.getMessage()); + PageRequest pageRequest = PageRequest.of(page, size, Sort.Direction.valueOf(direction.toUpperCase()), + sortProperties + ); + if (!userInfo.getTalent().getId().equals(talentId)) { + proofs = talentProofRepository.findByTalentIdAndStatus(talentId, ProofStatus.PUBLISHED, pageRequest); + } else { + proofs = talentProofRepository.findByTalentId(talentId, pageRequest); } - return FullProofDTO.builder() .id(talent.getId()) .image(talent.getImage()) @@ -166,7 +119,6 @@ public ResponseEntity addProof(AddProof addProof, long talentId, Authenticati .status(ProofStatus.DRAFT) .created(LocalDateTime.now()) .build(); - talentProofRepository.save(talentProof); URI location = ServletUriComponentsBuilder diff --git a/src/main/java/com/provedcode/talent/service/TalentService.java b/src/main/java/com/provedcode/talent/service/TalentService.java index 93fb180..48a854d 100644 --- a/src/main/java/com/provedcode/talent/service/TalentService.java +++ b/src/main/java/com/provedcode/talent/service/TalentService.java @@ -1,22 +1,151 @@ package com.provedcode.talent.service; -import com.provedcode.talent.model.dto.ShortTalentDTO; -import com.provedcode.talent.model.entity.Talent; +import com.provedcode.config.PageProperties; +import com.provedcode.talent.model.entity.*; import com.provedcode.talent.model.request.EditTalent; +import com.provedcode.talent.repo.TalentProofRepository; +import com.provedcode.talent.repo.TalentRepository; +import com.provedcode.talent.utill.ValidateTalentForCompliance; import com.provedcode.user.model.dto.SessionInfoDTO; -import org.springframework.security.core.Authentication; +import com.provedcode.user.model.entity.UserInfo; +import com.provedcode.user.repo.AuthorityRepository; +import com.provedcode.user.repo.UserInfoRepository; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; -import com.provedcode.talent.model.dto.FullTalentDTO; +import org.springframework.data.domain.PageRequest; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.server.ResponseStatusException; +import java.util.List; import java.util.Optional; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.NOT_FOUND; + +@Service +@Slf4j +@AllArgsConstructor +@Transactional +public class TalentService { + AuthorityRepository authorityRepository; + TalentProofRepository talentProofRepository; + TalentRepository talentRepository; + UserInfoRepository userInfoRepository; + PageProperties pageProperties; + ValidateTalentForCompliance validateTalentForCompliance; + + @Transactional(readOnly = true) + public Page getTalentsPage(Integer page, Integer size) { + return talentRepository.findAll(PageRequest.of(page, size)); + } + + @Transactional(readOnly = true) + public Talent getTalentById(long id) { + return talentRepository.findById(id).orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); + } + + public Talent editTalent(long id, EditTalent editTalent, Authentication authentication) { + Optional talent = talentRepository.findById(id); + Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); + validateTalentForCompliance.userVerification(talent, userInfo, id); + checkEditTalentNull(editTalent); + + Talent editableTalent = talent.get(); + + TalentDescription editableTalentDescription = editableTalent.getTalentDescription(); + List editableTalentTalents = editableTalent.getTalentTalents(); + List editableTalentLinks = editableTalent.getTalentLinks(); + List editableTalentContacts = editableTalent.getTalentContacts(); + List editableTalentAttachedFiles = editableTalent.getTalentAttachedFiles(); + + if (editTalent.firstName() != null) { + editableTalent.setFirstName(editTalent.firstName()); + } + if (editTalent.lastName() != null) { + editableTalent.setLastName(editTalent.lastName()); + } + if (editTalent.specialization() != null) { + editableTalent.setSpecialization(editTalent.specialization()); + } + if (editTalent.image() != null) { + editableTalent.setImage(editTalent.image()); + } + if (editTalent.additionalInfo() != null || editTalent.bio() != null) { + if (editableTalentDescription != null) { + if (editTalent.additionalInfo() != null) + editableTalentDescription.setAdditionalInfo(editTalent.additionalInfo()); + if (editTalent.bio() != null) + editableTalentDescription.setBio(editTalent.bio()); + } else { + editableTalentDescription = TalentDescription.builder() + .additionalInfo(editTalent.additionalInfo()) + .bio(editTalent.bio()) + .talent(editableTalent) + .build(); + } + editableTalent.setTalentDescription(editableTalentDescription); + } + if (editTalent.talents() != null) { + editableTalentTalents.clear(); + editableTalentTalents.addAll(editTalent.talents().stream().map(s -> TalentTalents.builder() + .talent(editableTalent) + .talentName(s) + .build()).toList()); + editableTalent.setTalentTalents(editableTalentTalents); + } + if (editTalent.links() != null) { + editableTalentLinks.clear(); + editableTalentLinks.addAll(editTalent.links().stream().map(s -> TalentLink.builder() + .talent(editableTalent) + .link(s) + .build()).toList()); + editableTalent.setTalentLinks(editableTalentLinks); + } + if (editTalent.contacts() != null) { + editableTalentContacts.clear(); + editableTalentContacts.addAll(editTalent.contacts().stream().map(s -> TalentContact.builder() + .talent(editableTalent) + .contact(s) + .build()).toList()); + editableTalent.setTalentContacts(editableTalentContacts); + } + if (editTalent.attachedFiles() != null) { + editableTalentAttachedFiles.clear(); + editableTalentAttachedFiles.addAll(editTalent.attachedFiles().stream().map(s -> TalentAttachedFile.builder() + .talent(editableTalent) + .attachedFile( + s) + .build()) + .toList()); + editableTalent.setTalentAttachedFiles(editableTalentAttachedFiles); + } + return talentRepository.save(editableTalent); + } + + public SessionInfoDTO deleteTalentById(long id, Authentication authentication) { + Optional talent = talentRepository.findById(id); + Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); + + validateTalentForCompliance.userVerification(talent, userInfo, id); -public interface TalentService { - Page getTalentsPage(Optional page, Optional size); + UserInfo user = userInfo.get(); + Talent entity = talent.get(); - Talent getTalentById(long id); + user.getAuthorities().clear(); + userInfoRepository.delete(user); + talentRepository.delete(entity); - Talent editTalent(long id, EditTalent editTalent, Authentication authentication); + return new SessionInfoDTO("deleted", "null"); + } - SessionInfoDTO deleteTalentById(long id, Authentication authentication); + private void checkEditTalentNull(EditTalent editTalent) { + if (editTalent.firstName() == null && editTalent.lastName() == null && editTalent.image() == null && + editTalent.specialization() == null && editTalent.additionalInfo() == null && editTalent.bio() == null && + editTalent.talents() == null && editTalent.links() == null && editTalent.contacts() == null && + editTalent.attachedFiles() == null) + throw new ResponseStatusException(BAD_REQUEST, "you did not provide information to make changes"); + } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/service/impl/TalentServiceImpl.java b/src/main/java/com/provedcode/talent/service/impl/TalentServiceImpl.java deleted file mode 100644 index 29939c7..0000000 --- a/src/main/java/com/provedcode/talent/service/impl/TalentServiceImpl.java +++ /dev/null @@ -1,163 +0,0 @@ -package com.provedcode.talent.service.impl; - -import com.provedcode.config.PageProperties; -import com.provedcode.talent.model.entity.*; -import com.provedcode.talent.model.request.EditTalent; -import com.provedcode.talent.repo.TalentProofRepository; -import com.provedcode.talent.repo.TalentRepository; -import com.provedcode.talent.service.TalentService; -import com.provedcode.talent.utill.ValidateTalentForCompliance; -import com.provedcode.user.model.dto.SessionInfoDTO; -import com.provedcode.user.model.entity.UserInfo; -import com.provedcode.user.repo.AuthorityRepository; -import com.provedcode.user.repo.UserInfoRepository; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.server.ResponseStatusException; - -import java.util.List; -import java.util.Optional; - -import static org.springframework.http.HttpStatus.*; - -@Service -@Slf4j -@AllArgsConstructor -@Transactional -public class TalentServiceImpl implements TalentService { - AuthorityRepository authorityRepository; - TalentProofRepository talentProofRepository; - TalentRepository talentRepository; - UserInfoRepository userInfoRepository; - PageProperties pageProperties; - ValidateTalentForCompliance validateTalentForCompliance; - - @Override - @Transactional(readOnly = true) - public Page getTalentsPage(Optional page, Optional size) { - if (page.orElse(pageProperties.defaultPageNum()) < 0) { - throw new ResponseStatusException(BAD_REQUEST, "'page' query parameter must be greater than or equal to 0"); - } - if (size.orElse(pageProperties.defaultPageSize()) <= 0) { - throw new ResponseStatusException(BAD_REQUEST, "'size' query parameter must be greater than or equal to 1"); - } - return talentRepository.findAll(PageRequest.of(page.orElse(pageProperties.defaultPageNum()), - size.orElse(pageProperties.defaultPageSize()))); - } - - @Override - @Transactional(readOnly = true) - public Talent getTalentById(long id) { - Optional talent = talentRepository.findById(id); - if (talent.isEmpty()) { - throw new ResponseStatusException(NOT_FOUND, String.format("talent with id = %d not found", id)); - } - return talent.get(); - } - - @Override - public Talent editTalent(long id, EditTalent editTalent, Authentication authentication) { - if (editTalent.firstName() == null && editTalent.lastName() == null && editTalent.image() == null && - editTalent.specialization() == null && editTalent.additionalInfo() == null && editTalent.bio() == null && - editTalent.talents() == null && editTalent.links() == null && editTalent.contacts() == null && - editTalent.attachedFiles() == null) - throw new ResponseStatusException(BAD_REQUEST, "you did not provide information to make changes"); - - Optional talent = talentRepository.findById(id); - Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); - - validateTalentForCompliance.userVerification(talent, userInfo, id); - - Talent editableTalent = talent.get(); - long idEditableTalent = editableTalent.getId(); - - TalentDescription editableTalentDescription = editableTalent.getTalentDescription(); - List editableTalentTalents = editableTalent.getTalentTalents(); - List editableTalentLinks = editableTalent.getTalentLinks(); - List editableTalentContacts = editableTalent.getTalentContacts(); - List editableTalentAttachedFile = editableTalent.getTalentAttachedFiles(); - - if (editableTalentDescription != null) { - editableTalentDescription - .setAdditionalInfo(editTalent.additionalInfo() != null ? editTalent.additionalInfo() - : editableTalentDescription.getAdditionalInfo()) - .setBio(editTalent.bio() != null ? editTalent.bio() : editableTalentDescription.getBio()); - } else { - editableTalentDescription = TalentDescription.builder() - .additionalInfo(editTalent.additionalInfo()) - .bio(editTalent.bio()) - .talent(editableTalent) - .build(); - } - - if (editTalent.talents() != null) { - editableTalentTalents.clear(); - editableTalentTalents.addAll(editTalent.talents().stream().map(s -> TalentTalents.builder() - .talent(editableTalent) - .talentName(s) - .build()).toList()); - } - - if (editTalent.links() != null) { - editableTalentLinks.clear(); - editableTalentLinks.addAll(editTalent.links().stream().map(l -> TalentLink.builder() - .talent(editableTalent) - .link(l) - .build()).toList()); - } - - if (editTalent.contacts() != null) { - editableTalentContacts.clear(); - editableTalentContacts.addAll(editTalent.contacts().stream().map(s -> TalentContact.builder() - .talent(editableTalent) - .contact(s) - .build()).toList()); - } - - if (editTalent.attachedFiles() != null) { - editableTalentAttachedFile.clear(); - editableTalentAttachedFile.addAll(editTalent.attachedFiles().stream().map(s -> TalentAttachedFile.builder() - .talent(editableTalent) - .attachedFile( - s) - .build()) - .toList()); - } - - editableTalent.setFirstName( - editTalent.firstName() != null ? editTalent.firstName() : editableTalent.getFirstName()) - .setLastName(editTalent.lastName() != null ? editTalent.lastName() : editableTalent.getLastName()) - .setSpecialization(editTalent.specialization() != null ? editTalent.specialization() - : editableTalent.getSpecialization()) - .setImage(editTalent.image() != null ? editTalent.image() : editableTalent.getImage()) - .setTalentDescription(editableTalentDescription) - .setTalentTalents(editableTalentTalents) - .setTalentLinks(editableTalentLinks) - .setTalentContacts(editableTalentContacts) - .setTalentAttachedFiles(editableTalentAttachedFile); - - return talentRepository.save(editableTalent); - } - - @Override - public SessionInfoDTO deleteTalentById(long id, Authentication authentication) { - Optional talent = talentRepository.findById(id); - Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); - - validateTalentForCompliance.userVerification(talent, userInfo, id); - - UserInfo user = userInfo.orElseThrow(() -> new ResponseStatusException(NOT_IMPLEMENTED)); - Talent entity = talent.orElseThrow(() -> new ResponseStatusException(NOT_IMPLEMENTED)); - - user.getAuthorities().clear(); - userInfoRepository.delete(user); - talentRepository.delete(entity); - - return new SessionInfoDTO("deleted", "null"); - } -} \ No newline at end of file diff --git a/src/main/java/com/provedcode/user/controller/AuthenticationController.java b/src/main/java/com/provedcode/user/controller/AuthenticationController.java index 2be97f2..b30ee13 100644 --- a/src/main/java/com/provedcode/user/controller/AuthenticationController.java +++ b/src/main/java/com/provedcode/user/controller/AuthenticationController.java @@ -1,68 +1,43 @@ package com.provedcode.user.controller; -import com.provedcode.user.model.dto.RegistrationDTO; +import com.provedcode.user.model.dto.SponsorRegistrationDTO; +import com.provedcode.user.model.dto.TalentRegistrationDTO; import com.provedcode.user.model.dto.UserInfoDTO; import com.provedcode.user.service.AuthenticationService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; +import com.provedcode.util.annotations.doc.controller.user.PostSponsorRegistrationApiDoc; +import com.provedcode.util.annotations.doc.controller.user.PostTalentRegistrationApiDoc; +import com.provedcode.util.annotations.doc.controller.user.PostUserLoginApiDoc; import jakarta.validation.Valid; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; @RestController @AllArgsConstructor @Slf4j -@RequestMapping("/api/v2/talents") +@RequestMapping("/api") public class AuthenticationController { AuthenticationService authenticationService; - @Operation(summary = "Login") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", - description = "SUCCESS", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = UserInfoDTO.class))), - @ApiResponse(responseCode = "404", - description = "NOT_FOUND (Talent not registered)", - content = @Content), - @ApiResponse( - responseCode = "400", - description = "BAD_REQUEST", - content = @Content), - @ApiResponse( - responseCode = "401", - description = "UNAUTHORIZED", - content = @Content) - }) - @PostMapping("/login") + @PostUserLoginApiDoc + @PostMapping("/v2/login") UserInfoDTO login(Authentication authentication) { return authenticationService.login(authentication.getName(), authentication.getAuthorities()); } - @Operation(summary = "Talent Registration") - @ApiResponses(value = { - @ApiResponse(responseCode = "201", - description = "CREATED", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = UserInfoDTO.class))), - @ApiResponse(responseCode = "409", - description = "CONFLICT (user with login already exists)", - content = @Content), - @ApiResponse( - responseCode = "400", - description = "BAD_REQUEST", - content = @Content), - }) - @PostMapping("/register") + @PostTalentRegistrationApiDoc + @PostMapping("/v2/talents/register") @ResponseStatus(HttpStatus.CREATED) - UserInfoDTO register(@RequestBody @Valid RegistrationDTO user) { + UserInfoDTO register(@RequestBody @Valid TalentRegistrationDTO user) { + return authenticationService.register(user); + } + + @PostSponsorRegistrationApiDoc + @PostMapping("/v3/sponsors/register") + @ResponseStatus(HttpStatus.CREATED) + UserInfoDTO register(@RequestBody @Valid SponsorRegistrationDTO user) { return authenticationService.register(user); } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/user/model/Role.java b/src/main/java/com/provedcode/user/model/Role.java index d63f679..2c2cbbd 100644 --- a/src/main/java/com/provedcode/user/model/Role.java +++ b/src/main/java/com/provedcode/user/model/Role.java @@ -3,7 +3,8 @@ import org.springframework.security.core.GrantedAuthority; public enum Role implements GrantedAuthority { - TALENT("ROLE_TALENT"); + TALENT("ROLE_TALENT"), + SPONSOR("ROLE_SPONSOR"); private final String userRole; Role(String role) { diff --git a/src/main/java/com/provedcode/user/model/dto/SponsorRegistrationDTO.java b/src/main/java/com/provedcode/user/model/dto/SponsorRegistrationDTO.java new file mode 100644 index 0000000..27e8485 --- /dev/null +++ b/src/main/java/com/provedcode/user/model/dto/SponsorRegistrationDTO.java @@ -0,0 +1,20 @@ +package com.provedcode.user.model.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotEmpty; + +public record SponsorRegistrationDTO( + @NotEmpty + @Email + String login, + @NotEmpty + String password, + @JsonProperty("first_name") + @NotEmpty + String firstName, + @JsonProperty("last_name") + @NotEmpty + String lastName +) { +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/user/model/dto/RegistrationDTO.java b/src/main/java/com/provedcode/user/model/dto/TalentRegistrationDTO.java similarity index 93% rename from src/main/java/com/provedcode/user/model/dto/RegistrationDTO.java rename to src/main/java/com/provedcode/user/model/dto/TalentRegistrationDTO.java index a5a4105..5ebd11a 100644 --- a/src/main/java/com/provedcode/user/model/dto/RegistrationDTO.java +++ b/src/main/java/com/provedcode/user/model/dto/TalentRegistrationDTO.java @@ -6,7 +6,7 @@ import lombok.Builder; @Builder -public record RegistrationDTO( +public record TalentRegistrationDTO( @NotEmpty @Email String login, diff --git a/src/main/java/com/provedcode/user/model/dto/UserInfoDTO.java b/src/main/java/com/provedcode/user/model/dto/UserInfoDTO.java index a2423fd..4c2671d 100644 --- a/src/main/java/com/provedcode/user/model/dto/UserInfoDTO.java +++ b/src/main/java/com/provedcode/user/model/dto/UserInfoDTO.java @@ -5,6 +5,7 @@ @Builder public record UserInfoDTO( String token, - Long id + Long id, + String role ) { } \ No newline at end of file diff --git a/src/main/java/com/provedcode/user/model/entity/UserInfo.java b/src/main/java/com/provedcode/user/model/entity/UserInfo.java index 7714b77..852d0b8 100644 --- a/src/main/java/com/provedcode/user/model/entity/UserInfo.java +++ b/src/main/java/com/provedcode/user/model/entity/UserInfo.java @@ -1,5 +1,6 @@ package com.provedcode.user.model.entity; +import com.provedcode.sponsor.model.entity.Sponsor; import com.provedcode.talent.model.entity.Talent; import jakarta.persistence.*; import jakarta.validation.constraints.NotEmpty; @@ -21,10 +22,12 @@ public class UserInfo { @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; - @NotNull @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "talent_id", updatable = false) private Talent talent; + @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "sponsor_id", updatable = false) + private Sponsor sponsor; @NotEmpty @NotNull @Column(name = "login", length = 100) diff --git a/src/main/java/com/provedcode/user/service/AuthenticationService.java b/src/main/java/com/provedcode/user/service/AuthenticationService.java index 7814ac8..57b7bcd 100644 --- a/src/main/java/com/provedcode/user/service/AuthenticationService.java +++ b/src/main/java/com/provedcode/user/service/AuthenticationService.java @@ -1,6 +1,7 @@ package com.provedcode.user.service; -import com.provedcode.user.model.dto.RegistrationDTO; +import com.provedcode.user.model.dto.SponsorRegistrationDTO; +import com.provedcode.user.model.dto.TalentRegistrationDTO; import com.provedcode.user.model.dto.UserInfoDTO; import org.springframework.security.core.GrantedAuthority; @@ -8,5 +9,6 @@ public interface AuthenticationService { UserInfoDTO login(String name, Collection authorities); - UserInfoDTO register(RegistrationDTO user); + UserInfoDTO register(TalentRegistrationDTO user); + UserInfoDTO register(SponsorRegistrationDTO user); } diff --git a/src/main/java/com/provedcode/user/service/impl/AuthenticationServiceImpl.java b/src/main/java/com/provedcode/user/service/impl/AuthenticationServiceImpl.java index 0346c35..9fbd2b2 100644 --- a/src/main/java/com/provedcode/user/service/impl/AuthenticationServiceImpl.java +++ b/src/main/java/com/provedcode/user/service/impl/AuthenticationServiceImpl.java @@ -1,9 +1,12 @@ package com.provedcode.user.service.impl; +import com.provedcode.sponsor.model.entity.Sponsor; +import com.provedcode.sponsor.repository.SponsorRepository; import com.provedcode.talent.model.entity.Talent; import com.provedcode.talent.repo.TalentRepository; import com.provedcode.user.model.Role; -import com.provedcode.user.model.dto.RegistrationDTO; +import com.provedcode.user.model.dto.SponsorRegistrationDTO; +import com.provedcode.user.model.dto.TalentRegistrationDTO; import com.provedcode.user.model.dto.UserInfoDTO; import com.provedcode.user.model.entity.Authority; import com.provedcode.user.model.entity.UserInfo; @@ -37,41 +40,81 @@ public class AuthenticationServiceImpl implements AuthenticationService { JwtEncoder jwtEncoder; UserInfoRepository userInfoRepository; - TalentRepository talentEntityRepository; + TalentRepository talentRepository; + SponsorRepository sponsorRepository; AuthorityRepository authorityRepository; PasswordEncoder passwordEncoder; @Transactional(readOnly = true) public UserInfoDTO login(String name, Collection authorities) { UserInfo userInfo = userInfoRepository.findByLogin(name) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, String.format( - "talent with name = %s not found", name))); + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, String.format( + "user with login = %s not found", name))); + + Role userRole = userInfo.getAuthorities().stream().findFirst().orElseThrow().getAuthority(); return UserInfoDTO.builder() - .token(generateJWTToken(name, authorities)) - .id(userInfo.getTalent().getId()) - .build(); + .token(generateJWTToken(name, authorities)) + .id(userRole.equals(Role.TALENT) ? userInfo.getTalent().getId() + : userInfo.getSponsor().getId()) + .role(userRole.name()) + .build(); } - public UserInfoDTO register(RegistrationDTO user) { + public UserInfoDTO register(TalentRegistrationDTO user) { if (userInfoRepository.existsByLogin(user.login())) { throw new ResponseStatusException(HttpStatus.CONFLICT, - String.format("user with login = {%s} already exists", user.login())); + String.format("user with login = {%s} already exists", user.login())); } Talent talent = Talent.builder() - .firstName(user.firstName()) - .lastName(user.lastName()) - .specialization(user.specialization()) - .build(); - talentEntityRepository.save(talent); + .firstName(user.firstName()) + .lastName(user.lastName()) + .specialization(user.specialization()) + .build(); + talentRepository.save(talent); + + UserInfo userInfo = UserInfo.builder() + .talent(talent) + .login(user.login()) + .password(passwordEncoder.encode(user.password())) + .authorities(Set.of(authorityRepository.findByAuthority(Role.TALENT).orElseThrow())) + .build(); + userInfoRepository.save(userInfo); + + String userLogin = userInfo.getLogin(); + Collection userAuthorities = userInfo.getAuthorities().stream().map( + Authority::getAuthority).toList(); + + log.info("user with login {%s} was saved, his authorities: %s".formatted(userLogin, userAuthorities)); + + return UserInfoDTO.builder() + .token(generateJWTToken(userLogin, userAuthorities)) + .id(talent.getId()) + .role(Role.TALENT.name()) + .build(); + } + + public UserInfoDTO register(SponsorRegistrationDTO user) { + if (userInfoRepository.existsByLogin(user.login())) { + throw new ResponseStatusException(HttpStatus.CONFLICT, + String.format("user with login = {%s} already exists", user.login())); + } + + Sponsor sponsor = Sponsor.builder() + .firstName(user.firstName()) + .amountKudos(0L) + .lastName(user.lastName()) + .build(); + sponsorRepository.save(sponsor); UserInfo userInfo = UserInfo.builder() - .talent(talent) - .login(user.login()) - .password(passwordEncoder.encode(user.password())) - .authorities(Set.of(authorityRepository.findByAuthority(Role.TALENT).orElseThrow())) - .build(); + .sponsor(sponsor) + .login(user.login()) + .password(passwordEncoder.encode(user.password())) + .authorities( + Set.of(authorityRepository.findByAuthority(Role.SPONSOR).orElseThrow())) + .build(); userInfoRepository.save(userInfo); String userLogin = userInfo.getLogin(); @@ -81,9 +124,10 @@ public UserInfoDTO register(RegistrationDTO user) { log.info("user with login {%s} was saved, his authorities: %s".formatted(userLogin, userAuthorities)); return UserInfoDTO.builder() - .token(generateJWTToken(userLogin, userAuthorities)) - .id(talent.getId()) - .build(); + .token(generateJWTToken(userLogin, userAuthorities)) + .id(sponsor.getId()) + .role(Role.SPONSOR.name()) + .build(); } private String generateJWTToken(String name, Collection authorities) { @@ -91,13 +135,13 @@ private String generateJWTToken(String name, Collection new ResponseStatusException(NOT_FOUND, + "Sponsor with login = %s not found".formatted( + login))); + } +} diff --git a/src/main/java/com/provedcode/util/PhotoService.java b/src/main/java/com/provedcode/util/PhotoService.java new file mode 100644 index 0000000..97a1c41 --- /dev/null +++ b/src/main/java/com/provedcode/util/PhotoService.java @@ -0,0 +1,49 @@ +package com.provedcode.util; + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.List; + +import static org.apache.http.entity.ContentType.*; + + +@Service +@AllArgsConstructor +public class PhotoService { + public File degradePhoto(File photoFile) throws IOException { + // Load image from file + BufferedImage originalImage = ImageIO.read(photoFile); + + // New size for image + int newWidth = 300; + int newHeight = 300; + + // Creating new image with new size + Image resizedImage = originalImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH); + + // создаем новый файл для уменьшенного изображения + String fileName = photoFile.getName(); + String fileType = fileName.substring(fileName.lastIndexOf('.') + 1); + File newFile = new File(photoFile.getParent(), fileName); + + // записываем уменьшенное изображение в новый файл + BufferedImage outputImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB); + outputImage.createGraphics().drawImage(resizedImage, 0, 0, null); + ImageIO.write(outputImage, fileType, newFile); + + // возвращаем новый файл + return newFile; + } + + public boolean isFileImage(MultipartFile file) { + return !List.of(IMAGE_JPEG.getMimeType(), IMAGE_PNG.getMimeType(), IMAGE_GIF.getMimeType()) + .contains(file.getContentType()); + } +} diff --git a/src/main/java/com/provedcode/annotations/UrlList.java b/src/main/java/com/provedcode/util/annotations/UrlList.java similarity index 84% rename from src/main/java/com/provedcode/annotations/UrlList.java rename to src/main/java/com/provedcode/util/annotations/UrlList.java index 6a792bc..1530ae9 100644 --- a/src/main/java/com/provedcode/annotations/UrlList.java +++ b/src/main/java/com/provedcode/util/annotations/UrlList.java @@ -1,6 +1,6 @@ -package com.provedcode.annotations; +package com.provedcode.util.annotations; -import com.provedcode.annotations.impl.UrlListValidator; +import com.provedcode.util.annotations.impl.UrlListValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/aws/GetAllAWSBucketFilesDevApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/aws/GetAllAWSBucketFilesDevApiDoc.java new file mode 100644 index 0000000..7e45042 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/aws/GetAllAWSBucketFilesDevApiDoc.java @@ -0,0 +1,34 @@ +package com.provedcode.util.annotations.doc.controller.aws; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Dev`s endpoint, uses to get names of all files at AWS S3") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS"), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content), + @ApiResponse( + responseCode = "503", + description = "SERVICE UNAVAILABLE (connection to AWS S3 failed)", + content = @Content + ) +}) +public @interface GetAllAWSBucketFilesDevApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/aws/GetFileInfoDevApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/aws/GetFileInfoDevApiDoc.java new file mode 100644 index 0000000..a11c8c0 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/aws/GetFileInfoDevApiDoc.java @@ -0,0 +1,29 @@ +package com.provedcode.util.annotations.doc.controller.aws; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Dev`s endpoint, uses to get information about file") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS"), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content) +}) +public @interface GetFileInfoDevApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/aws/PostSetNewUserImageApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/aws/PostSetNewUserImageApiDoc.java new file mode 100644 index 0000000..562e1f1 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/aws/PostSetNewUserImageApiDoc.java @@ -0,0 +1,42 @@ +package com.provedcode.util.annotations.doc.controller.aws; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Set new Talent`s image") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS"), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content), + @ApiResponse( + responseCode = "403", + description = "FORBIDDEN", + content = @Content), + @ApiResponse( + responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "503", + description = "SERVICE UNAVAILABLE (connection to AWS S3 failed)", + content = @Content + ) +}) +public @interface PostSetNewUserImageApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/kudos/GetAmountOfKudosApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/kudos/GetAmountOfKudosApiDoc.java new file mode 100644 index 0000000..9ea3669 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/kudos/GetAmountOfKudosApiDoc.java @@ -0,0 +1,42 @@ +package com.provedcode.util.annotations.doc.controller.kudos; + +import com.provedcode.kudos.model.response.KudosAmountWithSponsor; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Amount of “kudos” given by sponsors and who gave the “kudos” on proof") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = KudosAmountWithSponsor.class))), + @ApiResponse(responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content), + @ApiResponse( + responseCode = "403", + description = "FORBIDDEN (if not the talent wants to see)", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST", + content = @Content) +}) +public @interface GetAmountOfKudosApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/kudos/GetKudosForSponsorApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/kudos/GetKudosForSponsorApiDoc.java new file mode 100644 index 0000000..2798f09 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/kudos/GetKudosForSponsorApiDoc.java @@ -0,0 +1,42 @@ +package com.provedcode.util.annotations.doc.controller.kudos; + + +import com.provedcode.kudos.model.response.KudosAmount; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Get all available kudos from a sponsor") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = KudosAmount.class))), + @ApiResponse(responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content), + @ApiResponse( + responseCode = "403", + description = "FORBIDDEN (if not the owner wants to see other sponsor kudos)", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST", + content = @Content) +}) +public @interface GetKudosForSponsorApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/kudos/PostAddKudosToProofApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/kudos/PostAddKudosToProofApiDoc.java new file mode 100644 index 0000000..77d5ed6 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/kudos/PostAddKudosToProofApiDoc.java @@ -0,0 +1,37 @@ +package com.provedcode.util.annotations.doc.controller.kudos; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "As a sponsor I want to estimate talent proof by giving kudos") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content), + @ApiResponse(responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content), + @ApiResponse( + responseCode = "403", + description = "FORBIDDEN (if sponsor does not have enough kudos)", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST", + content = @Content) +}) +public @interface PostAddKudosToProofApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/proof/DeleteProofApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/proof/DeleteProofApiDoc.java new file mode 100644 index 0000000..5f77466 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/proof/DeleteProofApiDoc.java @@ -0,0 +1,43 @@ +package com.provedcode.util.annotations.doc.controller.proof; + +import com.provedcode.talent.model.dto.StatusDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Delete proof", + description = "As a talent I want to have an opportunity to delete my personal proofs") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = StatusDTO.class))), + @ApiResponse(responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD_REQUEST, (incorrect talent-id,proof-id)", + content = @Content), + @ApiResponse( + responseCode = "403", + description = "FORBIDDEN (if not the owner wants to delete the proof or " + + "impossible change proofs status from DRAFT to HIDDEN, it should be PUBLISHED)", + content = @Content) +}) +public @interface DeleteProofApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetAllProofsApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetAllProofsApiDoc.java new file mode 100644 index 0000000..514600d --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetAllProofsApiDoc.java @@ -0,0 +1,35 @@ +package com.provedcode.util.annotations.doc.controller.proof; + +import com.provedcode.talent.model.dto.ProofDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.data.domain.Page; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Get all proofs", + description = "As a guest I want to see a list of all proofs displayed anonymously") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = Page.class, subTypes = {ProofDTO.class}))), + @ApiResponse(responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST, parameter: page, size or order-by are incorrect", + content = @Content) +}) +public @interface GetAllProofsApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetTalentInformationWithProofsApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetTalentInformationWithProofsApiDoc.java new file mode 100644 index 0000000..1d6a200 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetTalentInformationWithProofsApiDoc.java @@ -0,0 +1,38 @@ +package com.provedcode.util.annotations.doc.controller.proof; + +import com.provedcode.talent.model.dto.FullProofDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Get all talent proofs", + description = "As a talent I want to see all proofs in personal profile page") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = FullProofDTO.class))), + @ApiResponse(responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST, wrong @RequestParam like page, size, order-by, sort-by or incorrect talent-id", + content = @Content) +}) +public @interface GetTalentInformationWithProofsApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetTalentProofByProofIdApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetTalentProofByProofIdApiDoc.java new file mode 100644 index 0000000..89ef17d --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetTalentProofByProofIdApiDoc.java @@ -0,0 +1,37 @@ +package com.provedcode.util.annotations.doc.controller.proof; + +import com.provedcode.talent.model.dto.ProofDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Get proof") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = ProofDTO.class))), + @ApiResponse(responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST, parameter: page, proof-id or size are incorrect", + content = @Content) +}) +public @interface GetTalentProofByProofIdApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/proof/PatchEditProofApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/proof/PatchEditProofApiDoc.java new file mode 100644 index 0000000..9dca387 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/proof/PatchEditProofApiDoc.java @@ -0,0 +1,42 @@ +package com.provedcode.util.annotations.doc.controller.proof; + +import com.provedcode.talent.model.dto.ProofDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Edit information about proof", + description = "As a talent I want to have an opportunity to edit my personal proofs") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = ProofDTO.class))), + @ApiResponse(responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "Unauthorized", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST, (wrong data to edit or incorrect talent-id, proof-id)", + content = @Content), + @ApiResponse( + responseCode = "403", + description = "FORBIDDEN (if not the owner wants to edit the proof)", + content = @Content) +}) +public @interface PatchEditProofApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/proof/PostAddProofApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/proof/PostAddProofApiDoc.java new file mode 100644 index 0000000..13fe563 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/proof/PostAddProofApiDoc.java @@ -0,0 +1,48 @@ +package com.provedcode.util.annotations.doc.controller.proof; + +import com.provedcode.talent.model.dto.ProofDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.headers.Header; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Add proof", + description = "As a talent I want to have an opportunity to add my personal proof") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = ProofDTO.class)), + headers = {@Header(name = "Location", + description = "The URI of the created proof", + schema = @Schema(type = "string"))} + ), + @ApiResponse(responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "Unauthorized", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST, (wrong data to add or incorrect talent-id)", + content = @Content), + @ApiResponse( + responseCode = "403", + description = "FORBIDDEN (if not the owner wants to add the proof)", + content = @Content) +}) +public @interface PostAddProofApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/DeleteSponsorApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/DeleteSponsorApiDoc.java new file mode 100644 index 0000000..17968c1 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/DeleteSponsorApiDoc.java @@ -0,0 +1,42 @@ +package com.provedcode.util.annotations.doc.controller.sponsor; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Delete sponsor", + description = "As a sponsor I want to have an opportunity to delete personal accounts.") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content), + @ApiResponse(responseCode = "404", + description = "NOT FOUND ", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content), + @ApiResponse( + responseCode = "403", + description = "FORBIDDEN (if not the owner wants to delete the talent)", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST (incorrect id)", + content = @Content), + @ApiResponse( + responseCode = "501", + description = "NOT_IMPLEMENTED (login is not valid)", + content = @Content), +}) +public @interface DeleteSponsorApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/GetAllSponsorsApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/GetAllSponsorsApiDoc.java new file mode 100644 index 0000000..5423fac --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/GetAllSponsorsApiDoc.java @@ -0,0 +1,31 @@ +package com.provedcode.util.annotations.doc.controller.sponsor; + +import com.provedcode.sponsor.model.dto.SponsorDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.data.domain.Page; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Get all sponsors (SponsorDTO)") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = Page.class, subTypes = {SponsorDTO.class}))), + @ApiResponse( + responseCode = "400", + description = "BAD_REQUEST (parameter: page or size are incorrect)", + content = @Content) +}) +public @interface GetAllSponsorsApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/GetSponsorApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/GetSponsorApiDoc.java new file mode 100644 index 0000000..c194749 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/GetSponsorApiDoc.java @@ -0,0 +1,38 @@ +package com.provedcode.util.annotations.doc.controller.sponsor; + +import com.provedcode.sponsor.model.dto.SponsorDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Get sponsor", + description = "As a sponsor I want to have an opportunity to see my own profile with information") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = SponsorDTO.class))), + @ApiResponse(responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content), + @ApiResponse( + responseCode = "501", + description = "NOT_IMPLEMENTED (login is not valid)", + content = @Content) +}) +public @interface GetSponsorApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/PatchEditSponsorApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/PatchEditSponsorApiDoc.java new file mode 100644 index 0000000..dd5b45f --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/PatchEditSponsorApiDoc.java @@ -0,0 +1,47 @@ +package com.provedcode.util.annotations.doc.controller.sponsor; + +import com.provedcode.sponsor.model.dto.SponsorDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Edit information about sponsor", + description = "As a sponsor I want to have an opportunity to edit my personal profile by adding new information, " + + "changing already existing information.") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = SponsorDTO.class))), + @ApiResponse(responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content), + @ApiResponse( + responseCode = "403", + description = "FORBIDDEN (if not the owner wants to change the sponsor)", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST", + content = @Content), + @ApiResponse( + responseCode = "501", + description = "NOT_IMPLEMENTED (login is not valid)", + content = @Content) +}) +public @interface PatchEditSponsorApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/talent/DeleteTalentApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/talent/DeleteTalentApiDoc.java new file mode 100644 index 0000000..6f0fd00 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/talent/DeleteTalentApiDoc.java @@ -0,0 +1,38 @@ +package com.provedcode.util.annotations.doc.controller.talent; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Delete talent", + description = "As a talent I want to have an opportunity to delete personal accounts") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content), + @ApiResponse(responseCode = "404", + description = "NOT FOUND ", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content), + @ApiResponse( + responseCode = "403", + description = "FORBIDDEN (if not the owner wants to delete the talent)", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST (incorrect id)", + content = @Content) +}) +public @interface DeleteTalentApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/talent/GetAllTalentsApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/talent/GetAllTalentsApiDoc.java new file mode 100644 index 0000000..e5eea66 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/talent/GetAllTalentsApiDoc.java @@ -0,0 +1,35 @@ +package com.provedcode.util.annotations.doc.controller.talent; + +import com.provedcode.talent.model.dto.ShortTalentDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.data.domain.Page; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Get all talents (ShortTalentDTO)", + description = "As a guest I want to see a page with a list of all “talents” cards displayed with a short description about them") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = Page.class, subTypes = {ShortTalentDTO.class}))), + @ApiResponse(responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD_REQUEST (parameter: page or size are incorrect)", + content = @Content) +}) +public @interface GetAllTalentsApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/talent/GetTalentApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/talent/GetTalentApiDoc.java new file mode 100644 index 0000000..50b42e4 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/talent/GetTalentApiDoc.java @@ -0,0 +1,34 @@ +package com.provedcode.util.annotations.doc.controller.talent; + +import com.provedcode.talent.model.dto.FullTalentDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Get talent", + description = "As a talent I want to have an opportunity to see the full information about the talent") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = FullTalentDTO.class))), + @ApiResponse(responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content), +}) +public @interface GetTalentApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/talent/PatchEditTalentApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/talent/PatchEditTalentApiDoc.java new file mode 100644 index 0000000..565688e --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/talent/PatchEditTalentApiDoc.java @@ -0,0 +1,42 @@ +package com.provedcode.util.annotations.doc.controller.talent; + +import com.provedcode.talent.model.dto.FullTalentDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Edit information about talent", + description = "As a talent I want to have an opportunity to edit my personal profile by adding new information, changing already existing information") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = FullTalentDTO.class))), + @ApiResponse(responseCode = "404", + description = "NOT FOUND", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content), + @ApiResponse( + responseCode = "403", + description = "FORBIDDEN (if not the owner wants to change the talent)", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD REQUEST", + content = @Content) +}) +public @interface PatchEditTalentApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/user/PostSponsorRegistrationApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/user/PostSponsorRegistrationApiDoc.java new file mode 100644 index 0000000..608da55 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/user/PostSponsorRegistrationApiDoc.java @@ -0,0 +1,33 @@ +package com.provedcode.util.annotations.doc.controller.user; + +import com.provedcode.user.model.dto.UserInfoDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Sponsor Registration") +@ApiResponses(value = { + @ApiResponse(responseCode = "201", + description = "CREATED", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = UserInfoDTO.class))), + @ApiResponse(responseCode = "409", + description = "CONFLICT (user with login already exists)", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD_REQUEST", + content = @Content), +}) +public @interface PostSponsorRegistrationApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/user/PostTalentRegistrationApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/user/PostTalentRegistrationApiDoc.java new file mode 100644 index 0000000..1ed2517 --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/user/PostTalentRegistrationApiDoc.java @@ -0,0 +1,33 @@ +package com.provedcode.util.annotations.doc.controller.user; + +import com.provedcode.user.model.dto.UserInfoDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Talent Registration") +@ApiResponses(value = { + @ApiResponse(responseCode = "201", + description = "CREATED", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = UserInfoDTO.class))), + @ApiResponse(responseCode = "409", + description = "CONFLICT (user with login already exists)", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD_REQUEST", + content = @Content), +}) +public @interface PostTalentRegistrationApiDoc { +} diff --git a/src/main/java/com/provedcode/util/annotations/doc/controller/user/PostUserLoginApiDoc.java b/src/main/java/com/provedcode/util/annotations/doc/controller/user/PostUserLoginApiDoc.java new file mode 100644 index 0000000..7948e5c --- /dev/null +++ b/src/main/java/com/provedcode/util/annotations/doc/controller/user/PostUserLoginApiDoc.java @@ -0,0 +1,37 @@ +package com.provedcode.util.annotations.doc.controller.user; + +import com.provedcode.user.model.dto.UserInfoDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.MediaType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Operation(summary = "Login") +@ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "SUCCESS", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = UserInfoDTO.class))), + @ApiResponse(responseCode = "404", + description = "NOT_FOUND (Talent not registered)", + content = @Content), + @ApiResponse( + responseCode = "400", + description = "BAD_REQUEST", + content = @Content), + @ApiResponse( + responseCode = "401", + description = "UNAUTHORIZED", + content = @Content) +}) +public @interface PostUserLoginApiDoc { +} diff --git a/src/main/java/com/provedcode/annotations/impl/UrlListValidator.java b/src/main/java/com/provedcode/util/annotations/impl/UrlListValidator.java similarity index 88% rename from src/main/java/com/provedcode/annotations/impl/UrlListValidator.java rename to src/main/java/com/provedcode/util/annotations/impl/UrlListValidator.java index ac473d7..b06a1ac 100644 --- a/src/main/java/com/provedcode/annotations/impl/UrlListValidator.java +++ b/src/main/java/com/provedcode/util/annotations/impl/UrlListValidator.java @@ -1,6 +1,6 @@ -package com.provedcode.annotations.impl; +package com.provedcode.util.annotations.impl; -import com.provedcode.annotations.UrlList; +import com.provedcode.util.annotations.UrlList; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index b20a349..8b44fca 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -1,7 +1,5 @@ spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=sa spring.datasource.url=jdbc:h2:mem:./testdb;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE;DEFAULT_NULL_ORDERING=HIGH -spring.jpa.hibernate.ddl-auto=none -spring.sql.init.mode=always #logging.level.web=DEBUG logging.level.sql=DEBUG \ No newline at end of file diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index 810d9a1..b0ad889 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -1,5 +1,3 @@ spring.datasource.username=${DB_LOGIN} spring.datasource.password=${DB_PASSWORD} -spring.datasource.url=jdbc:postgresql://${DB_URL} -spring.jpa.hibernate.ddl-auto=none -spring.sql.init.mode=always \ No newline at end of file +spring.datasource.url=jdbc:postgresql://${DB_URL} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 64af7b2..f91aa56 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -12,6 +12,7 @@ spring.datasource.driver-class-name=org.postgresql.Driver spring.h2.console.enabled=true spring.h2.console.path=/h2 spring.jpa.hibernate.ddl-auto=none +spring.sql.init.mode=always ## ## AWS S3 properties ## @@ -22,14 +23,14 @@ aws-s3.bucket=${BUCKET} ## ## Generate DDL files to create DB ## -spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create-drop -spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql -spring.jpa.properties.javax.persistence.schema-generation.scripts.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create-drop +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-source=metadata ## ## Generate DDL files to drop DB ## -spring.jpa.properties.javax.persistence.schema-generation.scripts.drop-target=drop.sql -spring.jpa.properties.javax.persistence.schema-generation.scripts.drop-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.drop-target=drop.sql +#spring.jpa.properties.javax.persistence.schema-generation.scripts.drop-source=metadata ## ## DEFAULT PAGE PROPS ## diff --git a/src/main/resources/db/changelog/changeset/add-data.sql b/src/main/resources/db/changelog/changeset/V1/data-V1.sql similarity index 98% rename from src/main/resources/db/changelog/changeset/add-data.sql rename to src/main/resources/db/changelog/changeset/V1/data-V1.sql index 0c1f465..3b8e80a 100644 --- a/src/main/resources/db/changelog/changeset/add-data.sql +++ b/src/main/resources/db/changelog/changeset/V1/data-V1.sql @@ -50,7 +50,7 @@ insert into user_info (talent_id, login, password) values ((select id from talent order by id desc limit 1), 'SerhiiSoloviov@gmail.com', 'password'); insert into user_authorities (user_id, authority_id) values ((select id from user_info order by id desc limit 1), - (select authority.id from authority where id = 1)); + (select authority.id from authority where id = 1)); insert into talent (first_name, last_name, specialization, image) values ('Mykhailo', 'Ordyntsev', 'Java-Developer', 'https://i.pinimg.com/564x/c2/41/31/c24131fe00218467721ba5bacdf0a256.jpg'); @@ -93,7 +93,7 @@ insert into user_info (talent_id, login, password) values ((select id from talent order by id desc limit 1), 'MykhailoOrdyntsev@gmail.com', 'password'); insert into user_authorities (user_id, authority_id) values ((select id from user_info order by id desc limit 1), - (select authority.id from authority where id = 1)); + (select authority.id from authority where id = 1)); insert into talent (first_name, last_name, specialization, image) values ('Denis', 'Boyko', 'Java-Developer', 'https://i.pinimg.com/564x/2a/0c/08/2a0c08c421e253ca895c3fdc8c9e08d9.jpg'); @@ -134,7 +134,7 @@ insert into user_info (talent_id, login, password) values ((select id from talent order by id desc limit 1), 'DenisBoyko@gmail.com', 'password'); insert into user_authorities (user_id, authority_id) values ((select id from user_info order by id desc limit 1), - (select authority.id from authority where id = 1)); + (select authority.id from authority where id = 1)); insert into talent (first_name, last_name, specialization, image) values ('Ihor', 'Schurenko', 'Java-Developer', 'https://i.pinimg.com/564x/e1/11/2f/e1112f0b7b63644dc3e313084936dedb.jpg'); @@ -174,7 +174,7 @@ insert into user_info (talent_id, login, password) values ((select id from talent order by id desc limit 1), 'IhorShchurenko@gmail.com', 'password'); insert into user_authorities (user_id, authority_id) values ((select id from user_info order by id desc limit 1), - (select authority.id from authority where id = 1)); + (select authority.id from authority where id = 1)); insert into talent (first_name, last_name, specialization, image) values ('Dmytro', 'Uzun', 'Dev-Ops', 'https://i.pinimg.com/564x/1c/af/87/1caf8771ef3edf351f6f2bf6f1c0a276.jpg'); @@ -216,7 +216,7 @@ insert into user_info (talent_id, login, password) values ((select id from talent order by id desc limit 1), 'DmytroUzun@gmail.com', 'password'); insert into user_authorities (user_id, authority_id) values ((select id from user_info order by id desc limit 1), - (select authority.id from authority where id = 1)); + (select authority.id from authority where id = 1)); insert into talent (first_name, last_name, specialization, image) values ('Viktor', 'Voloshko', 'Dev-Ops', 'https://i.pinimg.com/564x/a9/51/ab/a951ab682413b89617235e65564c1e5e.jpg'); @@ -256,7 +256,7 @@ insert into user_info (talent_id, login, password) values ((select id from talent order by id desc limit 1), 'ViktorVoloshko@gmail.com', 'password'); insert into user_authorities (user_id, authority_id) values ((select id from user_info order by id desc limit 1), - (select authority.id from authority where id = 1)); + (select authority.id from authority where id = 1)); insert into talent (first_name, last_name, specialization, image) values ('Olha', 'Moiseienko', 'QA', 'https://i.pinimg.com/564x/6d/9d/43/6d9d437baf4db114c047d927307beb84.jpg'); @@ -298,7 +298,7 @@ insert into user_info (talent_id, login, password) values ((select id from talent order by id desc limit 1), 'OlhaMoiseienko@gmail.com', 'password'); insert into user_authorities (user_id, authority_id) values ((select id from user_info order by id desc limit 1), - (select authority.id from authority where id = 1)); + (select authority.id from authority where id = 1)); insert into talent (first_name, last_name, specialization, image) values ('Maxim', 'Kiyashko', 'QA', 'https://i.pinimg.com/564x/80/2d/58/802d58b0302985f9486893d499d3634d.jpg'); @@ -338,7 +338,7 @@ insert into user_info (talent_id, login, password) values ((select id from talent order by id desc limit 1), 'MaximKiyashko@gmail.com', 'password'); insert into user_authorities (user_id, authority_id) values ((select id from user_info order by id desc limit 1), - (select authority.id from authority where id = 1)); + (select authority.id from authority where id = 1)); insert into talent (first_name, last_name, specialization, image) values ('Nikolaiev', 'Oleksii', 'QA', 'https://i.pinimg.com/564x/54/d1/0d/54d10dfce64afefabc9fbbce5de82c87.jpg'); @@ -380,7 +380,7 @@ insert into user_info (talent_id, login, password) values ((select id from talent order by id desc limit 1), 'NikolaievOleksiio@gmail.com', 'password'); insert into user_authorities (user_id, authority_id) values ((select id from user_info order by id desc limit 1), - (select authority.id from authority where id = 1)); + (select authority.id from authority where id = 1)); insert into talent (first_name, last_name, specialization, image) values ('Artem', 'Lytvynenko', 'QA', 'https://i.pinimg.com/564x/87/63/55/87635509c5fa7ee496ec351fa7e67eaa.jpg'); @@ -420,7 +420,7 @@ insert into user_info (talent_id, login, password) values ((select id from talent order by id desc limit 1), 'ArtemLytvynenko@gmail.com', 'password'); insert into user_authorities (user_id, authority_id) values ((select id from user_info order by id desc limit 1), - (select authority.id from authority where id = 1)); + (select authority.id from authority where id = 1)); insert into talent (first_name, last_name, specialization, image) values ('Daniil', 'Yevtukhov', 'Java-Script-Developer', 'https://i.pinimg.com/564x/fe/b1/37/feb137d88a3d1c8fb28796db6cbc576f.jpg'); @@ -460,7 +460,7 @@ insert into user_info (talent_id, login, password) values ((select id from talent order by id desc limit 1), 'DaniilYevtukhov@gmail.com', 'password'); insert into user_authorities (user_id, authority_id) values ((select id from user_info order by id desc limit 1), - (select authority.id from authority where id = 1)); + (select authority.id from authority where id = 1)); insert into talent (first_name, last_name, specialization, image) values ('Ruslan', 'Morozov', 'Java-Script-Developer', 'https://i.pinimg.com/736x/36/ae/0e/36ae0ea4aad656f7c3d3175bc33b8399.jpg'); @@ -502,7 +502,7 @@ insert into user_info (talent_id, login, password) values ((select id from talent order by id desc limit 1), 'RuslanMorozov@gmail.com', 'password'); insert into user_authorities (user_id, authority_id) values ((select id from user_info order by id desc limit 1), - (select authority.id from authority where id = 1)); + (select authority.id from authority where id = 1)); insert into talent (first_name, last_name, specialization, image) values ('Ihor', 'Kopieichykov', 'Java-Script-Developer', 'https://i.pinimg.com/564x/0d/f0/83/0df083121bac75f64e3d93c7c5682d04.jpg'); @@ -544,4 +544,4 @@ insert into user_info (talent_id, login, password) values ((select id from talent order by id desc limit 1), 'IhorKopieichykov@gmail.com', 'password'); insert into user_authorities (user_id, authority_id) values ((select id from user_info order by id desc limit 1), - (select authority.id from authority where id = 1)); + (select authority.id from authority where id = 1)); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V1/drop-V1.sql b/src/main/resources/db/changelog/changeset/V1/drop-V1.sql new file mode 100644 index 0000000..09b1124 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V1/drop-V1.sql @@ -0,0 +1,14 @@ +--liquibase formatted sql +--changeset mykhailo:2 + +drop table if exists authority cascade; +drop table if exists talent cascade; +drop table if exists talent_attached_file cascade; +drop table if exists talent_contact cascade; +drop table if exists talent_description cascade; +drop table if exists talent_link cascade; +drop table if exists talent_proofs cascade; +drop table if exists talent_talents cascade; +drop table if exists user_authorities cascade; +drop table if exists user_info cascade; +drop table if exists kudos cascade; diff --git a/src/main/resources/db/changelog/changeset/create-tables.sql b/src/main/resources/db/changelog/changeset/V1/schema-V1.sql similarity index 99% rename from src/main/resources/db/changelog/changeset/create-tables.sql rename to src/main/resources/db/changelog/changeset/V1/schema-V1.sql index 33ed8af..7eccc32 100644 --- a/src/main/resources/db/changelog/changeset/create-tables.sql +++ b/src/main/resources/db/changelog/changeset/V1/schema-V1.sql @@ -129,4 +129,4 @@ ALTER TABLE user_authorities ALTER TABLE kudos ADD CONSTRAINT FK_KUDOS_ON_PROOF FOREIGN KEY (proof_id) REFERENCES talent_proofs (id); ALTER TABLE kudos - ADD CONSTRAINT FK_KUDOS_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); + ADD CONSTRAINT FK_KUDOS_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V2/data-V2.sql b/src/main/resources/db/changelog/changeset/V2/data-V2.sql new file mode 100644 index 0000000..a5de8d5 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V2/data-V2.sql @@ -0,0 +1,595 @@ +--liquibase formatted sql +--changeset mykhailo:2 + +-- -- FOR USER AUTHORITY +-- -- SELECT USER_INFO.ID , LOGIN , PASSWORD, talent_id , AUTHORITY FROM +-- -- USER_INFO +-- -- JOIN user_authorities ON talent_id = USER_INFO.ID +-- -- JOIN AUTHORITY ON AUTHORITY.ID = id + +insert into authority (id, authority) +values (1, 'TALENT'); +insert into authority (id, authority) +values (2, 'SPONSOR'); + +insert into talent (first_name, last_name, specialization, image) +values ('Serhii', 'Soloviov', 'Java-Developer', 'https://i.pinimg.com/564x/e1/08/49/e10849923a8b2e85a7adf494ebd063e6.jpg'); +insert into talent_description (talent_id, BIO, addition_info) +values((select id from talent order by id desc limit 1), 'Hello! I was born in Ukraine. My profession is Java Back-end developer. Now I`m developing a Java backend using Spring Boot.', 'My cat`s name is Igor'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Java Core'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Spring Core'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Spring boot'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'H2 Database'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'first_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'second_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'third_contact'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'Here I wrote a program that transforms the written code into music', 'PUBLISHED', '2022-01-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to second proof', 'DRAFT', '2023-03-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to third proof', 'HIDDEN', '2021-06-08 16:00:19'); + +insert into user_info (talent_id, login, password) +values ((select id from talent order by id desc limit 1), 'SerhiiSoloviov@gmail.com', '$2a$10$EzYxG1DEUek/veK.HzP7B.ynSKE42VbLb4pvFd/v4OwGPNol6buEC'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 1)); + +insert into talent (first_name, last_name, specialization, image) +values ('Mykhailo', 'Ordyntsev', 'Java-Developer', 'https://i.pinimg.com/564x/c2/41/31/c24131fe00218467721ba5bacdf0a256.jpg'); +insert into talent_description (talent_id, BIO, addition_info) +values((select id from talent order by id desc limit 1), 'Hello! I was born in Ukraine. My profession is Java Back-end developer. Now I`m developing a Java backend using Spring Boot.', 'I very like anime'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Java Core'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Hibernate'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Spring Boot'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Git'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'MykhailoOrdyntsev_first_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'MykhailoOrdyntsev_second_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'MykhailoOrdyntsev_third_contact'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to first proof', 'DRAFT', '2022-08-07 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to second proof', 'HIDDEN', '2022-04-08 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to third proof', 'DRAFT', '2022-09-02 16:00:19'); + +insert into user_info (talent_id, login, password) +values ((select id from talent order by id desc limit 1), 'MykhailoOrdyntsev@gmail.com', '$2a$10$XD60M86n1MDf3AMIixgnnOQq9JVYnnX/umlNFcre0GoC2XgSN/Cfq'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 1)); + +insert into talent (first_name, last_name, specialization, image) +values ('Denis', 'Boyko', 'Java-Developer', 'https://i.pinimg.com/564x/2a/0c/08/2a0c08c421e253ca895c3fdc8c9e08d9.jpg'); +insert into talent_description (talent_id, BIO, addition_info) +values((select id from talent order by id desc limit 1), 'Hello! I was born in Ukraine. My profession is Java Back-end developer. Now I`m developing a Java backend using Spring Boot.', 'I`m a student '); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Java Core'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Spring Security'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Spring Core'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'DenisBoyko_first_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'DenisBoyko_second_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'DenisBoyko_third_contact'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to first proof', 'DRAFT', '2022-02-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to second proof', 'DRAFT', '2021-09-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to third proof', 'DRAFT', '2023-04-04 16:00:19'); + +insert into user_info (talent_id, login, password) +values ((select id from talent order by id desc limit 1), 'DenisBoyko@gmail.com', '$2a$10$tLm27FGH8Sabz57eNkTwm.bSnhmJHINcqt7dNfZI0NfOwD2o/Drse'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 1)); + +insert into talent (first_name, last_name, specialization, image) +values ('Ihor', 'Schurenko', 'Java-Developer', 'https://i.pinimg.com/564x/e1/11/2f/e1112f0b7b63644dc3e313084936dedb.jpg'); +insert into talent_description (talent_id, BIO, addition_info) +values((select id from talent order by id desc limit 1), 'Hello! I was born in Ukraine. My profession is Java Back-end developer. Now I`m developing a Java backend using Spring Boot.', 'I will get married soon'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Java Core'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'REST API'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'IhorShchurenko_first_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'IhorShchurenko_second_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'IhorShchurenko_third_contact'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'Here I describe my rest api project in java', 'PUBLISHED', '2021-08-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to second proof', 'DRAFT', '2022-06-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to third proof', 'DRAFT', '2023-05-04 16:00:19'); + +insert into user_info (talent_id, login, password) +values ((select id from talent order by id desc limit 1), 'IhorShchurenko@gmail.com', '$2a$10$X.d4hR.yRf3cK0Go20aTTukOI9u/Zu2cj5WU0iTcDihyhJ5vUHXkq'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 1)); + +insert into talent (first_name, last_name, specialization, image) +values ('Dmytro', 'Uzun', 'Dev-Ops', 'https://i.pinimg.com/564x/1c/af/87/1caf8771ef3edf351f6f2bf6f1c0a276.jpg'); +insert into talent_description (talent_id, BIO, addition_info) +values((select id from talent order by id desc limit 1), 'I am instructing a team that is currently writing my own biography for me.', 'He-he-he, hello everyone!'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Git'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Docker'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Mentor'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'DmytroUzun_first_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'DmytroUzun_second_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'DmytroUzun_third_contact'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://github.com/ProvedCode', 'My project where I am a team mentor', 'PUBLISHED', '2023-02-08 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to second proof', 'DRAFT', '2021-03-03 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to third proof', 'DRAFT', '2023-09-05 16:00:19'); + +insert into user_info (talent_id, login, password) +values ((select id from talent order by id desc limit 1), 'DmytroUzun@gmail.com', '$2a$10$J2Yuh10BWHy8XYk.T5rd2uOwk/h5EYG1eVXTAOkTkTdQcc5Qzd9.y'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 1)); + +insert into talent (first_name, last_name, specialization, image) +values ('Viktor', 'Voloshko', 'Dev-Ops', 'https://i.pinimg.com/564x/a9/51/ab/a951ab682413b89617235e65564c1e5e.jpg'); +insert into talent_description (talent_id, BIO, addition_info) +values((select id from talent order by id desc limit 1), 'Hi all! I was born in Ukraine. I am a student. My profession is dev-ops.', 'I like videogames!'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Git'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Docker'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'ViktorVoloshko_first_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'ViktorVoloshko_second_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'ViktorVoloshko_third_contact'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to first proof', 'HIDDEN', '2022-02-09 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to second proof', 'DRAFT', '2020-04-02 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to third proof', 'DRAFT', '2023-08-06 16:00:19'); + +insert into user_info (talent_id, login, password) +values ((select id from talent order by id desc limit 1), 'ViktorVoloshko@gmail.com', '$2a$10$eZX3hBvllxkmH.juZzN72uvFYtphkrxsj14K5BnHHKy4coRV9FMvq'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 1)); + +insert into talent (first_name, last_name, specialization, image) +values ('Olha', 'Moiseienko', 'QA', 'https://i.pinimg.com/564x/6d/9d/43/6d9d437baf4db114c047d927307beb84.jpg'); +insert into talent_description (talent_id, BIO, addition_info) +values((select id from talent order by id desc limit 1), 'Hi all! I was born in Ukraine. I am a student. My profession is QA.', 'Glory to Ukraine'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Git'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Jira'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'QA'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'OlhaMoiseienko_first_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'OlhaMoiseienko_second_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'OlhaMoiseienko_third_contact'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to first proof', 'HIDDEN', '2023-06-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'My QA Jira project', 'PUBLISHED', '2022-09-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to third proof', 'DRAFT', '2021-01-09 16:00:19'); + +insert into user_info (talent_id, login, password) +values ((select id from talent order by id desc limit 1), 'OlhaMoiseienko@gmail.com', '$2a$10$lvvX7DZOwCS/Q7zSo.k.oeayTcKHh8rO1yBBkgIbU4VAC7abPfIa2'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 1)); + +insert into talent (first_name, last_name, specialization, image) +values ('Maxim', 'Kiyashko', 'QA', 'https://i.pinimg.com/564x/80/2d/58/802d58b0302985f9486893d499d3634d.jpg'); +insert into talent_description (talent_id, BIO, addition_info) +values((select id from talent order by id desc limit 1), 'Hi all! I was born in Ukraine. I am a student. My profession is QA.', 'Glory to Ukraine'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Git'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'QA'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'MaximKiyashko_first_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'MaximKiyashko_second_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'MaximKiyashko_third_contact'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'My custom Arduino OS', 'PUBLISHED', '2023-08-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to second proof', 'DRAFT', '2023-01-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to third proof', 'PUBLISHED', '2023-02-09 16:00:19'); + +insert into user_info (talent_id, login, password) +values ((select id from talent order by id desc limit 1), 'MaximKiyashko@gmail.com', '$2a$10$y.g9qHYUOPEkIL8xDc2h1.EdVAG5DYh6OKxf9CRb6s16oHHbr8Bny'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 1)); + +insert into talent (first_name, last_name, specialization, image) +values ('Nikolaiev', 'Oleksii', 'QA', 'https://i.pinimg.com/564x/54/d1/0d/54d10dfce64afefabc9fbbce5de82c87.jpg'); +insert into talent_description (talent_id, BIO, addition_info) +values((select id from talent order by id desc limit 1), 'Hi all! I was born in Ukraine. I am a student. My profession is QA.', 'Glory to Ukraine'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'QA'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Git'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'NikolaievOleksii_third_talents'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'NikolaievOleksii_first_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'NikolaievOleksii_second_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'NikolaievOleksii_third_contact'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'Link to my magnum opus:', 'PUBLISHED', '2023-06-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to second proof', 'DRAFT', '2023-06-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to third proof', 'HIDDEN', '2023-06-04 16:00:19'); + +insert into user_info (talent_id, login, password) +values ((select id from talent order by id desc limit 1), 'NikolaievOleksiio@gmail.com', '$2a$10$nDObO3nDlhWev29qCnzNuOszdg/.ANaMlTirDVWVyLMapYmtSSqza'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 1)); + +insert into talent (first_name, last_name, specialization, image) +values ('Artem', 'Lytvynenko', 'QA', 'https://i.pinimg.com/564x/87/63/55/87635509c5fa7ee496ec351fa7e67eaa.jpg'); +insert into talent_description (talent_id, BIO, addition_info) +values((select id from talent order by id desc limit 1), 'Hi all! I was born in Ukraine. I am a student. My profession is QA.', 'Glory to Ukraine'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'QA'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Git'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'ArtemLytvynenko_first_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'ArtemLytvynenko_second_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'ArtemLytvynenko_third_contact'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'Here I wrote tasks for the project', 'PUBLISHED', '2023-06-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to second proof', 'DRAFT', '2023-06-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to third proof', 'HIDDEN', '2023-06-04 16:00:19'); + +insert into user_info (talent_id, login, password) +values ((select id from talent order by id desc limit 1), 'ArtemLytvynenko@gmail.com', '$2a$10$.M2fHh9NXbkbnrVHeT.lYeInA8K2khuMUL08iG4NuXs18KIeFBmwG'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 1)); + +insert into talent (first_name, last_name, specialization, image) +values ('Daniil', 'Yevtukhov', 'Java-Script-Developer', 'https://i.pinimg.com/564x/fe/b1/37/feb137d88a3d1c8fb28796db6cbc576f.jpg'); +insert into talent_description (talent_id, BIO, addition_info) +values((select id from talent order by id desc limit 1), 'Hi all! I was born in Ukraine. I am a student. My profession is JavaScript developer.', 'I have my own Instagram'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'JavaScript Core'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'React'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'DaniilYevtukhov_first_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'DaniilYevtukhov_second_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'DaniilYevtukhov_third_contact'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'My main project where I am making REACT application', 'PUBLISHED', '2023-06-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to second proof', 'HIDDEN', '2023-06-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to third proof', 'DRAFT', '2023-06-04 16:00:19'); + +insert into user_info (talent_id, login, password) +values ((select id from talent order by id desc limit 1), 'DaniilYevtukhov@gmail.com', '$2a$10$cDxp6U/YcObKMwZNgtEB5eZFLWXuwFU0lIUSPIkfPdvq9l8JUqGea'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 1)); + +insert into talent (first_name, last_name, specialization, image) +values ('Ruslan', 'Morozov', 'Java-Script-Developer', 'https://i.pinimg.com/736x/36/ae/0e/36ae0ea4aad656f7c3d3175bc33b8399.jpg'); +insert into talent_description (talent_id, BIO, addition_info) +values((select id from talent order by id desc limit 1), 'Hi all! I was born in Ukraine. I am a student. My profession is JavaScript developer.', 'Glory to Ukraine'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'JavaScript Core'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'React'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Node.js'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'RuslanMorozov_first_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'RuslanMorozov_second_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'RuslanMorozov_third_contact'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'Here my container for styles', 'PUBLISHED', '2023-06-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to second proof', 'DRAFT', '2023-06-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to third proof', 'DRAFT', '2023-06-04 16:00:19'); + +insert into user_info (talent_id, login, password) +values ((select id from talent order by id desc limit 1), 'RuslanMorozov@gmail.com', '$2a$10$Hfzp4b6r825g1ZqGzxmal..VNKvo7F4v4YFpBZZ036hmO.7UIWlaK'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 1)); + +insert into talent (first_name, last_name, specialization, image) +values ('Ihor', 'Kopieichykov', 'Java-Script-Developer', 'https://i.pinimg.com/564x/0d/f0/83/0df083121bac75f64e3d93c7c5682d04.jpg'); +insert into talent_description (talent_id, BIO, addition_info) +values((select id from talent order by id desc limit 1), 'Hi all! I was born in Ukraine. I am a student. My profession is JavaScript developer.', 'Glory to Ukraine'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_link (talent_id, link) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'JavaScript Core'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'React'); +insert into talent_talents (talent_id, talent_name) +values ((select id from talent order by id desc limit 1), 'Angular'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'IhorKopieichykov_first_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'IhorKopieichykov_second_contact'); +insert into talent_contact (talent_id, contact) +values ((select id from talent order by id desc limit 1), 'IhorKopieichykov_third_contact'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +insert into talent_attached_file (talent_id, attached_file) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'Here is my JavaScript library', 'PUBLISHED', '2023-06-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'Here is my main project in Angular', 'PUBLISHED', '2023-06-04 16:00:19'); +insert into talent_proofs (talent_id, link, text, status, created) +values ((select id from talent order by id desc limit 1), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'text to third proof', 'DRAFT', '2023-06-04 16:00:19'); + +insert into user_info (talent_id, login, password) +values ((select id from talent order by id desc limit 1), 'IhorKopieichykov@gmail.com', '$2a$10$D4KM50WemOahkFv1fkrPX.MvVESsE0TYWlkh5TypTE/q4nlv8ooyS'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 1)); + +insert into sponsor (amount_kudos, first_name, last_name, image) +values (888, 'Maksym', 'Khudoliy', 'https://i.pinimg.com/564x/e1/08/49/e10849923a8b2e85a7adf494ebd063e6.jpg'); + +insert into user_info (sponsor_id, login, password) +values ((select id from sponsor order by id desc limit 1), 'MaksymKhudoliy@gmail.com', '$2a$10$pDrAuawhi3ADZpVDDr7C6eAcaQwDr5oQ9GdZUUZHSsqyM/vVkpruy'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 2) ); + +insert into sponsor (amount_kudos, first_name, last_name, image) +values (888, 'Oleksandr', 'Butrym', 'https://i.pinimg.com/564x/c2/41/31/c24131fe00218467721ba5bacdf0a256.jpg'); + +insert into user_info (sponsor_id, login, password) +values ((select id from sponsor order by id desc limit 1), 'OleksandrButrym@gmail.com', '$2a$10$R0o8os0t86qyBvg0bO/a6ukuy9VesLapxIkZFLjNupWjvr5Hdjyge'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 2) ); + +insert into sponsor (amount_kudos, first_name, last_name, image) +values (888, 'Olha', 'Shutylieva', 'https://i.pinimg.com/564x/2a/0c/08/2a0c08c421e253ca895c3fdc8c9e08d9.jpg'); + +insert into user_info (sponsor_id, login, password) +values ((select id from sponsor order by id desc limit 1), 'OlhaShutylieva@gmail.com', '$2a$10$UzwVTVR7E2BW.5hA4XWgy.g0XcM.UbIMBoY1cDnYNPQDhCXEa7eGm'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 2) ); + +insert into sponsor (amount_kudos, first_name, last_name, image) +values (888, 'Vladyslav', 'Khrychov', 'https://i.pinimg.com/564x/e1/11/2f/e1112f0b7b63644dc3e313084936dedb.jpg'); + +insert into user_info (sponsor_id, login, password) +values ((select id from sponsor order by id desc limit 1), 'VladyslavKhrychov@gmail.com', '$2a$10$o2va23ZPVVSptyCaSBO/oubpML4xEPZo9Ie0ASt154zNVSKdFrN02'); +insert into user_authorities (user_id, authority_id) +values ((select id from user_info order by id desc limit 1), + (select authority.id from authority where id = 2) ); + +insert into kudos (amount, sponsor_id, proof_id) +values (100, 1, 1); +insert into kudos (amount, sponsor_id, proof_id) +values (200, 2, 1); +insert into kudos (amount, sponsor_id, proof_id) +values (200, 3, 1); +insert into kudos (amount, sponsor_id, proof_id) +values (300, 4, 1); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V2/drop-V2.sql b/src/main/resources/db/changelog/changeset/V2/drop-V2.sql new file mode 100644 index 0000000..7b0ee1f --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V2/drop-V2.sql @@ -0,0 +1,15 @@ +--liquibase formatted sql +--changeset mykhailo:2 + +drop table if exists authority cascade; +drop table if exists talent cascade; +drop table if exists talent_attached_file cascade; +drop table if exists talent_contact cascade; +drop table if exists talent_description cascade; +drop table if exists talent_link cascade; +drop table if exists talent_proofs cascade; +drop table if exists talent_talents cascade; +drop table if exists user_authorities cascade; +drop table if exists user_info cascade; +drop table if exists kudos cascade; +drop table if exists sponsor cascade; diff --git a/src/main/resources/db/changelog/changeset/V2/schema-V2.sql b/src/main/resources/db/changelog/changeset/V2/schema-V2.sql new file mode 100644 index 0000000..adad4a6 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V2/schema-V2.sql @@ -0,0 +1,124 @@ +-- liquibase formatted sql +-- changeset mykhailo:2 + +-- tables for sprint 3.2 + + +CREATE TABLE authority +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + authority VARCHAR(20) NOT NULL, + CONSTRAINT pk_authority PRIMARY KEY (id) +); +CREATE TABLE talent +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + first_name VARCHAR(20), + last_name VARCHAR(20), + specialization VARCHAR(30), + image VARCHAR(1000), + image_name VARCHAR(100), + CONSTRAINT pk_talent PRIMARY KEY (id) +); +CREATE TABLE talent_attached_file +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL, + attached_file VARCHAR(100), + CONSTRAINT pk_talent_attached_file PRIMARY KEY (id) +); +CREATE TABLE talent_contact +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL, + contact VARCHAR(255), + CONSTRAINT pk_talent_contact PRIMARY KEY (id) +); +CREATE TABLE talent_description +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL, + bio VARCHAR(2000), + addition_info VARCHAR(500), + CONSTRAINT pk_talent_description PRIMARY KEY (id) +); +CREATE TABLE talent_link +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL, + link VARCHAR(500), + CONSTRAINT pk_talent_link PRIMARY KEY (id) +); +CREATE TABLE talent_proofs +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL, + link VARCHAR(100), + text VARCHAR(1000), + status VARCHAR(20) NOT NULL, + created TIMESTAMP, + CONSTRAINT pk_talent_proofs PRIMARY KEY (id) +); +CREATE TABLE talent_talents +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL, + talent_name VARCHAR(255), + CONSTRAINT pk_talent_talents PRIMARY KEY (id) +); +CREATE TABLE user_authorities +( + authority_id BIGINT NOT NULL, + user_id BIGINT NOT NULL, + CONSTRAINT pk_user_authorities PRIMARY KEY (authority_id, user_id) +); +CREATE TABLE user_info +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT, + sponsor_id BIGINT, + login VARCHAR(100) NOT NULL, + password VARCHAR(255) NOT NULL, + CONSTRAINT pk_user_info PRIMARY KEY (id) +); +CREATE TABLE kudos +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + sponsor_id BIGINT, + proof_id BIGINT, + amount BIGINT, + CONSTRAINT pk_kudos PRIMARY KEY (id) +); +CREATE TABLE sponsor +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + first_name VARCHAR(20), + last_name VARCHAR(20), + image VARCHAR(1000), + image_name VARCHAR(100), + amount_kudos BIGINT, + CONSTRAINT pk_sponsor PRIMARY KEY (id) +); + +ALTER TABLE talent_attached_file + ADD CONSTRAINT FK_TALENT_ATTACHED_FILE_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); +ALTER TABLE talent_contact + ADD CONSTRAINT FK_TALENT_CONTACT_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); +ALTER TABLE talent_description + ADD CONSTRAINT FK_TALENT_DESCRIPTION_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); +ALTER TABLE talent_link + ADD CONSTRAINT FK_TALENT_LINK_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); +ALTER TABLE talent_proofs + ADD CONSTRAINT FK_TALENT_PROOFS_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); +ALTER TABLE talent_talents + ADD CONSTRAINT FK_TALENT_TALENTS_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); +ALTER TABLE user_info + ADD CONSTRAINT FK_USER_INFO_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); +ALTER TABLE user_authorities + ADD CONSTRAINT FK_useaut_on_authority FOREIGN KEY (authority_id) REFERENCES authority (id); +ALTER TABLE user_authorities + ADD CONSTRAINT FK_useaut_on_user_info FOREIGN KEY (user_id) REFERENCES user_info (id); +ALTER TABLE kudos + ADD CONSTRAINT FK_KUDOS_ON_PROOF FOREIGN KEY (proof_id) REFERENCES talent_proofs (id); +ALTER TABLE kudos + ADD CONSTRAINT FK_KUDOS_ON_SPONSOR FOREIGN KEY (sponsor_id) REFERENCES sponsor (id); \ No newline at end of file diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 41cf880..4a6438c 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -1,6 +1,9 @@ databaseChangeLog: - include: - file: db/changelog/changeset/create-tables.sql - + file: db/changelog/changeset/V1/drop-V1.sql - include: - file: db/changelog/changeset/add-data.sql + file: db/changelog/changeset/V2/drop-V2.sql + - include: + file: db/changelog/changeset/V2/schema-V2.sql + - include: + file: db/changelog/changeset/V2/data-V2.sql \ No newline at end of file diff --git a/src/main/resources/pagination.properties b/src/main/resources/pagination.properties deleted file mode 100644 index 7cbaa30..0000000 --- a/src/main/resources/pagination.properties +++ /dev/null @@ -1 +0,0 @@ -## DEFAULT PAGE VALUES