From b9991ed304431f4fc64754d04b557a7f41374bef Mon Sep 17 00:00:00 2001 From: Ren Date: Sat, 22 Apr 2023 01:24:55 +0300 Subject: [PATCH 01/59] * Edit db structure * Working with sponsor --- pom.xml | 5 +- .../com/provedcode/ProvedCodeApplication.java | 4 +- .../kudos/controller/KudosController.java | 36 ++--- .../provedcode/kudos/model/entity/Kudos.java | 10 +- .../kudos/repository/KudosRepository.java | 2 - .../kudos/service/KudosService.java | 128 +++++++++--------- .../sponsor/controller/SponsorController.java | 35 +++++ .../sponsor/mapper/SponsorMapper.java | 14 ++ .../sponsor/model/dto/SponsorDTO.java | 9 ++ .../sponsor/model/entity/Sponsor.java | 35 +++++ .../sponsor/repository/SponsorRepository.java | 7 + .../sponsor/service/SponsorService.java | 38 ++++++ .../talent/model/entity/Talent.java | 4 +- .../java/com/provedcode/user/model/Role.java | 3 +- .../user/model/entity/UserInfo.java | 5 +- .../db/changelog/changeset/add-data.sql | 1 + .../db/changelog/changeset/create-tables.sql | 40 +++--- src/main/resources/pagination.properties | 1 - 18 files changed, 257 insertions(+), 120 deletions(-) create mode 100644 src/main/java/com/provedcode/sponsor/controller/SponsorController.java create mode 100644 src/main/java/com/provedcode/sponsor/mapper/SponsorMapper.java create mode 100644 src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java create mode 100644 src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java create mode 100644 src/main/java/com/provedcode/sponsor/repository/SponsorRepository.java create mode 100644 src/main/java/com/provedcode/sponsor/service/SponsorService.java delete mode 100644 src/main/resources/pagination.properties 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..f88f54e 100644 --- a/src/main/java/com/provedcode/ProvedCodeApplication.java +++ b/src/main/java/com/provedcode/ProvedCodeApplication.java @@ -7,9 +7,7 @@ @SpringBootApplication @ConfigurationPropertiesScan 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/kudos/controller/KudosController.java b/src/main/java/com/provedcode/kudos/controller/KudosController.java index 101de0c..fcd85c8 100644 --- a/src/main/java/com/provedcode/kudos/controller/KudosController.java +++ b/src/main/java/com/provedcode/kudos/controller/KudosController.java @@ -11,22 +11,22 @@ @AllArgsConstructor @RequestMapping("/api/v3/talent") public class KudosController { - KudosService kudosService; - - @GetMapping("/proofs/{proof-id}/kudos") - KudosAmount getKudosProof(@PathVariable("proof-id") long id) { - return kudosService.getAmountKudosProof(id); - } - - @PreAuthorize("hasRole('TALENT')") - @PostMapping("/proofs/{proof-id}/kudos") - void addKudosToProof(@PathVariable("proof-id") long id, Authentication authentication) { - kudosService.addKudosToProof(id, authentication); - } - - @PreAuthorize("hasRole('TALENT')") - @DeleteMapping("/proofs/{proof-id}/kudos") - void deleteKudosFromProof(@PathVariable("proof-id") long id, Authentication authentication) { - kudosService.deleteKudosFromProof(id, authentication); - } +// KudosService kudosService; +// +// @GetMapping("/proofs/{proof-id}/kudos") +// KudosAmount getKudosProof(@PathVariable("proof-id") long id) { +// return kudosService.getAmountKudosProof(id); +// } +// +// @PreAuthorize("hasRole('TALENT')") +// @PostMapping("/proofs/{proof-id}/kudos") +// void addKudosToProof(@PathVariable("proof-id") long id, Authentication authentication) { +// kudosService.addKudosToProof(id, authentication); +// } +// +// @PreAuthorize("hasRole('TALENT')") +// @DeleteMapping("/proofs/{proof-id}/kudos") +// void deleteKudosFromProof(@PathVariable("proof-id") long id, Authentication authentication) { +// kudosService.deleteKudosFromProof(id, 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..198e433 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 @@ -20,9 +18,9 @@ public class Kudos { @Column(name = "id", nullable = false) private Long id; @ManyToOne(cascade = CascadeType.ALL) - @JoinColumn(name = "talent_id") - private Talent talent; - @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/repository/KudosRepository.java b/src/main/java/com/provedcode/kudos/repository/KudosRepository.java index 4338d6b..529129e 100644 --- a/src/main/java/com/provedcode/kudos/repository/KudosRepository.java +++ b/src/main/java/com/provedcode/kudos/repository/KudosRepository.java @@ -7,6 +7,4 @@ public interface KudosRepository extends JpaRepository { long countByProof_Id(Long id); - - boolean existsByTalent(Talent talent); } \ 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 84ffeef..c98995e 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -25,68 +25,68 @@ @AllArgsConstructor @Transactional public class KudosService { - KudosRepository kudosRepository; - TalentRepository talentRepository; - TalentProofRepository talentProofRepository; - UserInfoRepository userInfoRepository; - - @Transactional(readOnly = true) - public KudosAmount getAmountKudosProof(long id) { - 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); - return new KudosAmount(count); - } - - 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.existsByTalent(talent)) { - throw new ResponseStatusException(CONFLICT, "Talent can give only one `kudos` for one proof"); - } - if (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { - throw new ResponseStatusException(FORBIDDEN); - } - - kudosRepository.save(Kudos.builder() - .proof(talentProof) - .talent(talent) - .build()); - } - - 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))); - - if (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { - throw new ResponseStatusException(FORBIDDEN); - } - if (!kudosRepository.existsByTalent(talent)) { - throw new ResponseStatusException(CONFLICT, "kudos don`t exist"); - } - - 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); - } +// KudosRepository kudosRepository; +// TalentRepository talentRepository; +// TalentProofRepository talentProofRepository; +// UserInfoRepository userInfoRepository; +// +// @Transactional(readOnly = true) +// public KudosAmount getAmountKudosProof(long id) { +// 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); +// return new KudosAmount(count); +// } +// +// 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.existsByTalent(talent)) { +// throw new ResponseStatusException(CONFLICT, "Talent can give only one `kudos` for one proof"); +// } +// if (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { +// throw new ResponseStatusException(FORBIDDEN); +// } +// +// kudosRepository.save(Kudos.builder() +// .proof(talentProof) +// .talent(talent) +// .build()); +// } +// +// 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))); +// +// if (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { +// throw new ResponseStatusException(FORBIDDEN); +// } +// if (!kudosRepository.existsByTalent(talent)) { +// throw new ResponseStatusException(CONFLICT, "kudos don`t exist"); +// } +// +// 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..406910b --- /dev/null +++ b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java @@ -0,0 +1,35 @@ +package com.provedcode.sponsor.controller; + +import com.provedcode.sponsor.mapper.SponsorMapper; +import com.provedcode.sponsor.model.dto.SponsorDTO; +import com.provedcode.sponsor.service.SponsorService; +import com.provedcode.talent.model.dto.FullTalentDTO; +import lombok.AllArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +import java.util.Optional; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/v3") +public class SponsorController { + SponsorService sponsorService; + SponsorMapper sponsorMapper; + + @GetMapping("/sponsor") + @ResponseStatus(HttpStatus.OK) + Page getSponsors(@RequestParam(value = "page") Optional page, + @RequestParam(value = "size") Optional size) { + return sponsorService.getAllSponsors(page, size).map(sponsorMapper::toDto); + } + + @PreAuthorize("hasRole('SPONSOR')") + @GetMapping("/sponsor/{id}") + SponsorDTO getSponsor(@PathVariable("id") long id, Authentication authentication) { + return sponsorMapper.toDto(sponsorService.getSponsorById(id)); + } +} \ 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..e01235b --- /dev/null +++ b/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java @@ -0,0 +1,9 @@ +package com.provedcode.sponsor.model.dto; + +public record SponsorDTO( + Long id, + String firstName, + 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..c471d88 --- /dev/null +++ b/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java @@ -0,0 +1,35 @@ +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; + @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 = 300) + private String image; + @OneToMany(mappedBy = "sponsor", cascade = CascadeType.ALL, orphanRemoval = true) + private List kudoses = new ArrayList<>(); +} \ No newline at end of file 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..93fb044 --- /dev/null +++ b/src/main/java/com/provedcode/sponsor/service/SponsorService.java @@ -0,0 +1,38 @@ +package com.provedcode.sponsor.service; + +import com.provedcode.config.PageProperties; +import com.provedcode.sponsor.model.entity.Sponsor; +import com.provedcode.sponsor.repository.SponsorRepository; +import lombok.AllArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; +import org.springframework.web.server.ResponseStatusException; + +import java.util.Optional; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.NOT_FOUND; + +@Service +@AllArgsConstructor +public class SponsorService { + PageProperties pageProperties; + SponsorRepository sponsorRepository; + + public Page getAllSponsors(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 sponsorRepository.findAll(PageRequest.of(page.orElse(pageProperties.defaultPageNum()), + size.orElse(pageProperties.defaultPageSize()))); + } + + public Sponsor getSponsorById(long id) { + return sponsorRepository.findById(id).orElseThrow( + () -> new ResponseStatusException(NOT_FOUND, String.format("sponsor with id = %d not found", id))); + } +} \ No newline at end of file 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..331ad63 100644 --- a/src/main/java/com/provedcode/talent/model/entity/Talent.java +++ b/src/main/java/com/provedcode/talent/model/entity/Talent.java @@ -33,7 +33,7 @@ public class Talent { @Column(name = "specialization", length = 30) private String specialization; @URL - @Column(name = "image", length = 100) + @Column(name = "image", length = 300) private String image; @OneToOne(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) private TalentDescription talentDescription; @@ -47,6 +47,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/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/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/resources/db/changelog/changeset/add-data.sql b/src/main/resources/db/changelog/changeset/add-data.sql index 0c1f465..90393d2 100644 --- a/src/main/resources/db/changelog/changeset/add-data.sql +++ b/src/main/resources/db/changelog/changeset/add-data.sql @@ -3,6 +3,7 @@ insert into authority (id, authority) values (1, 'TALENT'); +values (2, 'SPONSOR'); -- -- FOR USER AUTHORITY -- -- SELECT USER_INFO.ID , LOGIN , PASSWORD, talent_id , AUTHORITY FROM -- -- USER_INFO diff --git a/src/main/resources/db/changelog/changeset/create-tables.sql b/src/main/resources/db/changelog/changeset/create-tables.sql index 33ed8af..40927c3 100644 --- a/src/main/resources/db/changelog/changeset/create-tables.sql +++ b/src/main/resources/db/changelog/changeset/create-tables.sql @@ -88,25 +88,31 @@ CREATE TABLE user_authorities ); drop table if exists user_info cascade; -CREATE TABLE user_info -( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - talent_id BIGINT NOT NULL, - login VARCHAR(100) NOT NULL, - password VARCHAR(255) NOT NULL, - CONSTRAINT pk_user_info PRIMARY KEY (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) ); - drop table if exists kudos cascade; -CREATE TABLE kudos -( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - talent_id BIGINT, - proof_id BIGINT, - CONSTRAINT pk_kudos PRIMARY KEY (id) +CREATE TABLE kudos ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + sponsor_id BIGINT, + proof_id BIGINT, + CONSTRAINT pk_kudos PRIMARY KEY (id) ); +drop table if exists sponsor cascade; +CREATE TABLE sponsor ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + first_name VARCHAR(20), + last_name VARCHAR(20), + image VARCHAR(300), + 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); @@ -123,10 +129,10 @@ ALTER TABLE talent_talents 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); + 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); + 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_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); + 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/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 From 722637593128906fe5aa192e9f79d5bf47b51c5e Mon Sep 17 00:00:00 2001 From: Ren Date: Sat, 22 Apr 2023 20:09:18 +0300 Subject: [PATCH 02/59] * finished login and registration for sponsor * edit changeset * bugfix --- .../com/provedcode/config/SecurityConfig.java | 2 + .../sponsor/controller/SponsorController.java | 6 +- .../sponsor/service/SponsorService.java | 16 ++++-- .../controller/AuthenticationController.java | 17 ++++-- .../model/dto/SponsorRegistrationDTO.java | 20 +++++++ ...ionDTO.java => TalentRegistrationDTO.java} | 2 +- .../user/model/dto/UserInfoDTO.java | 3 +- .../user/service/AuthenticationService.java | 6 +- .../impl/AuthenticationServiceImpl.java | 55 +++++++++++++++++-- .../db/changelog/changeset/add-data.sql | 44 ++++++++++++++- 10 files changed, 146 insertions(+), 25 deletions(-) create mode 100644 src/main/java/com/provedcode/user/model/dto/SponsorRegistrationDTO.java rename src/main/java/com/provedcode/user/model/dto/{RegistrationDTO.java => TalentRegistrationDTO.java} (93%) diff --git a/src/main/java/com/provedcode/config/SecurityConfig.java b/src/main/java/com/provedcode/config/SecurityConfig.java index f725d5c..1997071 100644 --- a/src/main/java/com/provedcode/config/SecurityConfig.java +++ b/src/main/java/com/provedcode/config/SecurityConfig.java @@ -51,6 +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/*/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/sponsor/controller/SponsorController.java b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java index 406910b..d6a59a0 100644 --- a/src/main/java/com/provedcode/sponsor/controller/SponsorController.java +++ b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java @@ -20,7 +20,7 @@ public class SponsorController { SponsorService sponsorService; SponsorMapper sponsorMapper; - @GetMapping("/sponsor") + @GetMapping("/sponsors") @ResponseStatus(HttpStatus.OK) Page getSponsors(@RequestParam(value = "page") Optional page, @RequestParam(value = "size") Optional size) { @@ -28,8 +28,8 @@ Page getSponsors(@RequestParam(value = "page") Optional pag } @PreAuthorize("hasRole('SPONSOR')") - @GetMapping("/sponsor/{id}") + @GetMapping("/sponsors/{id}") SponsorDTO getSponsor(@PathVariable("id") long id, Authentication authentication) { - return sponsorMapper.toDto(sponsorService.getSponsorById(id)); + return sponsorMapper.toDto(sponsorService.getSponsorById(id, authentication)); } } \ 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 index 93fb044..4ec1dd1 100644 --- a/src/main/java/com/provedcode/sponsor/service/SponsorService.java +++ b/src/main/java/com/provedcode/sponsor/service/SponsorService.java @@ -3,22 +3,25 @@ import com.provedcode.config.PageProperties; import com.provedcode.sponsor.model.entity.Sponsor; import com.provedcode.sponsor.repository.SponsorRepository; +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.web.server.ResponseStatusException; import java.util.Optional; -import static org.springframework.http.HttpStatus.BAD_REQUEST; -import static org.springframework.http.HttpStatus.NOT_FOUND; +import static org.springframework.http.HttpStatus.*; @Service @AllArgsConstructor public class SponsorService { PageProperties pageProperties; SponsorRepository sponsorRepository; + UserInfoRepository userInfoRepository; public Page getAllSponsors(Optional page, Optional size) { if (page.orElse(pageProperties.defaultPageNum()) < 0) { @@ -31,8 +34,13 @@ public Page getAllSponsors(Optional page, Optional si size.orElse(pageProperties.defaultPageSize()))); } - public Sponsor getSponsorById(long id) { - return sponsorRepository.findById(id).orElseThrow( + public Sponsor getSponsorById(long id, Authentication authentication) { + Sponsor sponsor = sponsorRepository.findById(id).orElseThrow( () -> new ResponseStatusException(NOT_FOUND, String.format("sponsor with id = %d not found", id))); + UserInfo user = userInfoRepository.findByLogin(authentication.getName()).orElseThrow(); + + if (!sponsor.getId().equals(user.getSponsor().getId())) + throw new ResponseStatusException(FORBIDDEN, "The user cannot view someone else's profile"); + return sponsor; } } \ 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..b31e4c2 100644 --- a/src/main/java/com/provedcode/user/controller/AuthenticationController.java +++ b/src/main/java/com/provedcode/user/controller/AuthenticationController.java @@ -1,6 +1,7 @@ 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; @@ -19,7 +20,7 @@ @RestController @AllArgsConstructor @Slf4j -@RequestMapping("/api/v2/talents") +@RequestMapping("/api") public class AuthenticationController { AuthenticationService authenticationService; @@ -41,7 +42,7 @@ public class AuthenticationController { description = "UNAUTHORIZED", content = @Content) }) - @PostMapping("/login") + @PostMapping("/v2/login") UserInfoDTO login(Authentication authentication) { return authenticationService.login(authentication.getName(), authentication.getAuthorities()); } @@ -60,9 +61,15 @@ UserInfoDTO login(Authentication authentication) { description = "BAD_REQUEST", content = @Content), }) - @PostMapping("/register") + @PostMapping("/v2/talents/register") @ResponseStatus(HttpStatus.CREATED) - UserInfoDTO register(@RequestBody @Valid RegistrationDTO user) { + UserInfoDTO register(@RequestBody @Valid TalentRegistrationDTO user) { + return authenticationService.register(user); + } + + @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/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/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..ca72df0 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,7 +40,8 @@ public class AuthenticationServiceImpl implements AuthenticationService { JwtEncoder jwtEncoder; UserInfoRepository userInfoRepository; - TalentRepository talentEntityRepository; + TalentRepository talentRepository; + SponsorRepository sponsorRepository; AuthorityRepository authorityRepository; PasswordEncoder passwordEncoder; @@ -45,15 +49,19 @@ public class AuthenticationServiceImpl implements AuthenticationService { 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))); + "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()) + .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())); @@ -64,7 +72,7 @@ public UserInfoDTO register(RegistrationDTO user) { .lastName(user.lastName()) .specialization(user.specialization()) .build(); - talentEntityRepository.save(talent); + talentRepository.save(talent); UserInfo userInfo = UserInfo.builder() .talent(talent) @@ -83,6 +91,41 @@ public UserInfoDTO register(RegistrationDTO user) { 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()) + .lastName(user.lastName()) + .build(); + sponsorRepository.save(sponsor); + + UserInfo userInfo = UserInfo.builder() + .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(); + 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(sponsor.getId()) + .role(Role.SPONSOR.name()) .build(); } diff --git a/src/main/resources/db/changelog/changeset/add-data.sql b/src/main/resources/db/changelog/changeset/add-data.sql index 90393d2..8691281 100644 --- a/src/main/resources/db/changelog/changeset/add-data.sql +++ b/src/main/resources/db/changelog/changeset/add-data.sql @@ -1,15 +1,17 @@ --liquibase formatted sql --changeset dennis:1 -insert into authority (id, authority) -values (1, 'TALENT'); -values (2, 'SPONSOR'); -- -- 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) @@ -546,3 +548,39 @@ values ((select id from talent order by id desc limit 1), 'IhorKopieichykov@gmai 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 (first_name, last_name, image) +values ('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', '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 = 2)); + +insert into sponsor (first_name, last_name, image) +values ('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', '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 = 2)); + +insert into sponsor (first_name, last_name, image) +values ('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', '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 = 2)); + +insert into sponsor (first_name, last_name, image) +values ('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', '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 = 2)); \ No newline at end of file From 8cab03ea518f86bf4da9947ae300fa8c0214f4c2 Mon Sep 17 00:00:00 2001 From: Mykhailo Ordyntsev <102993813+Maslyna@users.noreply.github.com> Date: Sun, 23 Apr 2023 15:23:04 +0200 Subject: [PATCH 03/59] S3.2US2&4 (#103) * US2 COMPLETED! Created new PATCH edpoint (.../sponsors/id) * US2 COMPLETED 2nd TIME, YAY! * DELETE IS WORKING!!!!! *sounds of cry* --- .../provedcode/kudos/model/entity/Kudos.java | 2 +- .../sponsor/controller/SponsorController.java | 16 +++++ .../sponsor/model/dto/SponsorDTO.java | 4 ++ .../sponsor/model/dto/SponsorEditDTO.java | 17 +++++ .../sponsor/model/entity/Sponsor.java | 2 +- .../sponsor/service/SponsorService.java | 65 ++++++++++++++++++- .../db/changelog/changeset/create-tables.sql | 39 ++++++----- 7 files changed, 123 insertions(+), 22 deletions(-) create mode 100644 src/main/java/com/provedcode/sponsor/model/dto/SponsorEditDTO.java 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 198e433..4af769b 100644 --- a/src/main/java/com/provedcode/kudos/model/entity/Kudos.java +++ b/src/main/java/com/provedcode/kudos/model/entity/Kudos.java @@ -17,7 +17,7 @@ public class Kudos { @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; - @ManyToOne(cascade = CascadeType.ALL) + @ManyToOne @JoinColumn(name = "sponsor_id") private Sponsor sponsor; @ManyToOne(cascade = CascadeType.ALL) diff --git a/src/main/java/com/provedcode/sponsor/controller/SponsorController.java b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java index d6a59a0..4e94b9d 100644 --- a/src/main/java/com/provedcode/sponsor/controller/SponsorController.java +++ b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java @@ -2,6 +2,7 @@ import com.provedcode.sponsor.mapper.SponsorMapper; import com.provedcode.sponsor.model.dto.SponsorDTO; +import com.provedcode.sponsor.model.dto.SponsorEditDTO; import com.provedcode.sponsor.service.SponsorService; import com.provedcode.talent.model.dto.FullTalentDTO; import lombok.AllArgsConstructor; @@ -32,4 +33,19 @@ Page getSponsors(@RequestParam(value = "page") Optional pag SponsorDTO getSponsor(@PathVariable("id") long id, Authentication authentication) { return sponsorMapper.toDto(sponsorService.getSponsorById(id, authentication)); } + + @PreAuthorize("hasRole('SPONSOR')") + @PatchMapping("/sponsors/{id}") + SponsorDTO editSponsor(@PathVariable("id") long id, + @RequestBody SponsorEditDTO sponsorEditDTO, + Authentication authentication) { + return sponsorMapper.toDto(sponsorService.editSponsorById(id, sponsorEditDTO, authentication)); + } + + @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/model/dto/SponsorDTO.java b/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java index e01235b..adffbbd 100644 --- a/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java +++ b/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java @@ -1,8 +1,12 @@ package com.provedcode.sponsor.model.dto; +import com.fasterxml.jackson.annotation.JsonProperty; + public record SponsorDTO( Long id, + @JsonProperty("first_name") String firstName, + @JsonProperty("last_name") String lastName, String image ) { diff --git a/src/main/java/com/provedcode/sponsor/model/dto/SponsorEditDTO.java b/src/main/java/com/provedcode/sponsor/model/dto/SponsorEditDTO.java new file mode 100644 index 0000000..82867a5 --- /dev/null +++ b/src/main/java/com/provedcode/sponsor/model/dto/SponsorEditDTO.java @@ -0,0 +1,17 @@ +package com.provedcode.sponsor.model.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Builder; + +@Builder +public record SponsorEditDTO( + 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/model/entity/Sponsor.java b/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java index c471d88..35ea8a0 100644 --- a/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java +++ b/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java @@ -30,6 +30,6 @@ public class Sponsor { @URL @Column(name = "image", length = 300) private String image; - @OneToMany(mappedBy = "sponsor", cascade = CascadeType.ALL, orphanRemoval = true) + @OneToMany(mappedBy = "sponsor") private List kudoses = new ArrayList<>(); } \ 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 index 4ec1dd1..c1cc416 100644 --- a/src/main/java/com/provedcode/sponsor/service/SponsorService.java +++ b/src/main/java/com/provedcode/sponsor/service/SponsorService.java @@ -1,6 +1,10 @@ package com.provedcode.sponsor.service; import com.provedcode.config.PageProperties; +import com.provedcode.kudos.model.entity.Kudos; +import com.provedcode.kudos.repository.KudosRepository; +import com.provedcode.sponsor.model.dto.SponsorDTO; +import com.provedcode.sponsor.model.dto.SponsorEditDTO; import com.provedcode.sponsor.model.entity.Sponsor; import com.provedcode.sponsor.repository.SponsorRepository; import com.provedcode.user.model.entity.UserInfo; @@ -10,19 +14,26 @@ 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 java.util.stream.Collectors; +import java.util.stream.IntStream; import static org.springframework.http.HttpStatus.*; @Service @AllArgsConstructor +@Transactional public class SponsorService { PageProperties pageProperties; SponsorRepository sponsorRepository; UserInfoRepository userInfoRepository; + private final KudosRepository kudosRepository; + @Transactional(readOnly = true) public Page getAllSponsors(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"); @@ -31,16 +42,66 @@ public Page getAllSponsors(Optional page, Optional si throw new ResponseStatusException(BAD_REQUEST, "'size' query parameter must be greater than or equal to 1"); } return sponsorRepository.findAll(PageRequest.of(page.orElse(pageProperties.defaultPageNum()), - size.orElse(pageProperties.defaultPageSize()))); + size.orElse(pageProperties.defaultPageSize()))); } + @Transactional(readOnly = true) public Sponsor getSponsorById(long id, Authentication authentication) { Sponsor sponsor = sponsorRepository.findById(id).orElseThrow( () -> new ResponseStatusException(NOT_FOUND, String.format("sponsor with id = %d not found", id))); - UserInfo user = userInfoRepository.findByLogin(authentication.getName()).orElseThrow(); + UserInfo user = userInfoRepository.findByLogin(authentication.getName()) + .orElseThrow(() -> new ResponseStatusException(NOT_IMPLEMENTED, "login is not valid")); if (!sponsor.getId().equals(user.getSponsor().getId())) throw new ResponseStatusException(FORBIDDEN, "The user cannot view someone else's profile"); return sponsor; } + + public Sponsor editSponsorById(long id, SponsorEditDTO sponsorEditDTO, Authentication authentication) { + Sponsor sponsor = sponsorRepository.findById(id) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "sponsor with id = %s not found".formatted(id))); + UserInfo user = userInfoRepository.findByLogin(authentication.getName()) + .orElseThrow(() -> new ResponseStatusException(NOT_IMPLEMENTED, "login is not valid")); + if (!sponsor.getId().equals(user.getSponsor().getId())) { + throw new ResponseStatusException(FORBIDDEN, "The user cannot edit someone else's profile"); + } + + if (sponsorEditDTO.firstName() != null) { + sponsor.setFirstName(sponsorEditDTO.firstName()); + } + if (sponsorEditDTO.lastName() != null) { + sponsor.setLastName(sponsorEditDTO.lastName()); + } + if (sponsorEditDTO.image() != null) { + sponsor.setImage(sponsorEditDTO.image()); + } + if (sponsorEditDTO.countOfKudos() != null) { + if (sponsorEditDTO.countOfKudos() > 0) { + List kudosList = IntStream.iterate(0, i -> i < sponsorEditDTO.countOfKudos(), i -> i + 1).boxed() + .map(i -> Kudos.builder() + .sponsor(sponsor) + .build()) + .toList(); + kudosRepository.saveAll(kudosList); + sponsor.getKudoses().addAll(kudosList); + } else { + throw new ResponseStatusException(BAD_REQUEST, "count of kudos must be greater than 0"); + } + } + return sponsorRepository.save(sponsor); + } + + public void deleteSponsor(long id, Authentication authentication) { + Sponsor sponsor = sponsorRepository.findById(id) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "sponsor with id = %s not found".formatted(id))); + UserInfo user = userInfoRepository.findByLogin(authentication.getName()) + .orElseThrow(() -> new ResponseStatusException(NOT_IMPLEMENTED, "login is not valid")); + if (!sponsor.getId().equals(user.getSponsor().getId())) { + throw new ResponseStatusException(FORBIDDEN, "The user cannot edit someone else's profile"); + } + + List kudosList = sponsor.getKudoses().stream().map(i -> {i.setSponsor(null); return i;}).toList(); + sponsor.setKudoses(kudosList); + userInfoRepository.delete(user); + } } \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/create-tables.sql b/src/main/resources/db/changelog/changeset/create-tables.sql index 40927c3..9324bd4 100644 --- a/src/main/resources/db/changelog/changeset/create-tables.sql +++ b/src/main/resources/db/changelog/changeset/create-tables.sql @@ -88,30 +88,33 @@ CREATE TABLE user_authorities ); drop table if exists user_info cascade; -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 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) ); drop table if exists kudos cascade; -CREATE TABLE kudos ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - sponsor_id BIGINT, - proof_id BIGINT, - CONSTRAINT pk_kudos PRIMARY KEY (id) +CREATE TABLE kudos +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + sponsor_id BIGINT, + proof_id BIGINT, + CONSTRAINT pk_kudos PRIMARY KEY (id) ); drop table if exists sponsor cascade; -CREATE TABLE sponsor ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - first_name VARCHAR(20), - last_name VARCHAR(20), - image VARCHAR(300), - CONSTRAINT pk_sponsor 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(300), + CONSTRAINT pk_sponsor PRIMARY KEY (id) ); ALTER TABLE talent_attached_file From f4082631d85e88d7abb4426c8a53e3bd439971a1 Mon Sep 17 00:00:00 2001 From: Denis973 <46610112+Denis973@users.noreply.github.com> Date: Tue, 25 Apr 2023 19:23:41 +0300 Subject: [PATCH 04/59] S3.2 us3 (#105) * us3 * us3 bug fix * bug fix * add swagger kudos and sponsor * add ExceptionHandler --- .../com/provedcode/handlers/ApiError.java | 28 ++++ .../handlers/TalentExceptionHandler.java | 90 ++++++++++ .../kudos/controller/KudosController.java | 113 ++++++++++--- .../provedcode/kudos/model/entity/Kudos.java | 2 + .../response/KudosAmountWithSponsor.java | 13 ++ .../kudos/service/KudosService.java | 154 ++++++++++-------- .../sponsor/controller/SponsorController.java | 92 ++++++++++- .../sponsor/model/entity/Sponsor.java | 2 + .../sponsor/service/SponsorService.java | 13 +- .../talent/controller/TalentController.java | 5 +- .../controller/AuthenticationController.java | 14 ++ .../impl/AuthenticationServiceImpl.java | 85 +++++----- .../db/changelog/changeset/add-data.sql | 33 ++-- .../db/changelog/changeset/create-tables.sql | 2 + 14 files changed, 489 insertions(+), 157 deletions(-) create mode 100644 src/main/java/com/provedcode/handlers/ApiError.java create mode 100644 src/main/java/com/provedcode/kudos/model/response/KudosAmountWithSponsor.java 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/TalentExceptionHandler.java b/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java index 1c63234..cf460c5 100644 --- a/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java +++ b/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java @@ -1,14 +1,104 @@ package com.provedcode.handlers; +import jakarta.validation.ConstraintViolation; +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.context.request.WebRequest; import org.springframework.web.server.ResponseStatusException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + @ControllerAdvice public class TalentExceptionHandler { @ExceptionHandler(ResponseStatusException.class) private ResponseEntity responseStatusExceptionHandler(ResponseStatusException exception) { return ResponseEntity.status(exception.getStatusCode()).body(exception.getBody()); } + + @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(); + } + } + } + } + } + + 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({ 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/kudos/controller/KudosController.java b/src/main/java/com/provedcode/kudos/controller/KudosController.java index fcd85c8..20f8bce 100644 --- a/src/main/java/com/provedcode/kudos/controller/KudosController.java +++ b/src/main/java/com/provedcode/kudos/controller/KudosController.java @@ -1,32 +1,107 @@ package com.provedcode.kudos.controller; +import com.provedcode.kudos.model.response.KudosAmountWithSponsor; import com.provedcode.kudos.service.KudosService; 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 lombok.AllArgsConstructor; +import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; @RestController @AllArgsConstructor -@RequestMapping("/api/v3/talent") +@RequestMapping("/api/v3/") public class KudosController { -// KudosService kudosService; -// -// @GetMapping("/proofs/{proof-id}/kudos") -// KudosAmount getKudosProof(@PathVariable("proof-id") long id) { -// return kudosService.getAmountKudosProof(id); -// } -// -// @PreAuthorize("hasRole('TALENT')") -// @PostMapping("/proofs/{proof-id}/kudos") -// void addKudosToProof(@PathVariable("proof-id") long id, Authentication authentication) { -// kudosService.addKudosToProof(id, authentication); -// } -// -// @PreAuthorize("hasRole('TALENT')") -// @DeleteMapping("/proofs/{proof-id}/kudos") -// void deleteKudosFromProof(@PathVariable("proof-id") long id, Authentication authentication) { -// kudosService.deleteKudosFromProof(id, authentication); -// } + KudosService kudosService; + + @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) + }) + @PreAuthorize("hasRole('SPONSOR')") + @GetMapping("/sponsors/{sponsor-id}/kudos") + KudosAmount getKudosForSponsor(@PathVariable("sponsor-id") long id, Authentication authentication) { + return kudosService.getKudosForSponsor(id, authentication); + } + + @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) + }) + @PreAuthorize("hasRole('SPONSOR')") + @PostMapping("/proofs/{proof-id}/kudos/{amount}") + void addKudosToProof(@PathVariable("proof-id") long id, + @PathVariable("amount") Long amount, + Authentication authentication) { + kudosService.addKudosToProof(id, amount, authentication); + } + + @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) + }) + @PreAuthorize("hasRole('TALENT')") + @GetMapping("/proofs/{proof-id}/kudos") + KudosAmountWithSponsor getProofKudos(@PathVariable("proof-id") long id, Authentication authentication) { + return kudosService.getProofKudos(id, 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 4af769b..8cacb21 100644 --- a/src/main/java/com/provedcode/kudos/model/entity/Kudos.java +++ b/src/main/java/com/provedcode/kudos/model/entity/Kudos.java @@ -17,6 +17,8 @@ public class Kudos { @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; + @Column(name = "amount_kudos") + private Long amountKudos; @ManyToOne @JoinColumn(name = "sponsor_id") private Sponsor sponsor; 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..16b302b --- /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/service/KudosService.java b/src/main/java/com/provedcode/kudos/service/KudosService.java index c98995e..65dd7bf 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -2,8 +2,12 @@ import com.provedcode.kudos.model.entity.Kudos; import com.provedcode.kudos.model.response.KudosAmount; +import com.provedcode.kudos.model.response.KudosAmountWithSponsor; import com.provedcode.kudos.repository.KudosRepository; -import com.provedcode.talent.model.ProofStatus; +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.entity.Talent; import com.provedcode.talent.model.entity.TalentProof; import com.provedcode.talent.repo.TalentProofRepository; @@ -11,13 +15,14 @@ import com.provedcode.user.model.entity.UserInfo; import com.provedcode.user.repo.UserInfoRepository; import lombok.AllArgsConstructor; -import org.springframework.http.HttpStatus; 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.HashMap; +import java.util.Map; +import java.util.stream.Collectors; import static org.springframework.http.HttpStatus.*; @@ -25,68 +30,83 @@ @AllArgsConstructor @Transactional public class KudosService { -// KudosRepository kudosRepository; -// TalentRepository talentRepository; -// TalentProofRepository talentProofRepository; -// UserInfoRepository userInfoRepository; -// -// @Transactional(readOnly = true) -// public KudosAmount getAmountKudosProof(long id) { -// 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); -// return new KudosAmount(count); -// } -// -// 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.existsByTalent(talent)) { -// throw new ResponseStatusException(CONFLICT, "Talent can give only one `kudos` for one proof"); -// } -// if (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { -// throw new ResponseStatusException(FORBIDDEN); -// } -// -// kudosRepository.save(Kudos.builder() -// .proof(talentProof) -// .talent(talent) -// .build()); -// } -// -// 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))); -// -// if (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { -// throw new ResponseStatusException(FORBIDDEN); -// } -// if (!kudosRepository.existsByTalent(talent)) { -// throw new ResponseStatusException(CONFLICT, "kudos don`t exist"); -// } -// -// 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); -// } + KudosRepository kudosRepository; + TalentProofRepository talentProofRepository; + UserInfoRepository userInfoRepository; + SponsorRepository sponsorRepository; + TalentRepository talentRepository; + SponsorMapper sponsorMapper; + + + public void addKudosToProof(long id, Long amount, Authentication authentication) { + UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Sponsor with id = %s not found".formatted(id))); + Sponsor sponsor = sponsorRepository.findById(userInfo.getSponsor().getId()).orElseThrow( + () -> new ResponseStatusException(NOT_FOUND, + String.format("sponsor with id = %d not found", id))); + TalentProof talentProof = talentProofRepository.findById(id) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "Proof with id = %s not found".formatted(id))); + if (sponsor.getAmountKudos() < amount) { + throw new ResponseStatusException(FORBIDDEN, "The sponsor cannot give more kudos than he has"); + } + if (amount <= 0) { + throw new ResponseStatusException(BAD_REQUEST, "amount of kudos must be greater than 0"); + } + sponsor.setAmountKudos(sponsor.getAmountKudos() - amount); + kudosRepository.save(Kudos.builder() + .amountKudos(amount) + .proof(talentProof) + .sponsor(sponsor) + .build()); + } + + @Transactional(readOnly = true) + public KudosAmount getKudosForSponsor(long id, Authentication authentication) { + UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Sponsor with id = %s not found".formatted(id))); + Sponsor sponsor = sponsorRepository.findById(userInfo.getSponsor().getId()).orElseThrow( + () -> new ResponseStatusException(NOT_FOUND, + String.format("Sponsor with id = %d not found", id))); + if (sponsor.getId() != userInfo.getSponsor().getId()) { + throw new ResponseStatusException(FORBIDDEN, "Only the account owner can view the number of kudos"); + } + return new KudosAmount(sponsor.getAmountKudos()); + } + + @Transactional(readOnly = true) + public KudosAmountWithSponsor getProofKudos(long id, Authentication authentication) { + UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Sponsor with id = %s not found".formatted(id))); + Talent talent = talentRepository.findById(userInfo.getId()) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Talent with id = %s not found".formatted(id))); + TalentProof talentProof = talentProofRepository.findById(id) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Proof with id = %s not found".formatted(id))); + + if (talent.getId() == talentProof.getTalent().getId()) { + Map kudosFromSponsor = talentProof.getKudos().stream() + .collect(Collectors.toMap( + sponsor -> sponsorMapper.toDto(sponsor.getSponsor()), + Kudos::getAmountKudos, + (sponsor, kudos) -> sponsor, + HashMap::new + )); + Long counter = talentProof.getKudos().stream().map(i -> i.getAmountKudos()) + .mapToLong(Long::intValue).sum(); + return KudosAmountWithSponsor.builder() + .allKudosOnProof(counter) + .kudosFromSponsor(kudosFromSponsor) + .build(); + } else { + Long counter = talentProof.getKudos().stream().map(i -> i.getAmountKudos()) + .mapToLong(Long::intValue).sum(); + return KudosAmountWithSponsor.builder() + .allKudosOnProof(counter) + .kudosFromSponsor(null).build(); + } + } } \ 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 index 4e94b9d..ea61f10 100644 --- a/src/main/java/com/provedcode/sponsor/controller/SponsorController.java +++ b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java @@ -4,10 +4,15 @@ import com.provedcode.sponsor.model.dto.SponsorDTO; import com.provedcode.sponsor.model.dto.SponsorEditDTO; import com.provedcode.sponsor.service.SponsorService; -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 lombok.AllArgsConstructor; 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.web.bind.annotation.*; @@ -21,6 +26,17 @@ public class SponsorController { SponsorService sponsorService; SponsorMapper sponsorMapper; + @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) + }) @GetMapping("/sponsors") @ResponseStatus(HttpStatus.OK) Page getSponsors(@RequestParam(value = "page") Optional page, @@ -28,12 +44,59 @@ Page getSponsors(@RequestParam(value = "page") Optional pag return sponsorService.getAllSponsors(page, size).map(sponsorMapper::toDto); } + @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) + }) @PreAuthorize("hasRole('SPONSOR')") @GetMapping("/sponsors/{id}") SponsorDTO getSponsor(@PathVariable("id") long id, Authentication authentication) { return sponsorMapper.toDto(sponsorService.getSponsorById(id, authentication)); } + @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) + }) @PreAuthorize("hasRole('SPONSOR')") @PatchMapping("/sponsors/{id}") SponsorDTO editSponsor(@PathVariable("id") long id, @@ -42,10 +105,35 @@ SponsorDTO editSponsor(@PathVariable("id") long id, return sponsorMapper.toDto(sponsorService.editSponsorById(id, sponsorEditDTO, authentication)); } + @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), + }) @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/model/entity/Sponsor.java b/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java index 35ea8a0..30b12d7 100644 --- a/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java +++ b/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java @@ -21,6 +21,8 @@ public class Sponsor { @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; diff --git a/src/main/java/com/provedcode/sponsor/service/SponsorService.java b/src/main/java/com/provedcode/sponsor/service/SponsorService.java index c1cc416..933fb69 100644 --- a/src/main/java/com/provedcode/sponsor/service/SponsorService.java +++ b/src/main/java/com/provedcode/sponsor/service/SponsorService.java @@ -2,8 +2,6 @@ import com.provedcode.config.PageProperties; import com.provedcode.kudos.model.entity.Kudos; -import com.provedcode.kudos.repository.KudosRepository; -import com.provedcode.sponsor.model.dto.SponsorDTO; import com.provedcode.sponsor.model.dto.SponsorEditDTO; import com.provedcode.sponsor.model.entity.Sponsor; import com.provedcode.sponsor.repository.SponsorRepository; @@ -19,8 +17,6 @@ import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.IntStream; import static org.springframework.http.HttpStatus.*; @@ -31,7 +27,6 @@ public class SponsorService { PageProperties pageProperties; SponsorRepository sponsorRepository; UserInfoRepository userInfoRepository; - private final KudosRepository kudosRepository; @Transactional(readOnly = true) public Page getAllSponsors(Optional page, Optional size) { @@ -77,13 +72,7 @@ public Sponsor editSponsorById(long id, SponsorEditDTO sponsorEditDTO, Authentic } if (sponsorEditDTO.countOfKudos() != null) { if (sponsorEditDTO.countOfKudos() > 0) { - List kudosList = IntStream.iterate(0, i -> i < sponsorEditDTO.countOfKudos(), i -> i + 1).boxed() - .map(i -> Kudos.builder() - .sponsor(sponsor) - .build()) - .toList(); - kudosRepository.saveAll(kudosList); - sponsor.getKudoses().addAll(kudosList); + sponsor.setAmountKudos(sponsor.getAmountKudos() + sponsorEditDTO.countOfKudos()); } else { throw new ResponseStatusException(BAD_REQUEST, "count of kudos must be greater than 0"); } diff --git a/src/main/java/com/provedcode/talent/controller/TalentController.java b/src/main/java/com/provedcode/talent/controller/TalentController.java index 4c8ea81..5ab3d23 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentController.java @@ -33,7 +33,7 @@ public class TalentController { TalentService talentService; TalentMapper talentMapper; - @Operation(summary = "Get all talents", + @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", @@ -114,8 +114,7 @@ FullTalentDTO editTalent(@PathVariable("talent-id") long id, @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "SUCCESS", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = FullTalentDTO.class))), + content = @Content), @ApiResponse(responseCode = "404", description = "NOT FOUND ", content = @Content), diff --git a/src/main/java/com/provedcode/user/controller/AuthenticationController.java b/src/main/java/com/provedcode/user/controller/AuthenticationController.java index b31e4c2..69559c6 100644 --- a/src/main/java/com/provedcode/user/controller/AuthenticationController.java +++ b/src/main/java/com/provedcode/user/controller/AuthenticationController.java @@ -67,6 +67,20 @@ UserInfoDTO register(@RequestBody @Valid TalentRegistrationDTO user) { return authenticationService.register(user); } + @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), + }) @PostMapping("/v3/sponsors/register") @ResponseStatus(HttpStatus.CREATED) UserInfoDTO register(@RequestBody @Valid 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 ca72df0..9fbd2b2 100644 --- a/src/main/java/com/provedcode/user/service/impl/AuthenticationServiceImpl.java +++ b/src/main/java/com/provedcode/user/service/impl/AuthenticationServiceImpl.java @@ -48,38 +48,38 @@ public class AuthenticationServiceImpl implements AuthenticationService { @Transactional(readOnly = true) public UserInfoDTO login(String name, Collection authorities) { UserInfo userInfo = userInfoRepository.findByLogin(name) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, String.format( - "user with login = %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(userRole.equals(Role.TALENT) ? userInfo.getTalent().getId() - : userInfo.getSponsor().getId()) - .role(userRole.name()) - .build(); + .token(generateJWTToken(name, authorities)) + .id(userRole.equals(Role.TALENT) ? userInfo.getTalent().getId() + : userInfo.getSponsor().getId()) + .role(userRole.name()) + .build(); } 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(); + .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(); + .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(); @@ -89,31 +89,32 @@ public UserInfoDTO register(TalentRegistrationDTO 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()) - .role(Role.TALENT.name()) - .build(); + .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())); + String.format("user with login = {%s} already exists", user.login())); } Sponsor sponsor = Sponsor.builder() - .firstName(user.firstName()) - .lastName(user.lastName()) - .build(); + .firstName(user.firstName()) + .amountKudos(0L) + .lastName(user.lastName()) + .build(); sponsorRepository.save(sponsor); UserInfo userInfo = UserInfo.builder() - .sponsor(sponsor) - .login(user.login()) - .password(passwordEncoder.encode(user.password())) - .authorities( - Set.of(authorityRepository.findByAuthority(Role.SPONSOR).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(); @@ -123,10 +124,10 @@ public UserInfoDTO register(SponsorRegistrationDTO user) { log.info("user with login {%s} was saved, his authorities: %s".formatted(userLogin, userAuthorities)); return UserInfoDTO.builder() - .token(generateJWTToken(userLogin, userAuthorities)) - .id(sponsor.getId()) - .role(Role.SPONSOR.name()) - .build(); + .token(generateJWTToken(userLogin, userAuthorities)) + .id(sponsor.getId()) + .role(Role.SPONSOR.name()) + .build(); } private String generateJWTToken(String name, Collection authorities) { @@ -134,13 +135,13 @@ private String generateJWTToken(String name, Collection Date: Tue, 25 Apr 2023 19:51:54 +0200 Subject: [PATCH 05/59] Updated liquibase: - new changesets --- .../com/provedcode/config/InitConfig.java | 58 +- src/main/resources/application-dev.properties | 2 - .../resources/application-prod.properties | 4 +- src/main/resources/application.properties | 13 +- .../db/changelog/changeset/V1/data-V1.sql | 547 ++++++++++++++++++ .../db/changelog/changeset/V1/drop-V1.sql | 14 + .../db/changelog/changeset/V1/schema-V1.sql | 132 +++++ .../{add-data.sql => V2/data-V2.sql} | 36 +- .../db/changelog/changeset/V2/drop-V2.sql | 15 + .../{create-tables.sql => V2/schema-V2.sql} | 27 +- .../db/changelog/db.changelog-master.yaml | 9 +- 11 files changed, 772 insertions(+), 85 deletions(-) create mode 100644 src/main/resources/db/changelog/changeset/V1/data-V1.sql create mode 100644 src/main/resources/db/changelog/changeset/V1/drop-V1.sql create mode 100644 src/main/resources/db/changelog/changeset/V1/schema-V1.sql rename src/main/resources/db/changelog/changeset/{add-data.sql => V2/data-V2.sql} (96%) create mode 100644 src/main/resources/db/changelog/changeset/V2/drop-V2.sql rename src/main/resources/db/changelog/changeset/{create-tables.sql => V2/schema-V2.sql} (88%) diff --git a/src/main/java/com/provedcode/config/InitConfig.java b/src/main/java/com/provedcode/config/InitConfig.java index f4d24bb..82aa7cb 100644 --- a/src/main/java/com/provedcode/config/InitConfig.java +++ b/src/main/java/com/provedcode/config/InitConfig.java @@ -1,29 +1,29 @@ -package com.provedcode.config; - -import com.provedcode.user.mapper.UserInfoMapper; -import com.provedcode.user.repo.UserInfoRepository; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.CommandLineRunner; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Component; - -@Slf4j -@Component -@AllArgsConstructor -public class InitConfig implements CommandLineRunner { - UserInfoRepository userInfoRepository; - PasswordEncoder passwordEncoder; - UserInfoMapper userInfoMapper; - - @Override - public void run(String... args) throws Exception { - // TODO: Method to change passwords for already created users from data1.sql - userInfoRepository.saveAll( - userInfoRepository.findAll().stream() - .map(i -> { - i.setPassword(passwordEncoder.encode(i.getPassword())); - return i; - }).toList()); - } -} \ No newline at end of file +//package com.provedcode.config; +// +//import com.provedcode.user.mapper.UserInfoMapper; +//import com.provedcode.user.repo.UserInfoRepository; +//import lombok.AllArgsConstructor; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.boot.CommandLineRunner; +//import org.springframework.security.crypto.password.PasswordEncoder; +//import org.springframework.stereotype.Component; +// +//@Slf4j +//@Component +//@AllArgsConstructor +//public class InitConfig implements CommandLineRunner { +// UserInfoRepository userInfoRepository; +// PasswordEncoder passwordEncoder; +// UserInfoMapper userInfoMapper; +// +// @Override +// public void run(String... args) throws Exception { +// // TODO: Method to change passwords for already created users from data1.sql +// userInfoRepository.saveAll( +// userInfoRepository.findAll().stream() +// .map(i -> { +// i.setPassword(passwordEncoder.encode(i.getPassword())); +// return i; +// }).toList()); +// } +//} \ No newline at end of file diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 4b8f38f..6bd5814 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 dbc8154..f91aa56 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -11,7 +11,8 @@ spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect spring.datasource.driver-class-name=org.postgresql.Driver spring.h2.console.enabled=true spring.h2.console.path=/h2 -spring.jpa.hibernate.ddl-auto=create-drop +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/V1/data-V1.sql b/src/main/resources/db/changelog/changeset/V1/data-V1.sql new file mode 100644 index 0000000..3b8e80a --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V1/data-V1.sql @@ -0,0 +1,547 @@ +--liquibase formatted sql +--changeset dennis:1 + +insert into authority (id, authority) +values (1, 'TALENT'); +-- -- 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 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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); \ 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/V1/schema-V1.sql b/src/main/resources/db/changelog/changeset/V1/schema-V1.sql new file mode 100644 index 0000000..7eccc32 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V1/schema-V1.sql @@ -0,0 +1,132 @@ +-- liquibase formatted sql +-- changeset dennis:1 + +drop table if exists authority cascade; + +CREATE TABLE authority +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + authority VARCHAR(20) NOT NULL, + CONSTRAINT pk_authority PRIMARY KEY (id) +); + +drop table if exists talent cascade; +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(300), + CONSTRAINT pk_talent PRIMARY KEY (id) +); + +drop table if exists talent_attached_file cascade; +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) +); + +drop table if exists talent_contact cascade; +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) +); + +drop table if exists talent_description cascade; +CREATE TABLE talent_description +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL, + bio VARCHAR(255), + addition_info VARCHAR(255), + CONSTRAINT pk_talent_description PRIMARY KEY (id) +); + +drop table if exists talent_link cascade; +CREATE TABLE talent_link +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL, + link VARCHAR(255), + CONSTRAINT pk_talent_link PRIMARY KEY (id) +); + +drop table if exists talent_proofs cascade; +CREATE TABLE talent_proofs +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL, + link VARCHAR(100), + text VARCHAR(255), + status VARCHAR(20) NOT NULL, + created TIMESTAMP, + CONSTRAINT pk_talent_proofs PRIMARY KEY (id) +); + +drop table if exists talent_talents cascade; +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) +); + +drop table if exists user_authorities cascade; +CREATE TABLE user_authorities +( + authority_id BIGINT NOT NULL, + user_id BIGINT NOT NULL, + CONSTRAINT pk_user_authorities PRIMARY KEY (authority_id, user_id) +); + +drop table if exists user_info cascade; +CREATE TABLE user_info +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL, + login VARCHAR(100) NOT NULL, + password VARCHAR(255) NOT NULL, + CONSTRAINT pk_user_info PRIMARY KEY (id) +); + + +drop table if exists kudos cascade; +CREATE TABLE kudos +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT, + proof_id BIGINT, + CONSTRAINT pk_kudos 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_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/add-data.sql b/src/main/resources/db/changelog/changeset/V2/data-V2.sql similarity index 96% rename from src/main/resources/db/changelog/changeset/add-data.sql rename to src/main/resources/db/changelog/changeset/V2/data-V2.sql index ce9026b..e0d6ee0 100644 --- a/src/main/resources/db/changelog/changeset/add-data.sql +++ b/src/main/resources/db/changelog/changeset/V2/data-V2.sql @@ -1,5 +1,5 @@ --liquibase formatted sql ---changeset dennis:1 +--changeset mykhailo:2 -- -- FOR USER AUTHORITY -- -- SELECT USER_INFO.ID , LOGIN , PASSWORD, talent_id , AUTHORITY FROM @@ -50,7 +50,7 @@ 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', '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)); @@ -93,7 +93,7 @@ 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', '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)); @@ -134,7 +134,7 @@ 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', '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)); @@ -174,7 +174,7 @@ 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', '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)); @@ -216,7 +216,7 @@ 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', '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)); @@ -256,7 +256,7 @@ 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', '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)); @@ -298,7 +298,7 @@ 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', '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)); @@ -338,7 +338,7 @@ 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', '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)); @@ -380,7 +380,7 @@ 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', '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)); @@ -420,7 +420,7 @@ 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', '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)); @@ -460,7 +460,7 @@ 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', '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)); @@ -502,7 +502,7 @@ 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', '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)); @@ -544,7 +544,7 @@ 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', 'password'); +values ((select id from talent order by id desc limit 1), '$2a$10$D4KM50WemOahkFv1fkrPX.MvVESsE0TYWlkh5TypTE/q4nlv8ooyS', '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)); @@ -553,7 +553,7 @@ 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', '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) ); @@ -562,7 +562,7 @@ 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', '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) ); @@ -571,7 +571,7 @@ 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', '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) ); @@ -580,7 +580,7 @@ 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', '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) ); 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/create-tables.sql b/src/main/resources/db/changelog/changeset/V2/schema-V2.sql similarity index 88% rename from src/main/resources/db/changelog/changeset/create-tables.sql rename to src/main/resources/db/changelog/changeset/V2/schema-V2.sql index 18a84f4..2519646 100644 --- a/src/main/resources/db/changelog/changeset/create-tables.sql +++ b/src/main/resources/db/changelog/changeset/V2/schema-V2.sql @@ -1,7 +1,8 @@ -- liquibase formatted sql --- changeset dennis:1 +-- changeset mykhailo:2 + +-- tables for sprint 3.2 -drop table if exists authority cascade; CREATE TABLE authority ( @@ -9,8 +10,6 @@ CREATE TABLE authority authority VARCHAR(20) NOT NULL, CONSTRAINT pk_authority PRIMARY KEY (id) ); - -drop table if exists talent cascade; CREATE TABLE talent ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -20,8 +19,6 @@ CREATE TABLE talent image VARCHAR(300), CONSTRAINT pk_talent PRIMARY KEY (id) ); - -drop table if exists talent_attached_file cascade; CREATE TABLE talent_attached_file ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -29,8 +26,6 @@ CREATE TABLE talent_attached_file attached_file VARCHAR(100), CONSTRAINT pk_talent_attached_file PRIMARY KEY (id) ); - -drop table if exists talent_contact cascade; CREATE TABLE talent_contact ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -38,8 +33,6 @@ CREATE TABLE talent_contact contact VARCHAR(255), CONSTRAINT pk_talent_contact PRIMARY KEY (id) ); - -drop table if exists talent_description cascade; CREATE TABLE talent_description ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -48,8 +41,6 @@ CREATE TABLE talent_description addition_info VARCHAR(255), CONSTRAINT pk_talent_description PRIMARY KEY (id) ); - -drop table if exists talent_link cascade; CREATE TABLE talent_link ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -57,8 +48,6 @@ CREATE TABLE talent_link link VARCHAR(255), CONSTRAINT pk_talent_link PRIMARY KEY (id) ); - -drop table if exists talent_proofs cascade; CREATE TABLE talent_proofs ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -69,8 +58,6 @@ CREATE TABLE talent_proofs created TIMESTAMP, CONSTRAINT pk_talent_proofs PRIMARY KEY (id) ); - -drop table if exists talent_talents cascade; CREATE TABLE talent_talents ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -78,16 +65,12 @@ CREATE TABLE talent_talents talent_name VARCHAR(255), CONSTRAINT pk_talent_talents PRIMARY KEY (id) ); - -drop table if exists user_authorities cascade; CREATE TABLE user_authorities ( authority_id BIGINT NOT NULL, user_id BIGINT NOT NULL, CONSTRAINT pk_user_authorities PRIMARY KEY (authority_id, user_id) ); - -drop table if exists user_info cascade; CREATE TABLE user_info ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -97,8 +80,6 @@ CREATE TABLE user_info password VARCHAR(255) NOT NULL, CONSTRAINT pk_user_info PRIMARY KEY (id) ); - -drop table if exists kudos cascade; CREATE TABLE kudos ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -107,8 +88,6 @@ CREATE TABLE kudos amount_kudos BIGINT, CONSTRAINT pk_kudos PRIMARY KEY (id) ); - -drop table if exists sponsor cascade; CREATE TABLE sponsor ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, 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 From 1ddf4d1a7d833412315647dd8b3fab2860bcc6fb Mon Sep 17 00:00:00 2001 From: Maslyna Date: Tue, 25 Apr 2023 20:46:59 +0200 Subject: [PATCH 06/59] BUGFIX: `GET(/api/v3/proofs/1/kudos)`` has problems after deleting a `sponsor` --- .../model/response/KudosAmountWithSponsor.java | 2 +- .../com/provedcode/kudos/service/KudosService.java | 14 ++++++++------ .../provedcode/sponsor/model/dto/SponsorDTO.java | 2 ++ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/provedcode/kudos/model/response/KudosAmountWithSponsor.java b/src/main/java/com/provedcode/kudos/model/response/KudosAmountWithSponsor.java index 16b302b..75b80f9 100644 --- a/src/main/java/com/provedcode/kudos/model/response/KudosAmountWithSponsor.java +++ b/src/main/java/com/provedcode/kudos/model/response/KudosAmountWithSponsor.java @@ -8,6 +8,6 @@ @Builder public record KudosAmountWithSponsor( Long allKudosOnProof, - Map kudosFromSponsor + Map kudosFromSponsor ) { } diff --git a/src/main/java/com/provedcode/kudos/service/KudosService.java b/src/main/java/com/provedcode/kudos/service/KudosService.java index 65dd7bf..7ccd36e 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -22,6 +22,8 @@ import java.util.HashMap; import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; import static org.springframework.http.HttpStatus.*; @@ -87,22 +89,22 @@ public KudosAmountWithSponsor getProofKudos(long id, Authentication authenticati .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "Proof with id = %s not found".formatted(id))); - if (talent.getId() == talentProof.getTalent().getId()) { - Map kudosFromSponsor = talentProof.getKudos().stream() + if (Objects.equals(talent.getId(), talentProof.getTalent().getId())) { + Map kudosFromSponsor = talentProof.getKudos().stream() .collect(Collectors.toMap( - sponsor -> sponsorMapper.toDto(sponsor.getSponsor()), Kudos::getAmountKudos, - (sponsor, kudos) -> sponsor, + proof -> proof.getSponsor() != null ? sponsorMapper.toDto(proof.getSponsor()) : SponsorDTO.builder().build(), + (prev, next) -> next, HashMap::new )); - Long counter = talentProof.getKudos().stream().map(i -> i.getAmountKudos()) + Long counter = talentProof.getKudos().stream().map(Kudos::getAmountKudos) .mapToLong(Long::intValue).sum(); return KudosAmountWithSponsor.builder() .allKudosOnProof(counter) .kudosFromSponsor(kudosFromSponsor) .build(); } else { - Long counter = talentProof.getKudos().stream().map(i -> i.getAmountKudos()) + Long counter = talentProof.getKudos().stream().map(Kudos::getAmountKudos) .mapToLong(Long::intValue).sum(); return KudosAmountWithSponsor.builder() .allKudosOnProof(counter) diff --git a/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java b/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java index adffbbd..62c3b62 100644 --- a/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java +++ b/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java @@ -1,7 +1,9 @@ package com.provedcode.sponsor.model.dto; import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Builder; +@Builder public record SponsorDTO( Long id, @JsonProperty("first_name") From 1b4588d8cc7e95999923f15c5917c0d4da76fadd Mon Sep 17 00:00:00 2001 From: Maslyna Date: Tue, 25 Apr 2023 21:32:51 +0200 Subject: [PATCH 07/59] Little update --- .../kudos/service/KudosService.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/provedcode/kudos/service/KudosService.java b/src/main/java/com/provedcode/kudos/service/KudosService.java index 7ccd36e..2edcdd3 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -22,8 +22,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.Objects; -import java.util.Optional; import java.util.stream.Collectors; import static org.springframework.http.HttpStatus.*; @@ -71,7 +69,7 @@ public KudosAmount getKudosForSponsor(long id, Authentication authentication) { Sponsor sponsor = sponsorRepository.findById(userInfo.getSponsor().getId()).orElseThrow( () -> new ResponseStatusException(NOT_FOUND, String.format("Sponsor with id = %d not found", id))); - if (sponsor.getId() != userInfo.getSponsor().getId()) { + if (!sponsor.getId().equals(userInfo.getSponsor().getId())) { throw new ResponseStatusException(FORBIDDEN, "Only the account owner can view the number of kudos"); } return new KudosAmount(sponsor.getAmountKudos()); @@ -89,7 +87,11 @@ public KudosAmountWithSponsor getProofKudos(long id, Authentication authenticati .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "Proof with id = %s not found".formatted(id))); - if (Objects.equals(talent.getId(), talentProof.getTalent().getId())) { + Long countOfAllKudos = talentProof.getKudos().stream() + .map(Kudos::getAmountKudos) + .reduce(0L, (prev, next) -> prev + next); + + if (talent.getId().equals(talentProof.getTalent().getId())) { Map kudosFromSponsor = talentProof.getKudos().stream() .collect(Collectors.toMap( Kudos::getAmountKudos, @@ -97,17 +99,14 @@ public KudosAmountWithSponsor getProofKudos(long id, Authentication authenticati (prev, next) -> next, HashMap::new )); - Long counter = talentProof.getKudos().stream().map(Kudos::getAmountKudos) - .mapToLong(Long::intValue).sum(); + return KudosAmountWithSponsor.builder() - .allKudosOnProof(counter) + .allKudosOnProof(countOfAllKudos) .kudosFromSponsor(kudosFromSponsor) .build(); } else { - Long counter = talentProof.getKudos().stream().map(Kudos::getAmountKudos) - .mapToLong(Long::intValue).sum(); return KudosAmountWithSponsor.builder() - .allKudosOnProof(counter) + .allKudosOnProof(countOfAllKudos) .kudosFromSponsor(null).build(); } } From d4da2b9596481c577dd70ad12efa09fdb7e6a8af Mon Sep 17 00:00:00 2001 From: Maslyna Date: Wed, 26 Apr 2023 14:15:59 +0200 Subject: [PATCH 08/59] Removed exception handler for Exception.class --- .../handlers/TalentExceptionHandler.java | 59 ++++++++++--------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java b/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java index cf460c5..b1a6e08 100644 --- a/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java +++ b/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java @@ -5,14 +5,19 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; 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.context.request.WebRequest; import org.springframework.web.server.ResponseStatusException; import java.sql.SQLException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; @ControllerAdvice public class TalentExceptionHandler { @@ -64,41 +69,39 @@ public static boolean ignoreSQLException(String sqlState) { return false; } - @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()); - } +// @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) { +// 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); -// }); +// 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()); - } +// @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 From 1bea5c8db18cada61b2cdd21c3cec6f3f83540a2 Mon Sep 17 00:00:00 2001 From: Maslyna Date: Wed, 26 Apr 2023 15:25:29 +0200 Subject: [PATCH 09/59] Code refactor: - Created and implemented new refactor idea use @Annotations to documenting REST API with Open API --- Created: --- DeleteProofApiDoc DeleteSponsorApiDoc DeleteTalentApiDoc GetAllProofsApiDoc GetAllSponsorsApiDoc GetAllTalentsApiDoc GetAmountOfKudosApiDoc GetKudosForSponsorApiDoc GetSponsorApiDoc GetTalentApiDoc GetTalentInformationWithProofsApiDoc GetTalentProofByProofIdApiDoc PatchEditProofApiDoc PatchEditSponsorApiDoc PatchEditTalentApiDoc PostAddKudosToProofApiDoc PostSponsorRegistrationApiDoc PostTalentRegistrationApiDoc PostUserLoginApiDoc --- .../kudos/controller/KudosController.java | 77 +--------- .../sponsor/controller/SponsorController.java | 98 +----------- .../talent/controller/TalentController.java | 89 +---------- .../controller/TalentProofController.java | 140 +----------------- .../talent/model/dto/FullTalentDTO.java | 2 +- .../talent/model/request/EditTalent.java | 3 +- .../controller/AuthenticationController.java | 58 +------- .../{ => util}/annotations/UrlList.java | 4 +- .../kudos/GetAmountOfKudosApiDoc.java | 42 ++++++ .../kudos/GetKudosForSponsorApiDoc.java | 42 ++++++ .../kudos/PostAddKudosToProofApiDoc.java | 37 +++++ .../controller/proof/DeleteProofApiDoc.java | 43 ++++++ .../controller/proof/GetAllProofsApiDoc.java | 35 +++++ .../GetTalentInformationWithProofsApiDoc.java | 38 +++++ .../proof/GetTalentProofByProofIdApiDoc.java | 37 +++++ .../proof/PatchEditProofApiDoc.java | 42 ++++++ .../controller/proof/PostAddProofApiDoc.java | 48 ++++++ .../sponsor/DeleteSponsorApiDoc.java | 42 ++++++ .../sponsor/GetAllSponsorsApiDoc.java | 31 ++++ .../controller/sponsor/GetSponsorApiDoc.java | 38 +++++ .../sponsor/PatchEditSponsorApiDoc.java | 47 ++++++ .../controller/talent/DeleteTalentApiDoc.java | 38 +++++ .../talent/GetAllTalentsApiDoc.java | 35 +++++ .../controller/talent/GetTalentApiDoc.java | 34 +++++ .../talent/PatchEditTalentApiDoc.java | 42 ++++++ .../user/PostSponsorRegistrationApiDoc.java | 33 +++++ .../user/PostTalentRegistrationApiDoc.java | 33 +++++ .../controller/user/PostUserLoginApiDoc.java | 37 +++++ .../annotations/impl/UrlListValidator.java | 4 +- 29 files changed, 815 insertions(+), 434 deletions(-) rename src/main/java/com/provedcode/{ => util}/annotations/UrlList.java (84%) create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/kudos/GetAmountOfKudosApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/kudos/GetKudosForSponsorApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/kudos/PostAddKudosToProofApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/proof/DeleteProofApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetAllProofsApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetTalentInformationWithProofsApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetTalentProofByProofIdApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/proof/PatchEditProofApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/proof/PostAddProofApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/DeleteSponsorApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/GetAllSponsorsApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/GetSponsorApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/PatchEditSponsorApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/talent/DeleteTalentApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/talent/GetAllTalentsApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/talent/GetTalentApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/talent/PatchEditTalentApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/user/PostSponsorRegistrationApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/user/PostTalentRegistrationApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/user/PostUserLoginApiDoc.java rename src/main/java/com/provedcode/{ => util}/annotations/impl/UrlListValidator.java (88%) diff --git a/src/main/java/com/provedcode/kudos/controller/KudosController.java b/src/main/java/com/provedcode/kudos/controller/KudosController.java index 20f8bce..6a3b6b8 100644 --- a/src/main/java/com/provedcode/kudos/controller/KudosController.java +++ b/src/main/java/com/provedcode/kudos/controller/KudosController.java @@ -3,13 +3,10 @@ import com.provedcode.kudos.model.response.KudosAmountWithSponsor; import com.provedcode.kudos.service.KudosService; 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 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 lombok.AllArgsConstructor; -import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; @@ -20,55 +17,14 @@ public class KudosController { KudosService kudosService; - @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) - }) + @GetKudosForSponsorApiDoc @PreAuthorize("hasRole('SPONSOR')") @GetMapping("/sponsors/{sponsor-id}/kudos") KudosAmount getKudosForSponsor(@PathVariable("sponsor-id") long id, Authentication authentication) { return kudosService.getKudosForSponsor(id, authentication); } - @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) - }) + @PostAddKudosToProofApiDoc @PreAuthorize("hasRole('SPONSOR')") @PostMapping("/proofs/{proof-id}/kudos/{amount}") void addKudosToProof(@PathVariable("proof-id") long id, @@ -77,28 +33,7 @@ void addKudosToProof(@PathVariable("proof-id") long id, kudosService.addKudosToProof(id, amount, authentication); } - @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) - }) + @GetAmountOfKudosApiDoc @PreAuthorize("hasRole('TALENT')") @GetMapping("/proofs/{proof-id}/kudos") KudosAmountWithSponsor getProofKudos(@PathVariable("proof-id") long id, Authentication authentication) { diff --git a/src/main/java/com/provedcode/sponsor/controller/SponsorController.java b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java index ea61f10..0dc811e 100644 --- a/src/main/java/com/provedcode/sponsor/controller/SponsorController.java +++ b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java @@ -4,15 +4,13 @@ import com.provedcode.sponsor.model.dto.SponsorDTO; import com.provedcode.sponsor.model.dto.SponsorEditDTO; import com.provedcode.sponsor.service.SponsorService; -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.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 lombok.AllArgsConstructor; 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.web.bind.annotation.*; @@ -26,17 +24,7 @@ public class SponsorController { SponsorService sponsorService; SponsorMapper sponsorMapper; - @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) - }) + @GetAllSponsorsApiDoc @GetMapping("/sponsors") @ResponseStatus(HttpStatus.OK) Page getSponsors(@RequestParam(value = "page") Optional page, @@ -44,59 +32,14 @@ Page getSponsors(@RequestParam(value = "page") Optional pag return sponsorService.getAllSponsors(page, size).map(sponsorMapper::toDto); } - @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) - }) + @GetSponsorApiDoc @PreAuthorize("hasRole('SPONSOR')") @GetMapping("/sponsors/{id}") SponsorDTO getSponsor(@PathVariable("id") long id, Authentication authentication) { return sponsorMapper.toDto(sponsorService.getSponsorById(id, authentication)); } - @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) - }) + @PatchEditSponsorApiDoc @PreAuthorize("hasRole('SPONSOR')") @PatchMapping("/sponsors/{id}") SponsorDTO editSponsor(@PathVariable("id") long id, @@ -105,32 +48,7 @@ SponsorDTO editSponsor(@PathVariable("id") long id, return sponsorMapper.toDto(sponsorService.editSponsorById(id, sponsorEditDTO, authentication)); } - @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), - }) + @DeleteSponsorApiDoc @PreAuthorize("hasRole('SPONSOR')") @DeleteMapping("/sponsors/{id}") void deleteSponsor(@PathVariable("id") long id, Authentication authentication) { diff --git a/src/main/java/com/provedcode/talent/controller/TalentController.java b/src/main/java/com/provedcode/talent/controller/TalentController.java index 5ab3d23..8691928 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentController.java @@ -6,18 +6,16 @@ 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 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.web.bind.annotation.*; @@ -33,21 +31,7 @@ public class TalentController { TalentService talentService; TalentMapper talentMapper; - @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) - }) + @GetAllTalentsApiDoc @GetMapping("/talents") @ResponseStatus(HttpStatus.OK) Page getTalents(@RequestParam(value = "page") Optional page, @@ -55,21 +39,7 @@ Page getTalents(@RequestParam(value = "page") Optional 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 +48,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,28 +57,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), - @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..7c5500f 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentProofController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentProofController.java @@ -6,16 +6,10 @@ 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 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; @@ -30,21 +24,7 @@ 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, @@ -53,24 +33,7 @@ Page getAllProofs(@RequestParam(value = "page") Optional page 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,25 +41,7 @@ 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, @@ -108,33 +53,7 @@ FullProofDTO getTalentInformationWithProofs(Authentication authentication, 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 +62,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 +73,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/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/user/controller/AuthenticationController.java b/src/main/java/com/provedcode/user/controller/AuthenticationController.java index 69559c6..b30ee13 100644 --- a/src/main/java/com/provedcode/user/controller/AuthenticationController.java +++ b/src/main/java/com/provedcode/user/controller/AuthenticationController.java @@ -4,16 +4,13 @@ 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.*; @@ -24,63 +21,20 @@ 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) - }) + @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), - }) + @PostTalentRegistrationApiDoc @PostMapping("/v2/talents/register") @ResponseStatus(HttpStatus.CREATED) UserInfoDTO register(@RequestBody @Valid TalentRegistrationDTO user) { return authenticationService.register(user); } - @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), - }) + @PostSponsorRegistrationApiDoc @PostMapping("/v3/sponsors/register") @ResponseStatus(HttpStatus.CREATED) UserInfoDTO register(@RequestBody @Valid SponsorRegistrationDTO user) { 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/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; From 631829bb2cf8593acf97cabdbe33556332be20d9 Mon Sep 17 00:00:00 2001 From: Denis Boyko Date: Wed, 26 Apr 2023 22:25:30 +0300 Subject: [PATCH 10/59] bug fix --- .../com/provedcode/talent/service/TalentProofService.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/provedcode/talent/service/TalentProofService.java b/src/main/java/com/provedcode/talent/service/TalentProofService.java index e4783b4..a411d28 100644 --- a/src/main/java/com/provedcode/talent/service/TalentProofService.java +++ b/src/main/java/com/provedcode/talent/service/TalentProofService.java @@ -29,7 +29,6 @@ import java.net.URI; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.List; import java.util.Optional; import static org.springframework.http.HttpStatus.*; @@ -193,9 +192,6 @@ public TalentProof editTalentProof(long talentId, long proofId, ProofDTO proof, if (proof.link() == null && proof.text() == null) { oldProof.setStatus(proof.status()); } else { - if (oldProofStatus != ProofStatus.DRAFT) - throw new ResponseStatusException(FORBIDDEN, "you cannot edit proofs without DRAFT status"); - oldProof.setLink(proof.link() != null ? proof.link() : oldProof.getLink()) .setText(proof.text() != null ? proof.text() : oldProof.getText()) .setStatus(proof.status()); From 80973351b59ab5278b31bd99b61fc3f2d9189280 Mon Sep 17 00:00:00 2001 From: Maslyna Date: Fri, 28 Apr 2023 17:56:11 +0200 Subject: [PATCH 11/59] aws update --- .../aws/controller/AWSS3BucketController.java | 8 +++++++ .../com/provedcode/aws/service/S3Service.java | 23 ++++++++++++------- .../talent/model/entity/Talent.java | 3 +++ .../db/changelog/changeset/V2/schema-V2.sql | 1 + 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java index 64141d0..54251d3 100644 --- a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java +++ b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java @@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import java.util.Arrays; import java.util.List; @RestController @@ -27,4 +28,11 @@ public void setNewUserImage(@RequestParam("file") MultipartFile file, List getAllFiles() { return fileService.listAllFiles(); } + + @PreAuthorize("hasRole('TALENT')") + @PostMapping("/aws/test") + 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/service/S3Service.java b/src/main/java/com/provedcode/aws/service/S3Service.java index 679c443..39603e8 100644 --- a/src/main/java/com/provedcode/aws/service/S3Service.java +++ b/src/main/java/com/provedcode/aws/service/S3Service.java @@ -18,11 +18,11 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.util.Arrays; 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 @@ -79,21 +79,28 @@ public void setNewUserImage(MultipartFile file, Authentication authentication) { 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 { + String fileType = file.getContentType().split("/")[1]; + String userLogin = authentication.getName(); + + String fullPath = "%s/%s".formatted(userLogin, "image.%s".formatted(fileType)); File f = convertMultiPartToFile(file); + if (user.getTalent().getImageName() != null) + s3.deleteObject(awsProperties.bucket(), user.getTalent().getImageName()); + s3.putObject(awsProperties.bucket(), fullPath, f); log.info("image = {}", s3.getUrl(awsProperties.bucket(), fullPath).toString()); + user.getTalent().setImage(s3.getUrl(awsProperties.bucket(), fullPath).toString()); + user.getTalent().setImageName(fullPath); + talentRepository.save(user.getTalent()); - } catch (RuntimeException | IOException e) { - throw new ResponseStatusException(NOT_IMPLEMENTED); + } catch (Exception e) { + throw new ResponseStatusException(BAD_REQUEST); } + } private File convertMultiPartToFile(MultipartFile file) 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 331ad63..9e65c3a 100644 --- a/src/main/java/com/provedcode/talent/model/entity/Talent.java +++ b/src/main/java/com/provedcode/talent/model/entity/Talent.java @@ -35,6 +35,9 @@ public class Talent { @URL @Column(name = "image", length = 300) 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) diff --git a/src/main/resources/db/changelog/changeset/V2/schema-V2.sql b/src/main/resources/db/changelog/changeset/V2/schema-V2.sql index 2519646..ebd940a 100644 --- a/src/main/resources/db/changelog/changeset/V2/schema-V2.sql +++ b/src/main/resources/db/changelog/changeset/V2/schema-V2.sql @@ -17,6 +17,7 @@ CREATE TABLE talent last_name VARCHAR(20), specialization VARCHAR(30), image VARCHAR(300), + image_name VARCHAR(100), CONSTRAINT pk_talent PRIMARY KEY (id) ); CREATE TABLE talent_attached_file From 841014846d518488ed78d814d4665d922a49c13a Mon Sep 17 00:00:00 2001 From: Maslyna Date: Sat, 29 Apr 2023 03:00:33 +0200 Subject: [PATCH 12/59] Created PhotoService --- .../aws/controller/AWSS3BucketController.java | 2 +- .../com/provedcode/aws/service/S3Service.java | 6 ++- .../com/provedcode/util/PhotoService.java | 50 +++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/provedcode/util/PhotoService.java diff --git a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java index 54251d3..ae9ac4b 100644 --- a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java +++ b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java @@ -19,7 +19,7 @@ public class AWSS3BucketController { @PreAuthorize("hasRole('TALENT')") @PostMapping("/image/upload") public void setNewUserImage(@RequestParam("file") MultipartFile file, - Authentication authentication) { + Authentication authentication) { fileService.setNewUserImage(file, authentication); } diff --git a/src/main/java/com/provedcode/aws/service/S3Service.java b/src/main/java/com/provedcode/aws/service/S3Service.java index 39603e8..1b1f80c 100644 --- a/src/main/java/com/provedcode/aws/service/S3Service.java +++ b/src/main/java/com/provedcode/aws/service/S3Service.java @@ -8,6 +8,7 @@ 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; @@ -32,6 +33,7 @@ public class S3Service implements FileService { AmazonS3 s3; UserInfoRepository userInfoRepository; TalentRepository talentRepository; + PhotoService photoService; @Override public String saveFile(MultipartFile file) { @@ -73,7 +75,7 @@ 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())); } - if (!List.of(IMAGE_JPEG.getMimeType(), IMAGE_PNG.getMimeType(), IMAGE_GIF.getMimeType()).contains(file.getContentType())) { + if (photoService.isFileImage(file)) { throw new ResponseStatusException(NOT_IMPLEMENTED, "not supported type: %s".formatted(file.getContentType())); } UserInfo user = userInfoRepository.findByLogin(authentication.getName()) @@ -84,7 +86,7 @@ public void setNewUserImage(MultipartFile file, Authentication authentication) { String userLogin = authentication.getName(); String fullPath = "%s/%s".formatted(userLogin, "image.%s".formatted(fileType)); - File f = convertMultiPartToFile(file); + File f = photoService.degradePhoto(convertMultiPartToFile(file)); if (user.getTalent().getImageName() != null) s3.deleteObject(awsProperties.bucket(), user.getTalent().getImageName()); 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..9ea1a09 --- /dev/null +++ b/src/main/java/com/provedcode/util/PhotoService.java @@ -0,0 +1,50 @@ +package com.provedcode.util; + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.awt.image.BufferedImage; +import java.awt.Image; +import java.util.List; +import javax.imageio.ImageIO; + +import static org.apache.http.entity.ContentType.*; + + +@Service +@AllArgsConstructor +public class PhotoService { + + public File degradePhoto(File photoFile) throws IOException { + // загружаем изображение из файла + BufferedImage originalImage = ImageIO.read(photoFile); + + // устанавливаем новый размер для изображения + int newWidth = 300; + int newHeight = 300; + + // создаем новое изображение с новым размером + 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()); + } + +} From 1e9560edaaa8e1f5246ae7d267565d16f0200744 Mon Sep 17 00:00:00 2001 From: Maslyna Date: Sat, 29 Apr 2023 03:10:55 +0200 Subject: [PATCH 13/59] minore update --- src/main/java/com/provedcode/aws/service/S3Service.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/provedcode/aws/service/S3Service.java b/src/main/java/com/provedcode/aws/service/S3Service.java index 1b1f80c..b7d48b1 100644 --- a/src/main/java/com/provedcode/aws/service/S3Service.java +++ b/src/main/java/com/provedcode/aws/service/S3Service.java @@ -100,7 +100,7 @@ public void setNewUserImage(MultipartFile file, Authentication authentication) { talentRepository.save(user.getTalent()); } catch (Exception e) { - throw new ResponseStatusException(BAD_REQUEST); + throw new ResponseStatusException(NOT_IMPLEMENTED, "problems with connection to aws s3"); } } From 44b3666a23c6ffe82c63ded2b6f520bfc683775c Mon Sep 17 00:00:00 2001 From: Ren Date: Sat, 29 Apr 2023 21:02:49 +0300 Subject: [PATCH 14/59] refactored and optimized code --- .../aws/controller/AWSS3BucketController.java | 3 +- .../provedcode/aws/service/FileService.java | 3 + .../com/provedcode/aws/service/S3Service.java | 16 +- .../handlers/TalentExceptionHandler.java | 55 +++--- .../kudos/controller/KudosController.java | 34 ++-- .../provedcode/kudos/model/entity/Kudos.java | 4 +- .../kudos/model/request/SetAmountKudos.java | 9 + .../kudos/repository/KudosRepository.java | 6 +- .../kudos/service/KudosService.java | 113 +++++++----- .../sponsor/controller/SponsorController.java | 17 +- .../EditSponsor.java} | 4 +- .../sponsor/service/SponsorService.java | 90 +++++----- .../utill/ValidateSponsorForCompliance.java | 24 +++ .../talent/controller/TalentController.java | 12 +- .../controller/TalentProofController.java | 28 ++- .../talent/service/TalentProofService.java | 83 +++------ .../talent/service/TalentService.java | 147 +++++++++++++++- .../service/impl/TalentServiceImpl.java | 163 ------------------ .../user/util/UserInfoValidator.java | 24 +++ .../com/provedcode/util/PhotoService.java | 11 +- .../db/changelog/changeset/V2/data-V2.sql | 10 +- .../db/changelog/changeset/V2/schema-V2.sql | 2 +- 22 files changed, 443 insertions(+), 415 deletions(-) create mode 100644 src/main/java/com/provedcode/kudos/model/request/SetAmountKudos.java rename src/main/java/com/provedcode/sponsor/model/{dto/SponsorEditDTO.java => request/EditSponsor.java} (81%) create mode 100644 src/main/java/com/provedcode/sponsor/utill/ValidateSponsorForCompliance.java delete mode 100644 src/main/java/com/provedcode/talent/service/impl/TalentServiceImpl.java create mode 100644 src/main/java/com/provedcode/user/util/UserInfoValidator.java diff --git a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java index ae9ac4b..0f09291 100644 --- a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java +++ b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java @@ -33,6 +33,7 @@ List getAllFiles() { @PostMapping("/aws/test") String testTypeOfFile(@RequestParam("file") MultipartFile file, Authentication authentication) { - return Arrays.stream(file.getContentType().split("/")).toList().get(1) + " " + file.getOriginalFilename() + " " + file.getName() + " " + file.getResource(); + return Arrays.stream(file.getContentType().split("/")).toList().get(1) + " " + file.getOriginalFilename() + + " " + file.getName() + " " + file.getResource(); } } diff --git a/src/main/java/com/provedcode/aws/service/FileService.java b/src/main/java/com/provedcode/aws/service/FileService.java index 78d722b..369898a 100644 --- a/src/main/java/com/provedcode/aws/service/FileService.java +++ b/src/main/java/com/provedcode/aws/service/FileService.java @@ -8,8 +8,11 @@ public interface FileService { String saveFile(MultipartFile file); + byte[] downloadFile(String filename); + String deleteFile(String filename); + List listAllFiles(); void setNewUserImage(MultipartFile file, Authentication authentication); diff --git a/src/main/java/com/provedcode/aws/service/S3Service.java b/src/main/java/com/provedcode/aws/service/S3Service.java index b7d48b1..3caa3ec 100644 --- a/src/main/java/com/provedcode/aws/service/S3Service.java +++ b/src/main/java/com/provedcode/aws/service/S3Service.java @@ -19,11 +19,10 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.util.Arrays; import java.util.List; -import static org.apache.http.entity.ContentType.*; -import static org.springframework.http.HttpStatus.*; +import static org.springframework.http.HttpStatus.NOT_FOUND; +import static org.springframework.http.HttpStatus.NOT_IMPLEMENTED; @Service @AllArgsConstructor @@ -73,13 +72,17 @@ public List listAllFiles() { @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(NOT_IMPLEMENTED, + "file must be not empty, actual file-size: %s".formatted(file.getSize())); } if (photoService.isFileImage(file)) { - throw new ResponseStatusException(NOT_IMPLEMENTED, "not supported type: %s".formatted(file.getContentType())); + throw new ResponseStatusException(NOT_IMPLEMENTED, + "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()))); + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "user with login = {%s} not found".formatted( + authentication.getName()))); try { String fileType = file.getContentType().split("/")[1]; @@ -113,5 +116,4 @@ private File convertMultiPartToFile(MultipartFile file) fos.close(); return convFile; } - } \ No newline at end of file diff --git a/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java b/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java index b1a6e08..7da4cc8 100644 --- a/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java +++ b/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java @@ -1,29 +1,34 @@ package com.provedcode.handlers; -import jakarta.validation.ConstraintViolation; import jakarta.validation.ConstraintViolationException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.validation.FieldError; -import org.springframework.web.bind.MethodArgumentNotValidException; 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.context.request.WebRequest; import org.springframework.web.server.ResponseStatusException; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; @ControllerAdvice public class TalentExceptionHandler { - @ExceptionHandler(ResponseStatusException.class) - private ResponseEntity responseStatusExceptionHandler(ResponseStatusException exception) { - return ResponseEntity.status(exception.getStatusCode()).body(exception.getBody()); + 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}) @@ -34,10 +39,10 @@ public void printSQLException(SQLException ex) { e.printStackTrace(System.err); System.err.println("SQLState: " + - ((SQLException) e).getSQLState()); + ((SQLException) e).getSQLState()); System.err.println("Error Code: " + - ((SQLException) e).getErrorCode()); + ((SQLException) e).getErrorCode()); System.err.println("Message: " + e.getMessage()); @@ -51,22 +56,16 @@ public void printSQLException(SQLException ex) { } } - 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; + @ExceptionHandler(ResponseStatusException.class) + private ResponseEntity responseStatusExceptionHandler(ResponseStatusException exception) { + return ResponseEntity.status(exception.getStatusCode()).body(exception.getBody()); + } - return false; + @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 }) diff --git a/src/main/java/com/provedcode/kudos/controller/KudosController.java b/src/main/java/com/provedcode/kudos/controller/KudosController.java index 6a3b6b8..7f18175 100644 --- a/src/main/java/com/provedcode/kudos/controller/KudosController.java +++ b/src/main/java/com/provedcode/kudos/controller/KudosController.java @@ -1,18 +1,24 @@ package com.provedcode.kudos.controller; +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.kudos.model.response.KudosAmount; 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 +@Validated @RequestMapping("/api/v3/") public class KudosController { KudosService kudosService; @@ -20,23 +26,23 @@ public class KudosController { @GetKudosForSponsorApiDoc @PreAuthorize("hasRole('SPONSOR')") @GetMapping("/sponsors/{sponsor-id}/kudos") - KudosAmount getKudosForSponsor(@PathVariable("sponsor-id") long id, Authentication authentication) { - return kudosService.getKudosForSponsor(id, authentication); - } - - @PostAddKudosToProofApiDoc - @PreAuthorize("hasRole('SPONSOR')") - @PostMapping("/proofs/{proof-id}/kudos/{amount}") - void addKudosToProof(@PathVariable("proof-id") long id, - @PathVariable("amount") Long amount, - Authentication authentication) { - kudosService.addKudosToProof(id, amount, authentication); + KudosAmount getKudosForSponsor(@PathVariable("sponsor-id") long sponsorId, Authentication authentication) { + return kudosService.getKudosForSponsor(sponsorId, authentication); } @GetAmountOfKudosApiDoc @PreAuthorize("hasRole('TALENT')") @GetMapping("/proofs/{proof-id}/kudos") - KudosAmountWithSponsor getProofKudos(@PathVariable("proof-id") long id, Authentication authentication) { - return kudosService.getProofKudos(id, authentication); + KudosAmountWithSponsor getProofKudos(@PathVariable("proof-id") long proofId, Authentication authentication) { + return kudosService.getProofKudos(proofId, 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 8cacb21..259c387 100644 --- a/src/main/java/com/provedcode/kudos/model/entity/Kudos.java +++ b/src/main/java/com/provedcode/kudos/model/entity/Kudos.java @@ -17,8 +17,8 @@ public class Kudos { @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; - @Column(name = "amount_kudos") - private Long amountKudos; + @Column(name = "amount") + private Long amount; @ManyToOne @JoinColumn(name = "sponsor_id") private Sponsor sponsor; 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/repository/KudosRepository.java b/src/main/java/com/provedcode/kudos/repository/KudosRepository.java index 529129e..3b0f629 100644 --- a/src/main/java/com/provedcode/kudos/repository/KudosRepository.java +++ b/src/main/java/com/provedcode/kudos/repository/KudosRepository.java @@ -1,10 +1,10 @@ package com.provedcode.kudos.repository; import com.provedcode.kudos.model.entity.Kudos; -import com.provedcode.talent.model.entity.Talent; -import com.provedcode.talent.model.entity.TalentProof; import org.springframework.data.jpa.repository.JpaRepository; public interface KudosRepository extends JpaRepository { - long countByProof_Id(Long id); + long countByProofId(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 2edcdd3..13c1e53 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -1,6 +1,7 @@ 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; @@ -8,6 +9,7 @@ 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; import com.provedcode.talent.repo.TalentProofRepository; @@ -22,6 +24,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import static org.springframework.http.HttpStatus.*; @@ -37,77 +40,93 @@ public class KudosService { TalentRepository talentRepository; SponsorMapper sponsorMapper; - - public void addKudosToProof(long id, Long amount, Authentication authentication) { - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Sponsor with id = %s not found".formatted(id))); + 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, - String.format("sponsor with id = %d not found", id))); - TalentProof talentProof = talentProofRepository.findById(id) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "Proof with id = %s not found".formatted(id))); - if (sponsor.getAmountKudos() < amount) { + "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"); } - if (amount <= 0) { - throw new ResponseStatusException(BAD_REQUEST, "amount of kudos must be greater than 0"); - } - sponsor.setAmountKudos(sponsor.getAmountKudos() - amount); + sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); kudosRepository.save(Kudos.builder() - .amountKudos(amount) - .proof(talentProof) - .sponsor(sponsor) - .build()); + .amount(obtainedAmount) + .proof(talentProof) + .sponsor(sponsor) + .build()); } @Transactional(readOnly = true) - public KudosAmount getKudosForSponsor(long id, Authentication authentication) { - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Sponsor with id = %s not found".formatted(id))); - Sponsor sponsor = sponsorRepository.findById(userInfo.getSponsor().getId()).orElseThrow( - () -> new ResponseStatusException(NOT_FOUND, - String.format("Sponsor with id = %d not found", id))); - if (!sponsor.getId().equals(userInfo.getSponsor().getId())) { + 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"); } + Sponsor sponsor = sponsorRepository.findById(sponsorId).orElseThrow( + () -> new ResponseStatusException(NOT_FOUND, + String.format("Sponsor with id = %d not found", sponsorId))); return new KudosAmount(sponsor.getAmountKudos()); } @Transactional(readOnly = true) - public KudosAmountWithSponsor getProofKudos(long id, Authentication authentication) { - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Sponsor with id = %s not found".formatted(id))); + 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 id = %s not found".formatted(id))); - TalentProof talentProof = talentProofRepository.findById(id) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Proof with id = %s not found".formatted(id))); + .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::getAmountKudos) - .reduce(0L, (prev, next) -> prev + next); + .map(Kudos::getAmount) + .reduce(0L, (prev, next) -> prev + next); if (talent.getId().equals(talentProof.getTalent().getId())) { Map kudosFromSponsor = talentProof.getKudos().stream() - .collect(Collectors.toMap( - Kudos::getAmountKudos, - proof -> proof.getSponsor() != null ? sponsorMapper.toDto(proof.getSponsor()) : SponsorDTO.builder().build(), - (prev, next) -> next, - HashMap::new - )); + .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(); + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(kudosFromSponsor) + .build(); } else { return KudosAmountWithSponsor.builder() - .allKudosOnProof(countOfAllKudos) - .kudosFromSponsor(null).build(); + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(null).build(); } } } \ 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 index 0dc811e..39c5bad 100644 --- a/src/main/java/com/provedcode/sponsor/controller/SponsorController.java +++ b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java @@ -2,23 +2,27 @@ import com.provedcode.sponsor.mapper.SponsorMapper; import com.provedcode.sponsor.model.dto.SponsorDTO; -import com.provedcode.sponsor.model.dto.SponsorEditDTO; +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.http.HttpStatus; 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; @@ -26,9 +30,8 @@ public class SponsorController { @GetAllSponsorsApiDoc @GetMapping("/sponsors") - @ResponseStatus(HttpStatus.OK) - Page getSponsors(@RequestParam(value = "page") Optional page, - @RequestParam(value = "size") Optional size) { + 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); } @@ -43,9 +46,9 @@ SponsorDTO getSponsor(@PathVariable("id") long id, Authentication authentication @PreAuthorize("hasRole('SPONSOR')") @PatchMapping("/sponsors/{id}") SponsorDTO editSponsor(@PathVariable("id") long id, - @RequestBody SponsorEditDTO sponsorEditDTO, + @RequestBody EditSponsor editSponsor, Authentication authentication) { - return sponsorMapper.toDto(sponsorService.editSponsorById(id, sponsorEditDTO, authentication)); + return sponsorMapper.toDto(sponsorService.editSponsorById(id, editSponsor, authentication)); } @DeleteSponsorApiDoc diff --git a/src/main/java/com/provedcode/sponsor/model/dto/SponsorEditDTO.java b/src/main/java/com/provedcode/sponsor/model/request/EditSponsor.java similarity index 81% rename from src/main/java/com/provedcode/sponsor/model/dto/SponsorEditDTO.java rename to src/main/java/com/provedcode/sponsor/model/request/EditSponsor.java index 82867a5..55bf951 100644 --- a/src/main/java/com/provedcode/sponsor/model/dto/SponsorEditDTO.java +++ b/src/main/java/com/provedcode/sponsor/model/request/EditSponsor.java @@ -1,10 +1,10 @@ -package com.provedcode.sponsor.model.dto; +package com.provedcode.sponsor.model.request; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Builder; @Builder -public record SponsorEditDTO( +public record EditSponsor( Long id, @JsonProperty("first_name") String firstName, diff --git a/src/main/java/com/provedcode/sponsor/service/SponsorService.java b/src/main/java/com/provedcode/sponsor/service/SponsorService.java index 933fb69..8beaba7 100644 --- a/src/main/java/com/provedcode/sponsor/service/SponsorService.java +++ b/src/main/java/com/provedcode/sponsor/service/SponsorService.java @@ -2,9 +2,10 @@ import com.provedcode.config.PageProperties; import com.provedcode.kudos.model.entity.Kudos; -import com.provedcode.sponsor.model.dto.SponsorEditDTO; 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; @@ -18,7 +19,8 @@ import java.util.List; import java.util.Optional; -import static org.springframework.http.HttpStatus.*; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.FORBIDDEN; @Service @AllArgsConstructor @@ -27,70 +29,64 @@ public class SponsorService { PageProperties pageProperties; SponsorRepository sponsorRepository; UserInfoRepository userInfoRepository; + ValidateSponsorForCompliance validateSponsorForCompliance; @Transactional(readOnly = true) - public Page getAllSponsors(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 sponsorRepository.findAll(PageRequest.of(page.orElse(pageProperties.defaultPageNum()), - size.orElse(pageProperties.defaultPageSize()))); + public Page getAllSponsors(Integer page, Integer size) { + return sponsorRepository.findAll(PageRequest.of(page, size)); } @Transactional(readOnly = true) public Sponsor getSponsorById(long id, Authentication authentication) { - Sponsor sponsor = sponsorRepository.findById(id).orElseThrow( - () -> new ResponseStatusException(NOT_FOUND, String.format("sponsor with id = %d not found", id))); - UserInfo user = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_IMPLEMENTED, "login is not valid")); - - if (!sponsor.getId().equals(user.getSponsor().getId())) - throw new ResponseStatusException(FORBIDDEN, "The user cannot view someone else's profile"); - return sponsor; + Optional user = userInfoRepository.findByLogin(authentication.getName()); + Optional sponsor = sponsorRepository.findById(id); + validateSponsorForCompliance.userVerification(sponsor, user, id); + return sponsor.get(); } - public Sponsor editSponsorById(long id, SponsorEditDTO sponsorEditDTO, Authentication authentication) { - Sponsor sponsor = sponsorRepository.findById(id) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "sponsor with id = %s not found".formatted(id))); - UserInfo user = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_IMPLEMENTED, "login is not valid")); - if (!sponsor.getId().equals(user.getSponsor().getId())) { - throw new ResponseStatusException(FORBIDDEN, "The user cannot edit someone else's profile"); - } + 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); - if (sponsorEditDTO.firstName() != null) { - sponsor.setFirstName(sponsorEditDTO.firstName()); + Sponsor editableSponsor = sponsor.get(); + if (editSponsor.firstName() != null) { + editableSponsor.setFirstName(editSponsor.firstName()); } - if (sponsorEditDTO.lastName() != null) { - sponsor.setLastName(sponsorEditDTO.lastName()); + if (editSponsor.lastName() != null) { + editableSponsor.setLastName(editSponsor.lastName()); } - if (sponsorEditDTO.image() != null) { - sponsor.setImage(sponsorEditDTO.image()); + if (editSponsor.image() != null) { + editableSponsor.setImage(editSponsor.image()); } - if (sponsorEditDTO.countOfKudos() != null) { - if (sponsorEditDTO.countOfKudos() > 0) { - sponsor.setAmountKudos(sponsor.getAmountKudos() + sponsorEditDTO.countOfKudos()); + 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(sponsor); + return sponsorRepository.save(editableSponsor); } public void deleteSponsor(long id, Authentication authentication) { - Sponsor sponsor = sponsorRepository.findById(id) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "sponsor with id = %s not found".formatted(id))); - UserInfo user = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_IMPLEMENTED, "login is not valid")); - if (!sponsor.getId().equals(user.getSponsor().getId())) { - throw new ResponseStatusException(FORBIDDEN, "The user cannot edit someone else's profile"); - } + 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()); + } - List kudosList = sponsor.getKudoses().stream().map(i -> {i.setSponsor(null); return i;}).toList(); - sponsor.setKudoses(kudosList); - userInfoRepository.delete(user); + 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 8691928..1b9e20d 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentController.java @@ -1,5 +1,6 @@ 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; @@ -12,12 +13,16 @@ 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.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; @@ -27,15 +32,16 @@ @AllArgsConstructor @RequestMapping("/api/v2") @Tag(name = "talent", description = "Talent API") +@Validated public class TalentController { TalentService talentService; TalentMapper talentMapper; @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); } diff --git a/src/main/java/com/provedcode/talent/controller/TalentProofController.java b/src/main/java/com/provedcode/talent/controller/TalentProofController.java index 7c5500f..2b5e769 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentProofController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentProofController.java @@ -8,27 +8,35 @@ import com.provedcode.talent.service.TalentProofService; 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.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; @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); } @@ -46,9 +54,13 @@ ProofDTO getTalentProof(@PathVariable(value = "proof-id") long proofId, @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); } diff --git a/src/main/java/com/provedcode/talent/service/TalentProofService.java b/src/main/java/com/provedcode/talent/service/TalentProofService.java index a411d28..bbd8434 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,48 +73,25 @@ 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.findById(talentId) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, - "Talent with id = %s not found".formatted( + "User with id = %d not found".formatted( talentId))); 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.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.getLogin().equals(authentication.getName())) { + proofs = talentProofRepository.findByTalentIdAndStatus(talentId, ProofStatus.PUBLISHED, pageRequest); + } else { + proofs = talentProofRepository.findByTalentId(talentId, pageRequest); } - return FullProofDTO.builder() .id(talent.getId()) .image(talent.getImage()) @@ -161,7 +121,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/util/UserInfoValidator.java b/src/main/java/com/provedcode/user/util/UserInfoValidator.java new file mode 100644 index 0000000..04dd6c4 --- /dev/null +++ b/src/main/java/com/provedcode/user/util/UserInfoValidator.java @@ -0,0 +1,24 @@ +package com.provedcode.user.util; + +import com.provedcode.user.model.entity.UserInfo; +import com.provedcode.user.repo.UserInfoRepository; +import lombok.AllArgsConstructor; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ResponseStatusException; + +import static org.springframework.http.HttpStatus.NOT_FOUND; + +@Component +@AllArgsConstructor +public class UserInfoValidator { + UserInfoRepository userInfoRepository; + + public UserInfo findByLoginOrElseThrow(Authentication authentication) { + String login = authentication.getName(); + return userInfoRepository.findByLogin(login) + .orElseThrow(() -> 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 index 9ea1a09..a7b74d3 100644 --- a/src/main/java/com/provedcode/util/PhotoService.java +++ b/src/main/java/com/provedcode/util/PhotoService.java @@ -4,12 +4,12 @@ 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.awt.image.BufferedImage; -import java.awt.Image; import java.util.List; -import javax.imageio.ImageIO; import static org.apache.http.entity.ContentType.*; @@ -17,7 +17,6 @@ @Service @AllArgsConstructor public class PhotoService { - public File degradePhoto(File photoFile) throws IOException { // загружаем изображение из файла BufferedImage originalImage = ImageIO.read(photoFile); @@ -44,7 +43,7 @@ public File degradePhoto(File photoFile) throws IOException { } public boolean isFileImage(MultipartFile file) { - return !List.of(IMAGE_JPEG.getMimeType(), IMAGE_PNG.getMimeType(), IMAGE_GIF.getMimeType()).contains(file.getContentType()); + return !List.of(IMAGE_JPEG.getMimeType(), IMAGE_PNG.getMimeType(), IMAGE_GIF.getMimeType()) + .contains(file.getContentType()); } - } diff --git a/src/main/resources/db/changelog/changeset/V2/data-V2.sql b/src/main/resources/db/changelog/changeset/V2/data-V2.sql index e0d6ee0..a5de8d5 100644 --- a/src/main/resources/db/changelog/changeset/V2/data-V2.sql +++ b/src/main/resources/db/changelog/changeset/V2/data-V2.sql @@ -544,7 +544,7 @@ 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), '$2a$10$D4KM50WemOahkFv1fkrPX.MvVESsE0TYWlkh5TypTE/q4nlv8ooyS', '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)); @@ -585,11 +585,11 @@ 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_kudos, sponsor_id, proof_id) +insert into kudos (amount, sponsor_id, proof_id) values (100, 1, 1); -insert into kudos (amount_kudos, sponsor_id, proof_id) +insert into kudos (amount, sponsor_id, proof_id) values (200, 2, 1); -insert into kudos (amount_kudos, sponsor_id, proof_id) +insert into kudos (amount, sponsor_id, proof_id) values (200, 3, 1); -insert into kudos (amount_kudos, sponsor_id, proof_id) +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/schema-V2.sql b/src/main/resources/db/changelog/changeset/V2/schema-V2.sql index ebd940a..799d7e5 100644 --- a/src/main/resources/db/changelog/changeset/V2/schema-V2.sql +++ b/src/main/resources/db/changelog/changeset/V2/schema-V2.sql @@ -86,7 +86,7 @@ CREATE TABLE kudos id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, sponsor_id BIGINT, proof_id BIGINT, - amount_kudos BIGINT, + amount BIGINT, CONSTRAINT pk_kudos PRIMARY KEY (id) ); CREATE TABLE sponsor From 8605ed42fcd94876e3b2bb80a93b4bcdd9d67389 Mon Sep 17 00:00:00 2001 From: Denis Boyko Date: Sat, 29 Apr 2023 21:57:55 +0300 Subject: [PATCH 15/59] fix .findByLogin(authentication.getName()) - getTalentProofs --- .../aws/controller/AWSS3BucketController.java | 2 +- .../com/provedcode/aws/service/S3Service.java | 10 +-- .../kudos/service/KudosService.java | 80 +++++++++---------- .../talent/service/TalentProofService.java | 56 +++++++------ 4 files changed, 73 insertions(+), 75 deletions(-) diff --git a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java index 0f09291..3b8ff0e 100644 --- a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java +++ b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java @@ -34,6 +34,6 @@ List getAllFiles() { String testTypeOfFile(@RequestParam("file") MultipartFile file, Authentication authentication) { return Arrays.stream(file.getContentType().split("/")).toList().get(1) + " " + file.getOriginalFilename() + - " " + file.getName() + " " + file.getResource(); + " " + file.getName() + " " + file.getResource(); } } diff --git a/src/main/java/com/provedcode/aws/service/S3Service.java b/src/main/java/com/provedcode/aws/service/S3Service.java index 3caa3ec..fa1ea9d 100644 --- a/src/main/java/com/provedcode/aws/service/S3Service.java +++ b/src/main/java/com/provedcode/aws/service/S3Service.java @@ -73,16 +73,16 @@ public List listAllFiles() { 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())); + "file must be not empty, actual file-size: %s".formatted(file.getSize())); } if (photoService.isFileImage(file)) { throw new ResponseStatusException(NOT_IMPLEMENTED, - "not supported type: %s".formatted(file.getContentType())); + "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()))); + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "user with login = {%s} not found".formatted( + authentication.getName()))); try { String fileType = file.getContentType().split("/")[1]; diff --git a/src/main/java/com/provedcode/kudos/service/KudosService.java b/src/main/java/com/provedcode/kudos/service/KudosService.java index 13c1e53..f506391 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -43,16 +43,16 @@ public class KudosService { 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))); + .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))); + "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))); + .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"); @@ -65,25 +65,25 @@ public void addKudosToProof(long proofId, Optional setAmountKudo } sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); kudosRepository.save(Kudos.builder() - .amount(obtainedAmount) - .proof(talentProof) - .sponsor(sponsor) - .build()); + .amount(obtainedAmount) + .proof(talentProof) + .sponsor(sponsor) + .build()); } @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))); + .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"); } Sponsor sponsor = sponsorRepository.findById(sponsorId).orElseThrow( () -> new ResponseStatusException(NOT_FOUND, - String.format("Sponsor with id = %d not found", sponsorId))); + String.format("Sponsor with id = %d not found", sponsorId))); return new KudosAmount(sponsor.getAmountKudos()); } @@ -91,42 +91,42 @@ public KudosAmount getKudosForSponsor(long sponsorId, Authentication authenticat 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))); + .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))); + .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))); + .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); + .map(Kudos::getAmount) + .reduce(0L, (prev, next) -> prev + next); 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 - )); + .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(); + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(kudosFromSponsor) + .build(); } else { return KudosAmountWithSponsor.builder() - .allKudosOnProof(countOfAllKudos) - .kudosFromSponsor(null).build(); + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(null).build(); } } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/service/TalentProofService.java b/src/main/java/com/provedcode/talent/service/TalentProofService.java index bbd8434..e429765 100644 --- a/src/main/java/com/provedcode/talent/service/TalentProofService.java +++ b/src/main/java/com/provedcode/talent/service/TalentProofService.java @@ -65,7 +65,7 @@ public TalentProof getTalentProof(long proofId, Authentication authentication) { () -> new ResponseStatusException(NOT_FOUND, "user with this token not found")); if (talentProof.getTalent().getId().equals(userInfo.getTalent().getId()) || - talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { + talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { return talentProof; } else { throw new ResponseStatusException(FORBIDDEN); @@ -76,16 +76,14 @@ public TalentProof getTalentProof(long proofId, Authentication authentication) { 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 = %d not found".formatted( - talentId))); - UserInfo userInfo = userInfoRepository.findById(talentId) - .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, - "User with id = %d not found".formatted( - talentId))); + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, + "Talent with id = %d not found".formatted( + talentId))); + UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); Page proofs; PageRequest pageRequest = PageRequest.of(page, size, Sort.Direction.valueOf(direction.toUpperCase()), - sortProperties + sortProperties ); if (!userInfo.getLogin().equals(authentication.getName())) { proofs = talentProofRepository.findByTalentIdAndStatus(talentId, ProofStatus.PUBLISHED, pageRequest); @@ -93,19 +91,19 @@ public FullProofDTO getTalentProofs(Long talentId, Integer page, Integer size, S proofs = talentProofRepository.findByTalentId(talentId, pageRequest); } return FullProofDTO.builder() - .id(talent.getId()) - .image(talent.getImage()) - .firstName(talent.getFirstName()) - .lastName(talent.getLastName()) - .specialization(talent.getSpecialization()) - .proofs(proofs.map(i -> ProofDTO.builder() - .id(i.getId()) - .created(DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss") - .format(i.getCreated())) - .link(i.getLink()) - .text(i.getText()) - .status(i.getStatus()).build())) - .build(); + .id(talent.getId()) + .image(talent.getImage()) + .firstName(talent.getFirstName()) + .lastName(talent.getLastName()) + .specialization(talent.getSpecialization()) + .proofs(proofs.map(i -> ProofDTO.builder() + .id(i.getId()) + .created(DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss") + .format(i.getCreated())) + .link(i.getLink()) + .text(i.getText()) + .status(i.getStatus()).build())) + .build(); } public ResponseEntity addProof(AddProof addProof, long talentId, Authentication authentication) { @@ -115,12 +113,12 @@ public ResponseEntity addProof(AddProof addProof, long talentId, Authenticati validateTalentForCompliance.userVerification(talent, userInfo, talentId); TalentProof talentProof = TalentProof.builder() - .talent(talent.get()) - .link(addProof.link()) - .text(addProof.text()) - .status(ProofStatus.DRAFT) - .created(LocalDateTime.now()) - .build(); + .talent(talent.get()) + .link(addProof.link()) + .text(addProof.text()) + .status(ProofStatus.DRAFT) + .created(LocalDateTime.now()) + .build(); talentProofRepository.save(talentProof); URI location = ServletUriComponentsBuilder @@ -146,7 +144,7 @@ public TalentProof editTalentProof(long talentId, long proofId, ProofDTO proof, throw new ResponseStatusException(FORBIDDEN, "you cannot change proofs status to DRAFT"); if (oldProofStatus == ProofStatus.DRAFT && proof.status() == ProofStatus.HIDDEN) throw new ResponseStatusException(FORBIDDEN, - "you cannot change proofs status from DRAFT to HIDDEN, it should be PUBLISHED"); + "you cannot change proofs status from DRAFT to HIDDEN, it should be PUBLISHED"); if (proof.link() == null && proof.text() == null) { oldProof.setStatus(proof.status()); From 0382ddc62195c282fe28e30ad4d7ac6f68a025e7 Mon Sep 17 00:00:00 2001 From: Denis Boyko Date: Sat, 29 Apr 2023 22:00:01 +0300 Subject: [PATCH 16/59] fix !userInfo.getTalent().getId().equals(talentId) --- .../java/com/provedcode/talent/service/TalentProofService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/provedcode/talent/service/TalentProofService.java b/src/main/java/com/provedcode/talent/service/TalentProofService.java index e429765..3880350 100644 --- a/src/main/java/com/provedcode/talent/service/TalentProofService.java +++ b/src/main/java/com/provedcode/talent/service/TalentProofService.java @@ -85,7 +85,7 @@ public FullProofDTO getTalentProofs(Long talentId, Integer page, Integer size, S PageRequest pageRequest = PageRequest.of(page, size, Sort.Direction.valueOf(direction.toUpperCase()), sortProperties ); - if (!userInfo.getLogin().equals(authentication.getName())) { + if (!userInfo.getTalent().getId().equals(talentId)) { proofs = talentProofRepository.findByTalentIdAndStatus(talentId, ProofStatus.PUBLISHED, pageRequest); } else { proofs = talentProofRepository.findByTalentId(talentId, pageRequest); From ae08a0cf257542c5c3070cd4238ab37749ca075a Mon Sep 17 00:00:00 2001 From: Maslyna Date: Mon, 1 May 2023 19:09:23 +0200 Subject: [PATCH 17/59] Doc update --- .../aws/controller/AWSS3BucketController.java | 6 +++ .../com/provedcode/aws/service/S3Service.java | 8 ++-- .../handlers/AwsS3ExceptionHandler.java | 17 ++++++++ .../com/provedcode/handlers/dto/ErrorDTO.java | 7 ++++ .../aws/GetAllAWSBucketFilesDevApiDoc.java | 34 +++++++++++++++ .../controller/aws/GetFileInfoDevApiDoc.java | 29 +++++++++++++ .../aws/PostSetNewUserImageApiDoc.java | 42 +++++++++++++++++++ 7 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/provedcode/handlers/AwsS3ExceptionHandler.java create mode 100644 src/main/java/com/provedcode/handlers/dto/ErrorDTO.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/aws/GetAllAWSBucketFilesDevApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/aws/GetFileInfoDevApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/aws/PostSetNewUserImageApiDoc.java diff --git a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java index ae9ac4b..3a49d63 100644 --- a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java +++ b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java @@ -1,6 +1,9 @@ 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; @@ -16,6 +19,7 @@ public class AWSS3BucketController { FileService fileService; + @PostSetNewUserImageApiDoc @PreAuthorize("hasRole('TALENT')") @PostMapping("/image/upload") public void setNewUserImage(@RequestParam("file") MultipartFile file, @@ -23,12 +27,14 @@ public void setNewUserImage(@RequestParam("file") MultipartFile file, fileService.setNewUserImage(file, authentication); } + @GetFileInfoDevApiDoc @PreAuthorize("hasRole('TALENT')") @GetMapping("/files") List getAllFiles() { return fileService.listAllFiles(); } + @GetAllAWSBucketFilesDevApiDoc @PreAuthorize("hasRole('TALENT')") @PostMapping("/aws/test") String testTypeOfFile(@RequestParam("file") MultipartFile file, diff --git a/src/main/java/com/provedcode/aws/service/S3Service.java b/src/main/java/com/provedcode/aws/service/S3Service.java index b7d48b1..439ee94 100644 --- a/src/main/java/com/provedcode/aws/service/S3Service.java +++ b/src/main/java/com/provedcode/aws/service/S3Service.java @@ -13,6 +13,7 @@ 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; @@ -28,6 +29,7 @@ @Service @AllArgsConstructor @Slf4j +@Transactional public class S3Service implements FileService { AWSProperties awsProperties; AmazonS3 s3; @@ -73,10 +75,10 @@ public List listAllFiles() { @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 (photoService.isFileImage(file)) { - throw new ResponseStatusException(NOT_IMPLEMENTED, "not supported type: %s".formatted(file.getContentType())); + 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()))); @@ -100,7 +102,7 @@ public void setNewUserImage(MultipartFile file, Authentication authentication) { talentRepository.save(user.getTalent()); } catch (Exception e) { - throw new ResponseStatusException(NOT_IMPLEMENTED, "problems with connection to aws s3"); + throw new ResponseStatusException(SERVICE_UNAVAILABLE, "problems with connection to aws s3"); } } 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/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/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 { +} From 1a1f0278211edfa74a71ff2a3643bb0ea73e9016 Mon Sep 17 00:00:00 2001 From: Maslyna Date: Tue, 2 May 2023 02:20:17 +0200 Subject: [PATCH 18/59] New test endpoint for images --- .../aws/controller/AWSS3BucketController.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java index 7d8e4bb..70a2d6f 100644 --- a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java +++ b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java @@ -1,6 +1,10 @@ package com.provedcode.aws.controller; +import com.amazonaws.HttpMethod; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; import com.provedcode.aws.service.FileService; +import com.provedcode.config.AWSProperties; 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; @@ -10,7 +14,10 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import java.net.URL; +import java.time.Instant; import java.util.Arrays; +import java.util.Date; import java.util.List; @RestController @@ -18,6 +25,8 @@ @RequestMapping("/api/v3/talents") public class AWSS3BucketController { FileService fileService; + AWSProperties awsProperties; + AmazonS3 amazonS3; @PostSetNewUserImageApiDoc @PreAuthorize("hasRole('TALENT')") @@ -36,10 +45,22 @@ List getAllFiles() { @GetAllAWSBucketFilesDevApiDoc @PreAuthorize("hasRole('TALENT')") - @PostMapping("/aws/test") + @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(); } + + @GetMapping("/aws/test") + URL getURL() { + GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(awsProperties.bucket(), "MykhailoOrdyntsev@gmail.com/image.jpeg") + .withMethod(HttpMethod.GET); + Instant expiration = Instant.now().plusMillis(1000L * 60 * 60 * 24 * 7); + + urlRequest.setExpiration(Date.from(expiration)); + URL url = amazonS3.generatePresignedUrl(urlRequest); + return url; + } + } From c8402321792fb3f9dacb0bc33d6ec60971eb25bc Mon Sep 17 00:00:00 2001 From: Maslyna Date: Wed, 3 May 2023 12:51:28 +0200 Subject: [PATCH 19/59] DB EDIT: SIZE UP --- .../resources/db/changelog/changeset/V2/schema-V2.sql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/db/changelog/changeset/V2/schema-V2.sql b/src/main/resources/db/changelog/changeset/V2/schema-V2.sql index 799d7e5..19ba151 100644 --- a/src/main/resources/db/changelog/changeset/V2/schema-V2.sql +++ b/src/main/resources/db/changelog/changeset/V2/schema-V2.sql @@ -38,15 +38,15 @@ CREATE TABLE talent_description ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, talent_id BIGINT NOT NULL, - bio VARCHAR(255), - addition_info VARCHAR(255), + 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(255), + link VARCHAR(500), CONSTRAINT pk_talent_link PRIMARY KEY (id) ); CREATE TABLE talent_proofs @@ -54,7 +54,7 @@ CREATE TABLE talent_proofs id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, talent_id BIGINT NOT NULL, link VARCHAR(100), - text VARCHAR(255), + text VARCHAR(1000), status VARCHAR(20) NOT NULL, created TIMESTAMP, CONSTRAINT pk_talent_proofs PRIMARY KEY (id) From 98aa8a280c17ad6d74c2222185a75fbea02a1dc4 Mon Sep 17 00:00:00 2001 From: Mykhailo Ordyntsev <102993813+Maslyna@users.noreply.github.com> Date: Wed, 3 May 2023 20:22:45 +0200 Subject: [PATCH 20/59] S3.2 refactor (#107) * Updated liquibase: - new changesets * BUGFIX: `GET(/api/v3/proofs/1/kudos)`` has problems after deleting a `sponsor` * Little update * Removed exception handler for Exception.class * Code refactor: - Created and implemented new refactor idea use @Annotations to documenting REST API with Open API --- Created: --- DeleteProofApiDoc DeleteSponsorApiDoc DeleteTalentApiDoc GetAllProofsApiDoc GetAllSponsorsApiDoc GetAllTalentsApiDoc GetAmountOfKudosApiDoc GetKudosForSponsorApiDoc GetSponsorApiDoc GetTalentApiDoc GetTalentInformationWithProofsApiDoc GetTalentProofByProofIdApiDoc PatchEditProofApiDoc PatchEditSponsorApiDoc PatchEditTalentApiDoc PostAddKudosToProofApiDoc PostSponsorRegistrationApiDoc PostTalentRegistrationApiDoc PostUserLoginApiDoc * bug fix * aws update * Created PhotoService * minore update * refactored and optimized code * fix .findByLogin(authentication.getName()) - getTalentProofs * fix !userInfo.getTalent().getId().equals(talentId) * Doc update * New test endpoint for images * DB EDIT: SIZE UP --------- Co-authored-by: Denis Boyko Co-authored-by: Ren --- .../aws/controller/AWSS3BucketController.java | 38 +- .../provedcode/aws/service/FileService.java | 3 + .../com/provedcode/aws/service/S3Service.java | 35 +- .../com/provedcode/config/InitConfig.java | 58 +- .../handlers/AwsS3ExceptionHandler.java | 17 + .../handlers/TalentExceptionHandler.java | 106 ++-- .../com/provedcode/handlers/dto/ErrorDTO.java | 7 + .../kudos/controller/KudosController.java | 109 +--- .../provedcode/kudos/model/entity/Kudos.java | 4 +- .../kudos/model/request/SetAmountKudos.java | 9 + .../response/KudosAmountWithSponsor.java | 2 +- .../kudos/repository/KudosRepository.java | 6 +- .../kudos/service/KudosService.java | 94 +-- .../sponsor/controller/SponsorController.java | 115 +--- .../sponsor/model/dto/SponsorDTO.java | 2 + .../EditSponsor.java} | 4 +- .../sponsor/service/SponsorService.java | 90 ++- .../utill/ValidateSponsorForCompliance.java | 24 + .../talent/controller/TalentController.java | 101 +--- .../controller/TalentProofController.java | 168 +----- .../talent/model/dto/FullTalentDTO.java | 2 +- .../talent/model/entity/Talent.java | 3 + .../talent/model/request/EditTalent.java | 3 +- .../talent/service/TalentProofService.java | 137 ++--- .../talent/service/TalentService.java | 147 ++++- .../service/impl/TalentServiceImpl.java | 163 ------ .../controller/AuthenticationController.java | 58 +- .../user/util/UserInfoValidator.java | 24 + .../com/provedcode/util/PhotoService.java | 49 ++ .../{ => util}/annotations/UrlList.java | 4 +- .../aws/GetAllAWSBucketFilesDevApiDoc.java | 34 ++ .../controller/aws/GetFileInfoDevApiDoc.java | 29 + .../aws/PostSetNewUserImageApiDoc.java | 42 ++ .../kudos/GetAmountOfKudosApiDoc.java | 42 ++ .../kudos/GetKudosForSponsorApiDoc.java | 42 ++ .../kudos/PostAddKudosToProofApiDoc.java | 37 ++ .../controller/proof/DeleteProofApiDoc.java | 43 ++ .../controller/proof/GetAllProofsApiDoc.java | 35 ++ .../GetTalentInformationWithProofsApiDoc.java | 38 ++ .../proof/GetTalentProofByProofIdApiDoc.java | 37 ++ .../proof/PatchEditProofApiDoc.java | 42 ++ .../controller/proof/PostAddProofApiDoc.java | 48 ++ .../sponsor/DeleteSponsorApiDoc.java | 42 ++ .../sponsor/GetAllSponsorsApiDoc.java | 31 + .../controller/sponsor/GetSponsorApiDoc.java | 38 ++ .../sponsor/PatchEditSponsorApiDoc.java | 47 ++ .../controller/talent/DeleteTalentApiDoc.java | 38 ++ .../talent/GetAllTalentsApiDoc.java | 35 ++ .../controller/talent/GetTalentApiDoc.java | 34 ++ .../talent/PatchEditTalentApiDoc.java | 42 ++ .../user/PostSponsorRegistrationApiDoc.java | 33 ++ .../user/PostTalentRegistrationApiDoc.java | 33 ++ .../controller/user/PostUserLoginApiDoc.java | 37 ++ .../annotations/impl/UrlListValidator.java | 4 +- src/main/resources/application-dev.properties | 2 - .../resources/application-prod.properties | 4 +- src/main/resources/application.properties | 13 +- .../db/changelog/changeset/V1/data-V1.sql | 547 ++++++++++++++++++ .../db/changelog/changeset/V1/drop-V1.sql | 14 + .../db/changelog/changeset/V1/schema-V1.sql | 132 +++++ .../{add-data.sql => V2/data-V2.sql} | 44 +- .../db/changelog/changeset/V2/drop-V2.sql | 15 + .../{create-tables.sql => V2/schema-V2.sql} | 38 +- .../db/changelog/db.changelog-master.yaml | 9 +- 64 files changed, 2303 insertions(+), 980 deletions(-) create mode 100644 src/main/java/com/provedcode/handlers/AwsS3ExceptionHandler.java create mode 100644 src/main/java/com/provedcode/handlers/dto/ErrorDTO.java create mode 100644 src/main/java/com/provedcode/kudos/model/request/SetAmountKudos.java rename src/main/java/com/provedcode/sponsor/model/{dto/SponsorEditDTO.java => request/EditSponsor.java} (81%) create mode 100644 src/main/java/com/provedcode/sponsor/utill/ValidateSponsorForCompliance.java delete mode 100644 src/main/java/com/provedcode/talent/service/impl/TalentServiceImpl.java create mode 100644 src/main/java/com/provedcode/user/util/UserInfoValidator.java create mode 100644 src/main/java/com/provedcode/util/PhotoService.java rename src/main/java/com/provedcode/{ => util}/annotations/UrlList.java (84%) create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/aws/GetAllAWSBucketFilesDevApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/aws/GetFileInfoDevApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/aws/PostSetNewUserImageApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/kudos/GetAmountOfKudosApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/kudos/GetKudosForSponsorApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/kudos/PostAddKudosToProofApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/proof/DeleteProofApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetAllProofsApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetTalentInformationWithProofsApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/proof/GetTalentProofByProofIdApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/proof/PatchEditProofApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/proof/PostAddProofApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/DeleteSponsorApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/GetAllSponsorsApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/GetSponsorApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/sponsor/PatchEditSponsorApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/talent/DeleteTalentApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/talent/GetAllTalentsApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/talent/GetTalentApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/talent/PatchEditTalentApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/user/PostSponsorRegistrationApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/user/PostTalentRegistrationApiDoc.java create mode 100644 src/main/java/com/provedcode/util/annotations/doc/controller/user/PostUserLoginApiDoc.java rename src/main/java/com/provedcode/{ => util}/annotations/impl/UrlListValidator.java (88%) create mode 100644 src/main/resources/db/changelog/changeset/V1/data-V1.sql create mode 100644 src/main/resources/db/changelog/changeset/V1/drop-V1.sql create mode 100644 src/main/resources/db/changelog/changeset/V1/schema-V1.sql rename src/main/resources/db/changelog/changeset/{add-data.sql => V2/data-V2.sql} (96%) create mode 100644 src/main/resources/db/changelog/changeset/V2/drop-V2.sql rename src/main/resources/db/changelog/changeset/{create-tables.sql => V2/schema-V2.sql} (85%) diff --git a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java index 64141d0..70a2d6f 100644 --- a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java +++ b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java @@ -1,12 +1,23 @@ package com.provedcode.aws.controller; +import com.amazonaws.HttpMethod; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; import com.provedcode.aws.service.FileService; +import com.provedcode.config.AWSProperties; +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.net.URL; +import java.time.Instant; +import java.util.Arrays; +import java.util.Date; import java.util.List; @RestController @@ -14,17 +25,42 @@ @RequestMapping("/api/v3/talents") public class AWSS3BucketController { FileService fileService; + AWSProperties awsProperties; + AmazonS3 amazonS3; + @PostSetNewUserImageApiDoc @PreAuthorize("hasRole('TALENT')") @PostMapping("/image/upload") public void setNewUserImage(@RequestParam("file") MultipartFile file, - Authentication authentication) { + Authentication authentication) { fileService.setNewUserImage(file, authentication); } + @GetFileInfoDevApiDoc @PreAuthorize("hasRole('TALENT')") @GetMapping("/files") List getAllFiles() { return fileService.listAllFiles(); } + + @GetAllAWSBucketFilesDevApiDoc + @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(); + } + + @GetMapping("/aws/test") + URL getURL() { + GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(awsProperties.bucket(), "MykhailoOrdyntsev@gmail.com/image.jpeg") + .withMethod(HttpMethod.GET); + Instant expiration = Instant.now().plusMillis(1000L * 60 * 60 * 24 * 7); + + urlRequest.setExpiration(Date.from(expiration)); + URL url = amazonS3.generatePresignedUrl(urlRequest); + return url; + } + } diff --git a/src/main/java/com/provedcode/aws/service/FileService.java b/src/main/java/com/provedcode/aws/service/FileService.java index 78d722b..369898a 100644 --- a/src/main/java/com/provedcode/aws/service/FileService.java +++ b/src/main/java/com/provedcode/aws/service/FileService.java @@ -8,8 +8,11 @@ public interface FileService { String saveFile(MultipartFile file); + byte[] downloadFile(String filename); + String deleteFile(String filename); + List listAllFiles(); void setNewUserImage(MultipartFile file, Authentication authentication); diff --git a/src/main/java/com/provedcode/aws/service/S3Service.java b/src/main/java/com/provedcode/aws/service/S3Service.java index 679c443..439ee94 100644 --- a/src/main/java/com/provedcode/aws/service/S3Service.java +++ b/src/main/java/com/provedcode/aws/service/S3Service.java @@ -8,30 +8,34 @@ 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.util.Arrays; 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; UserInfoRepository userInfoRepository; TalentRepository talentRepository; + PhotoService photoService; @Override public String saveFile(MultipartFile file) { @@ -71,29 +75,36 @@ public List listAllFiles() { @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 = file.getContentType().split("/")[1]; + String userLogin = authentication.getName(); + + String fullPath = "%s/%s".formatted(userLogin, "image.%s".formatted(fileType)); + File f = photoService.degradePhoto(convertMultiPartToFile(file)); + + if (user.getTalent().getImageName() != null) + s3.deleteObject(awsProperties.bucket(), user.getTalent().getImageName()); s3.putObject(awsProperties.bucket(), fullPath, f); log.info("image = {}", s3.getUrl(awsProperties.bucket(), fullPath).toString()); + user.getTalent().setImage(s3.getUrl(awsProperties.bucket(), fullPath).toString()); + user.getTalent().setImageName(fullPath); + talentRepository.save(user.getTalent()); - } catch (RuntimeException | IOException e) { - throw new ResponseStatusException(NOT_IMPLEMENTED); + } catch (Exception e) { + throw new ResponseStatusException(SERVICE_UNAVAILABLE, "problems with connection to aws s3"); } + } private File convertMultiPartToFile(MultipartFile file) diff --git a/src/main/java/com/provedcode/config/InitConfig.java b/src/main/java/com/provedcode/config/InitConfig.java index f4d24bb..82aa7cb 100644 --- a/src/main/java/com/provedcode/config/InitConfig.java +++ b/src/main/java/com/provedcode/config/InitConfig.java @@ -1,29 +1,29 @@ -package com.provedcode.config; - -import com.provedcode.user.mapper.UserInfoMapper; -import com.provedcode.user.repo.UserInfoRepository; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.CommandLineRunner; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Component; - -@Slf4j -@Component -@AllArgsConstructor -public class InitConfig implements CommandLineRunner { - UserInfoRepository userInfoRepository; - PasswordEncoder passwordEncoder; - UserInfoMapper userInfoMapper; - - @Override - public void run(String... args) throws Exception { - // TODO: Method to change passwords for already created users from data1.sql - userInfoRepository.saveAll( - userInfoRepository.findAll().stream() - .map(i -> { - i.setPassword(passwordEncoder.encode(i.getPassword())); - return i; - }).toList()); - } -} \ No newline at end of file +//package com.provedcode.config; +// +//import com.provedcode.user.mapper.UserInfoMapper; +//import com.provedcode.user.repo.UserInfoRepository; +//import lombok.AllArgsConstructor; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.boot.CommandLineRunner; +//import org.springframework.security.crypto.password.PasswordEncoder; +//import org.springframework.stereotype.Component; +// +//@Slf4j +//@Component +//@AllArgsConstructor +//public class InitConfig implements CommandLineRunner { +// UserInfoRepository userInfoRepository; +// PasswordEncoder passwordEncoder; +// UserInfoMapper userInfoMapper; +// +// @Override +// public void run(String... args) throws Exception { +// // TODO: Method to change passwords for already created users from data1.sql +// userInfoRepository.saveAll( +// userInfoRepository.findAll().stream() +// .map(i -> { +// i.setPassword(passwordEncoder.encode(i.getPassword())); +// return i; +// }).toList()); +// } +//} \ No newline at end of file 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 cf460c5..7da4cc8 100644 --- a/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java +++ b/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java @@ -1,24 +1,34 @@ package com.provedcode.handlers; -import jakarta.validation.ConstraintViolation; 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.context.request.WebRequest; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.server.ResponseStatusException; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; @ControllerAdvice public class TalentExceptionHandler { - @ExceptionHandler(ResponseStatusException.class) - private ResponseEntity responseStatusExceptionHandler(ResponseStatusException exception) { - return ResponseEntity.status(exception.getStatusCode()).body(exception.getBody()); + 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}) @@ -29,10 +39,10 @@ public void printSQLException(SQLException ex) { e.printStackTrace(System.err); System.err.println("SQLState: " + - ((SQLException) e).getSQLState()); + ((SQLException) e).getSQLState()); System.err.println("Error Code: " + - ((SQLException) e).getErrorCode()); + ((SQLException) e).getErrorCode()); System.err.println("Message: " + e.getMessage()); @@ -46,59 +56,51 @@ public void printSQLException(SQLException ex) { } } - 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(ResponseStatusException.class) + private ResponseEntity responseStatusExceptionHandler(ResponseStatusException exception) { + return ResponseEntity.status(exception.getStatusCode()).body(exception.getBody()); } - @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()); + @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) { +// 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); -// }); +// 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()); - } +// @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 20f8bce..7f18175 100644 --- a/src/main/java/com/provedcode/kudos/controller/KudosController.java +++ b/src/main/java/com/provedcode/kudos/controller/KudosController.java @@ -1,107 +1,48 @@ package com.provedcode.kudos.controller; +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.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 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.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; + @RestController @AllArgsConstructor +@Validated @RequestMapping("/api/v3/") public class KudosController { KudosService kudosService; - @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) - }) + @GetKudosForSponsorApiDoc @PreAuthorize("hasRole('SPONSOR')") @GetMapping("/sponsors/{sponsor-id}/kudos") - KudosAmount getKudosForSponsor(@PathVariable("sponsor-id") long id, Authentication authentication) { - return kudosService.getKudosForSponsor(id, authentication); + KudosAmount getKudosForSponsor(@PathVariable("sponsor-id") long sponsorId, Authentication authentication) { + return kudosService.getKudosForSponsor(sponsorId, authentication); } - @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) - }) - @PreAuthorize("hasRole('SPONSOR')") - @PostMapping("/proofs/{proof-id}/kudos/{amount}") - void addKudosToProof(@PathVariable("proof-id") long id, - @PathVariable("amount") Long amount, - Authentication authentication) { - kudosService.addKudosToProof(id, amount, authentication); - } - - @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) - }) + @GetAmountOfKudosApiDoc @PreAuthorize("hasRole('TALENT')") @GetMapping("/proofs/{proof-id}/kudos") - KudosAmountWithSponsor getProofKudos(@PathVariable("proof-id") long id, Authentication authentication) { - return kudosService.getProofKudos(id, authentication); + KudosAmountWithSponsor getProofKudos(@PathVariable("proof-id") long proofId, Authentication authentication) { + return kudosService.getProofKudos(proofId, 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 8cacb21..259c387 100644 --- a/src/main/java/com/provedcode/kudos/model/entity/Kudos.java +++ b/src/main/java/com/provedcode/kudos/model/entity/Kudos.java @@ -17,8 +17,8 @@ public class Kudos { @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; - @Column(name = "amount_kudos") - private Long amountKudos; + @Column(name = "amount") + private Long amount; @ManyToOne @JoinColumn(name = "sponsor_id") private Sponsor sponsor; 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 index 16b302b..75b80f9 100644 --- a/src/main/java/com/provedcode/kudos/model/response/KudosAmountWithSponsor.java +++ b/src/main/java/com/provedcode/kudos/model/response/KudosAmountWithSponsor.java @@ -8,6 +8,6 @@ @Builder public record KudosAmountWithSponsor( Long allKudosOnProof, - Map kudosFromSponsor + 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 529129e..3b0f629 100644 --- a/src/main/java/com/provedcode/kudos/repository/KudosRepository.java +++ b/src/main/java/com/provedcode/kudos/repository/KudosRepository.java @@ -1,10 +1,10 @@ package com.provedcode.kudos.repository; import com.provedcode.kudos.model.entity.Kudos; -import com.provedcode.talent.model.entity.Talent; -import com.provedcode.talent.model.entity.TalentProof; import org.springframework.data.jpa.repository.JpaRepository; public interface KudosRepository extends JpaRepository { - long countByProof_Id(Long id); + long countByProofId(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 65dd7bf..f506391 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -1,6 +1,7 @@ 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; @@ -8,6 +9,7 @@ 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; import com.provedcode.talent.repo.TalentProofRepository; @@ -22,6 +24,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import static org.springframework.http.HttpStatus.*; @@ -37,75 +40,92 @@ public class KudosService { TalentRepository talentRepository; SponsorMapper sponsorMapper; - - public void addKudosToProof(long id, Long amount, Authentication authentication) { - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) + public void addKudosToProof(long proofId, Optional setAmountKudos, Authentication authentication) { + String login = authentication.getName(); + UserInfo userInfo = userInfoRepository.findByLogin(login) .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Sponsor with id = %s not found".formatted(id))); + "User with login = %s not found".formatted( + login))); Sponsor sponsor = sponsorRepository.findById(userInfo.getSponsor().getId()).orElseThrow( () -> new ResponseStatusException(NOT_FOUND, - String.format("sponsor with id = %d not found", id))); - TalentProof talentProof = talentProofRepository.findById(id) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "Proof with id = %s not found".formatted(id))); - if (sponsor.getAmountKudos() < amount) { + "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"); } - if (amount <= 0) { - throw new ResponseStatusException(BAD_REQUEST, "amount of kudos must be greater than 0"); - } - sponsor.setAmountKudos(sponsor.getAmountKudos() - amount); + sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); kudosRepository.save(Kudos.builder() - .amountKudos(amount) + .amount(obtainedAmount) .proof(talentProof) .sponsor(sponsor) .build()); } @Transactional(readOnly = true) - public KudosAmount getKudosForSponsor(long id, Authentication authentication) { - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) + public KudosAmount getKudosForSponsor(long sponsorId, Authentication authentication) { + String login = authentication.getName(); + UserInfo userInfo = userInfoRepository.findByLogin(login) .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Sponsor with id = %s not found".formatted(id))); - Sponsor sponsor = sponsorRepository.findById(userInfo.getSponsor().getId()).orElseThrow( - () -> new ResponseStatusException(NOT_FOUND, - String.format("Sponsor with id = %d not found", id))); - if (sponsor.getId() != userInfo.getSponsor().getId()) { + "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"); } + Sponsor sponsor = sponsorRepository.findById(sponsorId).orElseThrow( + () -> new ResponseStatusException(NOT_FOUND, + String.format("Sponsor with id = %d not found", sponsorId))); return new KudosAmount(sponsor.getAmountKudos()); } @Transactional(readOnly = true) - public KudosAmountWithSponsor getProofKudos(long id, Authentication authentication) { - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) + public KudosAmountWithSponsor getProofKudos(long proofId, Authentication authentication) { + String login = authentication.getName(); + UserInfo userInfo = userInfoRepository.findByLogin(login) .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Sponsor with id = %s not found".formatted(id))); + "User with login = %s not found".formatted( + login))); Talent talent = talentRepository.findById(userInfo.getId()) .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Talent with id = %s not found".formatted(id))); - TalentProof talentProof = talentProofRepository.findById(id) + "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(id))); + "Proof with id = %s not found".formatted( + proofId))); - if (talent.getId() == talentProof.getTalent().getId()) { - Map kudosFromSponsor = talentProof.getKudos().stream() + Long countOfAllKudos = talentProof.getKudos().stream() + .map(Kudos::getAmount) + .reduce(0L, (prev, next) -> prev + next); + + if (talent.getId().equals(talentProof.getTalent().getId())) { + Map kudosFromSponsor = talentProof.getKudos().stream() .collect(Collectors.toMap( - sponsor -> sponsorMapper.toDto(sponsor.getSponsor()), - Kudos::getAmountKudos, - (sponsor, kudos) -> sponsor, + Kudos::getAmount, + proof -> proof.getSponsor() != null + ? sponsorMapper.toDto( + proof.getSponsor()) + : SponsorDTO.builder().build(), + (prev, next) -> next, HashMap::new )); - Long counter = talentProof.getKudos().stream().map(i -> i.getAmountKudos()) - .mapToLong(Long::intValue).sum(); + return KudosAmountWithSponsor.builder() - .allKudosOnProof(counter) + .allKudosOnProof(countOfAllKudos) .kudosFromSponsor(kudosFromSponsor) .build(); } else { - Long counter = talentProof.getKudos().stream().map(i -> i.getAmountKudos()) - .mapToLong(Long::intValue).sum(); return KudosAmountWithSponsor.builder() - .allKudosOnProof(counter) + .allKudosOnProof(countOfAllKudos) .kudosFromSponsor(null).build(); } } diff --git a/src/main/java/com/provedcode/sponsor/controller/SponsorController.java b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java index ea61f10..39c5bad 100644 --- a/src/main/java/com/provedcode/sponsor/controller/SponsorController.java +++ b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java @@ -2,135 +2,56 @@ import com.provedcode.sponsor.mapper.SponsorMapper; import com.provedcode.sponsor.model.dto.SponsorDTO; -import com.provedcode.sponsor.model.dto.SponsorEditDTO; +import com.provedcode.sponsor.model.request.EditSponsor; import com.provedcode.sponsor.service.SponsorService; -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.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.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; @RestController @AllArgsConstructor +@Validated @RequestMapping("/api/v3") public class SponsorController { SponsorService sponsorService; SponsorMapper sponsorMapper; - @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) - }) + @GetAllSponsorsApiDoc @GetMapping("/sponsors") - @ResponseStatus(HttpStatus.OK) - Page getSponsors(@RequestParam(value = "page") Optional page, - @RequestParam(value = "size") Optional size) { + 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); } - @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) - }) + @GetSponsorApiDoc @PreAuthorize("hasRole('SPONSOR')") @GetMapping("/sponsors/{id}") SponsorDTO getSponsor(@PathVariable("id") long id, Authentication authentication) { return sponsorMapper.toDto(sponsorService.getSponsorById(id, authentication)); } - @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) - }) + @PatchEditSponsorApiDoc @PreAuthorize("hasRole('SPONSOR')") @PatchMapping("/sponsors/{id}") SponsorDTO editSponsor(@PathVariable("id") long id, - @RequestBody SponsorEditDTO sponsorEditDTO, + @RequestBody EditSponsor editSponsor, Authentication authentication) { - return sponsorMapper.toDto(sponsorService.editSponsorById(id, sponsorEditDTO, authentication)); + return sponsorMapper.toDto(sponsorService.editSponsorById(id, editSponsor, authentication)); } - @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), - }) + @DeleteSponsorApiDoc @PreAuthorize("hasRole('SPONSOR')") @DeleteMapping("/sponsors/{id}") void deleteSponsor(@PathVariable("id") long id, Authentication authentication) { diff --git a/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java b/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java index adffbbd..62c3b62 100644 --- a/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java +++ b/src/main/java/com/provedcode/sponsor/model/dto/SponsorDTO.java @@ -1,7 +1,9 @@ package com.provedcode.sponsor.model.dto; import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Builder; +@Builder public record SponsorDTO( Long id, @JsonProperty("first_name") diff --git a/src/main/java/com/provedcode/sponsor/model/dto/SponsorEditDTO.java b/src/main/java/com/provedcode/sponsor/model/request/EditSponsor.java similarity index 81% rename from src/main/java/com/provedcode/sponsor/model/dto/SponsorEditDTO.java rename to src/main/java/com/provedcode/sponsor/model/request/EditSponsor.java index 82867a5..55bf951 100644 --- a/src/main/java/com/provedcode/sponsor/model/dto/SponsorEditDTO.java +++ b/src/main/java/com/provedcode/sponsor/model/request/EditSponsor.java @@ -1,10 +1,10 @@ -package com.provedcode.sponsor.model.dto; +package com.provedcode.sponsor.model.request; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Builder; @Builder -public record SponsorEditDTO( +public record EditSponsor( Long id, @JsonProperty("first_name") String firstName, diff --git a/src/main/java/com/provedcode/sponsor/service/SponsorService.java b/src/main/java/com/provedcode/sponsor/service/SponsorService.java index 933fb69..8beaba7 100644 --- a/src/main/java/com/provedcode/sponsor/service/SponsorService.java +++ b/src/main/java/com/provedcode/sponsor/service/SponsorService.java @@ -2,9 +2,10 @@ import com.provedcode.config.PageProperties; import com.provedcode.kudos.model.entity.Kudos; -import com.provedcode.sponsor.model.dto.SponsorEditDTO; 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; @@ -18,7 +19,8 @@ import java.util.List; import java.util.Optional; -import static org.springframework.http.HttpStatus.*; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.FORBIDDEN; @Service @AllArgsConstructor @@ -27,70 +29,64 @@ public class SponsorService { PageProperties pageProperties; SponsorRepository sponsorRepository; UserInfoRepository userInfoRepository; + ValidateSponsorForCompliance validateSponsorForCompliance; @Transactional(readOnly = true) - public Page getAllSponsors(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 sponsorRepository.findAll(PageRequest.of(page.orElse(pageProperties.defaultPageNum()), - size.orElse(pageProperties.defaultPageSize()))); + public Page getAllSponsors(Integer page, Integer size) { + return sponsorRepository.findAll(PageRequest.of(page, size)); } @Transactional(readOnly = true) public Sponsor getSponsorById(long id, Authentication authentication) { - Sponsor sponsor = sponsorRepository.findById(id).orElseThrow( - () -> new ResponseStatusException(NOT_FOUND, String.format("sponsor with id = %d not found", id))); - UserInfo user = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_IMPLEMENTED, "login is not valid")); - - if (!sponsor.getId().equals(user.getSponsor().getId())) - throw new ResponseStatusException(FORBIDDEN, "The user cannot view someone else's profile"); - return sponsor; + Optional user = userInfoRepository.findByLogin(authentication.getName()); + Optional sponsor = sponsorRepository.findById(id); + validateSponsorForCompliance.userVerification(sponsor, user, id); + return sponsor.get(); } - public Sponsor editSponsorById(long id, SponsorEditDTO sponsorEditDTO, Authentication authentication) { - Sponsor sponsor = sponsorRepository.findById(id) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "sponsor with id = %s not found".formatted(id))); - UserInfo user = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_IMPLEMENTED, "login is not valid")); - if (!sponsor.getId().equals(user.getSponsor().getId())) { - throw new ResponseStatusException(FORBIDDEN, "The user cannot edit someone else's profile"); - } + 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); - if (sponsorEditDTO.firstName() != null) { - sponsor.setFirstName(sponsorEditDTO.firstName()); + Sponsor editableSponsor = sponsor.get(); + if (editSponsor.firstName() != null) { + editableSponsor.setFirstName(editSponsor.firstName()); } - if (sponsorEditDTO.lastName() != null) { - sponsor.setLastName(sponsorEditDTO.lastName()); + if (editSponsor.lastName() != null) { + editableSponsor.setLastName(editSponsor.lastName()); } - if (sponsorEditDTO.image() != null) { - sponsor.setImage(sponsorEditDTO.image()); + if (editSponsor.image() != null) { + editableSponsor.setImage(editSponsor.image()); } - if (sponsorEditDTO.countOfKudos() != null) { - if (sponsorEditDTO.countOfKudos() > 0) { - sponsor.setAmountKudos(sponsor.getAmountKudos() + sponsorEditDTO.countOfKudos()); + 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(sponsor); + return sponsorRepository.save(editableSponsor); } public void deleteSponsor(long id, Authentication authentication) { - Sponsor sponsor = sponsorRepository.findById(id) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "sponsor with id = %s not found".formatted(id))); - UserInfo user = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_IMPLEMENTED, "login is not valid")); - if (!sponsor.getId().equals(user.getSponsor().getId())) { - throw new ResponseStatusException(FORBIDDEN, "The user cannot edit someone else's profile"); - } + 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()); + } - List kudosList = sponsor.getKudoses().stream().map(i -> {i.setSponsor(null); return i;}).toList(); - sponsor.setKudoses(kudosList); - userInfoRepository.delete(user); + 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 5ab3d23..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 (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) - }) + @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,28 +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), - @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 331ad63..9e65c3a 100644 --- a/src/main/java/com/provedcode/talent/model/entity/Talent.java +++ b/src/main/java/com/provedcode/talent/model/entity/Talent.java @@ -35,6 +35,9 @@ public class Talent { @URL @Column(name = "image", length = 300) 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) 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 e4783b4..3880350 100644 --- a/src/main/java/com/provedcode/talent/service/TalentProofService.java +++ b/src/main/java/com/provedcode/talent/service/TalentProofService.java @@ -29,10 +29,10 @@ import java.net.URI; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.List; 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 @@ -46,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) @@ -83,7 +65,7 @@ public TalentProof getTalentProof(long proofId, Authentication authentication) { () -> new ResponseStatusException(NOT_FOUND, "user with this token not found")); if (talentProof.getTalent().getId().equals(userInfo.getTalent().getId()) || - talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { + talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { return talentProof; } else { throw new ResponseStatusException(FORBIDDEN); @@ -91,62 +73,37 @@ 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( - talentId))); - UserInfo userInfo = userInfoRepository.findById(talentId) - .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, - "Talent with id = %s not found".formatted( - talentId))); + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, + "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.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()) - .firstName(talent.getFirstName()) - .lastName(talent.getLastName()) - .specialization(talent.getSpecialization()) - .proofs(proofs.map(i -> ProofDTO.builder() - .id(i.getId()) - .created(DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss") - .format(i.getCreated())) - .link(i.getLink()) - .text(i.getText()) - .status(i.getStatus()).build())) - .build(); + .id(talent.getId()) + .image(talent.getImage()) + .firstName(talent.getFirstName()) + .lastName(talent.getLastName()) + .specialization(talent.getSpecialization()) + .proofs(proofs.map(i -> ProofDTO.builder() + .id(i.getId()) + .created(DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss") + .format(i.getCreated())) + .link(i.getLink()) + .text(i.getText()) + .status(i.getStatus()).build())) + .build(); } public ResponseEntity addProof(AddProof addProof, long talentId, Authentication authentication) { @@ -156,13 +113,12 @@ public ResponseEntity addProof(AddProof addProof, long talentId, Authenticati validateTalentForCompliance.userVerification(talent, userInfo, talentId); TalentProof talentProof = TalentProof.builder() - .talent(talent.get()) - .link(addProof.link()) - .text(addProof.text()) - .status(ProofStatus.DRAFT) - .created(LocalDateTime.now()) - .build(); - + .talent(talent.get()) + .link(addProof.link()) + .text(addProof.text()) + .status(ProofStatus.DRAFT) + .created(LocalDateTime.now()) + .build(); talentProofRepository.save(talentProof); URI location = ServletUriComponentsBuilder @@ -188,14 +144,11 @@ public TalentProof editTalentProof(long talentId, long proofId, ProofDTO proof, throw new ResponseStatusException(FORBIDDEN, "you cannot change proofs status to DRAFT"); if (oldProofStatus == ProofStatus.DRAFT && proof.status() == ProofStatus.HIDDEN) throw new ResponseStatusException(FORBIDDEN, - "you cannot change proofs status from DRAFT to HIDDEN, it should be PUBLISHED"); + "you cannot change proofs status from DRAFT to HIDDEN, it should be PUBLISHED"); if (proof.link() == null && proof.text() == null) { oldProof.setStatus(proof.status()); } else { - if (oldProofStatus != ProofStatus.DRAFT) - throw new ResponseStatusException(FORBIDDEN, "you cannot edit proofs without DRAFT status"); - oldProof.setLink(proof.link() != null ? proof.link() : oldProof.getLink()) .setText(proof.text() != null ? proof.text() : oldProof.getText()) .setStatus(proof.status()); 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 69559c6..b30ee13 100644 --- a/src/main/java/com/provedcode/user/controller/AuthenticationController.java +++ b/src/main/java/com/provedcode/user/controller/AuthenticationController.java @@ -4,16 +4,13 @@ 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.*; @@ -24,63 +21,20 @@ 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) - }) + @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), - }) + @PostTalentRegistrationApiDoc @PostMapping("/v2/talents/register") @ResponseStatus(HttpStatus.CREATED) UserInfoDTO register(@RequestBody @Valid TalentRegistrationDTO user) { return authenticationService.register(user); } - @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), - }) + @PostSponsorRegistrationApiDoc @PostMapping("/v3/sponsors/register") @ResponseStatus(HttpStatus.CREATED) UserInfoDTO register(@RequestBody @Valid SponsorRegistrationDTO user) { diff --git a/src/main/java/com/provedcode/user/util/UserInfoValidator.java b/src/main/java/com/provedcode/user/util/UserInfoValidator.java new file mode 100644 index 0000000..04dd6c4 --- /dev/null +++ b/src/main/java/com/provedcode/user/util/UserInfoValidator.java @@ -0,0 +1,24 @@ +package com.provedcode.user.util; + +import com.provedcode.user.model.entity.UserInfo; +import com.provedcode.user.repo.UserInfoRepository; +import lombok.AllArgsConstructor; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ResponseStatusException; + +import static org.springframework.http.HttpStatus.NOT_FOUND; + +@Component +@AllArgsConstructor +public class UserInfoValidator { + UserInfoRepository userInfoRepository; + + public UserInfo findByLoginOrElseThrow(Authentication authentication) { + String login = authentication.getName(); + return userInfoRepository.findByLogin(login) + .orElseThrow(() -> 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..a7b74d3 --- /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 { + // загружаем изображение из файла + BufferedImage originalImage = ImageIO.read(photoFile); + + // устанавливаем новый размер для изображения + int newWidth = 300; + int newHeight = 300; + + // создаем новое изображение с новым размером + 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 4b8f38f..6bd5814 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 dbc8154..f91aa56 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -11,7 +11,8 @@ spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect spring.datasource.driver-class-name=org.postgresql.Driver spring.h2.console.enabled=true spring.h2.console.path=/h2 -spring.jpa.hibernate.ddl-auto=create-drop +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/V1/data-V1.sql b/src/main/resources/db/changelog/changeset/V1/data-V1.sql new file mode 100644 index 0000000..3b8e80a --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V1/data-V1.sql @@ -0,0 +1,547 @@ +--liquibase formatted sql +--changeset dennis:1 + +insert into authority (id, authority) +values (1, 'TALENT'); +-- -- 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 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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); + +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', '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)); \ 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/V1/schema-V1.sql b/src/main/resources/db/changelog/changeset/V1/schema-V1.sql new file mode 100644 index 0000000..7eccc32 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V1/schema-V1.sql @@ -0,0 +1,132 @@ +-- liquibase formatted sql +-- changeset dennis:1 + +drop table if exists authority cascade; + +CREATE TABLE authority +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + authority VARCHAR(20) NOT NULL, + CONSTRAINT pk_authority PRIMARY KEY (id) +); + +drop table if exists talent cascade; +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(300), + CONSTRAINT pk_talent PRIMARY KEY (id) +); + +drop table if exists talent_attached_file cascade; +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) +); + +drop table if exists talent_contact cascade; +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) +); + +drop table if exists talent_description cascade; +CREATE TABLE talent_description +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL, + bio VARCHAR(255), + addition_info VARCHAR(255), + CONSTRAINT pk_talent_description PRIMARY KEY (id) +); + +drop table if exists talent_link cascade; +CREATE TABLE talent_link +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL, + link VARCHAR(255), + CONSTRAINT pk_talent_link PRIMARY KEY (id) +); + +drop table if exists talent_proofs cascade; +CREATE TABLE talent_proofs +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL, + link VARCHAR(100), + text VARCHAR(255), + status VARCHAR(20) NOT NULL, + created TIMESTAMP, + CONSTRAINT pk_talent_proofs PRIMARY KEY (id) +); + +drop table if exists talent_talents cascade; +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) +); + +drop table if exists user_authorities cascade; +CREATE TABLE user_authorities +( + authority_id BIGINT NOT NULL, + user_id BIGINT NOT NULL, + CONSTRAINT pk_user_authorities PRIMARY KEY (authority_id, user_id) +); + +drop table if exists user_info cascade; +CREATE TABLE user_info +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL, + login VARCHAR(100) NOT NULL, + password VARCHAR(255) NOT NULL, + CONSTRAINT pk_user_info PRIMARY KEY (id) +); + + +drop table if exists kudos cascade; +CREATE TABLE kudos +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT, + proof_id BIGINT, + CONSTRAINT pk_kudos 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_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/add-data.sql b/src/main/resources/db/changelog/changeset/V2/data-V2.sql similarity index 96% rename from src/main/resources/db/changelog/changeset/add-data.sql rename to src/main/resources/db/changelog/changeset/V2/data-V2.sql index ce9026b..a5de8d5 100644 --- a/src/main/resources/db/changelog/changeset/add-data.sql +++ b/src/main/resources/db/changelog/changeset/V2/data-V2.sql @@ -1,5 +1,5 @@ --liquibase formatted sql ---changeset dennis:1 +--changeset mykhailo:2 -- -- FOR USER AUTHORITY -- -- SELECT USER_INFO.ID , LOGIN , PASSWORD, talent_id , AUTHORITY FROM @@ -50,7 +50,7 @@ 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', '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)); @@ -93,7 +93,7 @@ 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', '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)); @@ -134,7 +134,7 @@ 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', '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)); @@ -174,7 +174,7 @@ 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', '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)); @@ -216,7 +216,7 @@ 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', '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)); @@ -256,7 +256,7 @@ 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', '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)); @@ -298,7 +298,7 @@ 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', '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)); @@ -338,7 +338,7 @@ 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', '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)); @@ -380,7 +380,7 @@ 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', '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)); @@ -420,7 +420,7 @@ 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', '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)); @@ -460,7 +460,7 @@ 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', '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)); @@ -502,7 +502,7 @@ 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', '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)); @@ -544,7 +544,7 @@ 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', '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)); @@ -553,7 +553,7 @@ 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', '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) ); @@ -562,7 +562,7 @@ 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', '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) ); @@ -571,7 +571,7 @@ 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', '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) ); @@ -580,16 +580,16 @@ 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', '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_kudos, sponsor_id, proof_id) +insert into kudos (amount, sponsor_id, proof_id) values (100, 1, 1); -insert into kudos (amount_kudos, sponsor_id, proof_id) +insert into kudos (amount, sponsor_id, proof_id) values (200, 2, 1); -insert into kudos (amount_kudos, sponsor_id, proof_id) +insert into kudos (amount, sponsor_id, proof_id) values (200, 3, 1); -insert into kudos (amount_kudos, sponsor_id, proof_id) +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/create-tables.sql b/src/main/resources/db/changelog/changeset/V2/schema-V2.sql similarity index 85% rename from src/main/resources/db/changelog/changeset/create-tables.sql rename to src/main/resources/db/changelog/changeset/V2/schema-V2.sql index 18a84f4..19ba151 100644 --- a/src/main/resources/db/changelog/changeset/create-tables.sql +++ b/src/main/resources/db/changelog/changeset/V2/schema-V2.sql @@ -1,7 +1,8 @@ -- liquibase formatted sql --- changeset dennis:1 +-- changeset mykhailo:2 + +-- tables for sprint 3.2 -drop table if exists authority cascade; CREATE TABLE authority ( @@ -9,8 +10,6 @@ CREATE TABLE authority authority VARCHAR(20) NOT NULL, CONSTRAINT pk_authority PRIMARY KEY (id) ); - -drop table if exists talent cascade; CREATE TABLE talent ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -18,10 +17,9 @@ CREATE TABLE talent last_name VARCHAR(20), specialization VARCHAR(30), image VARCHAR(300), + image_name VARCHAR(100), CONSTRAINT pk_talent PRIMARY KEY (id) ); - -drop table if exists talent_attached_file cascade; CREATE TABLE talent_attached_file ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -29,8 +27,6 @@ CREATE TABLE talent_attached_file attached_file VARCHAR(100), CONSTRAINT pk_talent_attached_file PRIMARY KEY (id) ); - -drop table if exists talent_contact cascade; CREATE TABLE talent_contact ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -38,39 +34,31 @@ CREATE TABLE talent_contact contact VARCHAR(255), CONSTRAINT pk_talent_contact PRIMARY KEY (id) ); - -drop table if exists talent_description cascade; CREATE TABLE talent_description ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, talent_id BIGINT NOT NULL, - bio VARCHAR(255), - addition_info VARCHAR(255), + bio VARCHAR(2000), + addition_info VARCHAR(500), CONSTRAINT pk_talent_description PRIMARY KEY (id) ); - -drop table if exists talent_link cascade; CREATE TABLE talent_link ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, talent_id BIGINT NOT NULL, - link VARCHAR(255), + link VARCHAR(500), CONSTRAINT pk_talent_link PRIMARY KEY (id) ); - -drop table if exists talent_proofs cascade; CREATE TABLE talent_proofs ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, talent_id BIGINT NOT NULL, link VARCHAR(100), - text VARCHAR(255), + text VARCHAR(1000), status VARCHAR(20) NOT NULL, created TIMESTAMP, CONSTRAINT pk_talent_proofs PRIMARY KEY (id) ); - -drop table if exists talent_talents cascade; CREATE TABLE talent_talents ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -78,16 +66,12 @@ CREATE TABLE talent_talents talent_name VARCHAR(255), CONSTRAINT pk_talent_talents PRIMARY KEY (id) ); - -drop table if exists user_authorities cascade; CREATE TABLE user_authorities ( authority_id BIGINT NOT NULL, user_id BIGINT NOT NULL, CONSTRAINT pk_user_authorities PRIMARY KEY (authority_id, user_id) ); - -drop table if exists user_info cascade; CREATE TABLE user_info ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -97,18 +81,14 @@ CREATE TABLE user_info password VARCHAR(255) NOT NULL, CONSTRAINT pk_user_info PRIMARY KEY (id) ); - -drop table if exists kudos cascade; CREATE TABLE kudos ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, sponsor_id BIGINT, proof_id BIGINT, - amount_kudos BIGINT, + amount BIGINT, CONSTRAINT pk_kudos PRIMARY KEY (id) ); - -drop table if exists sponsor cascade; CREATE TABLE sponsor ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, 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 From fdc5c1186cafd1ac8a8009b63a19c50da9c2e05e Mon Sep 17 00:00:00 2001 From: Maslyna Date: Thu, 4 May 2023 18:01:46 +0200 Subject: [PATCH 21/59] AWS update: PresignedURL --- .../aws/controller/AWSS3BucketController.java | 2 +- .../com/provedcode/aws/service/S3Service.java | 51 ++++++++++++------- .../sponsor/model/entity/Sponsor.java | 4 +- .../talent/model/entity/Talent.java | 2 +- .../db/changelog/changeset/V2/schema-V2.sql | 5 +- 5 files changed, 42 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java index 70a2d6f..8f72600 100644 --- a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java +++ b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java @@ -57,9 +57,9 @@ URL getURL() { GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(awsProperties.bucket(), "MykhailoOrdyntsev@gmail.com/image.jpeg") .withMethod(HttpMethod.GET); Instant expiration = Instant.now().plusMillis(1000L * 60 * 60 * 24 * 7); - urlRequest.setExpiration(Date.from(expiration)); URL url = amazonS3.generatePresignedUrl(urlRequest); + return url; } diff --git a/src/main/java/com/provedcode/aws/service/S3Service.java b/src/main/java/com/provedcode/aws/service/S3Service.java index 439ee94..4e4c1a2 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; @@ -20,10 +21,11 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.util.Arrays; +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.*; @Service @@ -32,7 +34,7 @@ @Transactional public class S3Service implements FileService { AWSProperties awsProperties; - AmazonS3 s3; + AmazonS3 amazonS3; UserInfoRepository userInfoRepository; TalentRepository talentRepository; PhotoService photoService; @@ -42,7 +44,7 @@ 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); @@ -51,7 +53,7 @@ public String saveFile(MultipartFile file) { @Override public byte[] downloadFile(String filename) { - S3Object object = s3.getObject(awsProperties.bucket(), filename); + S3Object object = amazonS3.getObject(awsProperties.bucket(), filename); S3ObjectInputStream objectContent = object.getObjectContent(); try { return IOUtils.toByteArray(objectContent); @@ -62,13 +64,13 @@ public byte[] downloadFile(String filename) { @Override public String deleteFile(String filename) { - s3.deleteObject(awsProperties.bucket(), filename); + amazonS3.deleteObject(awsProperties.bucket(), filename); 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(); } @@ -84,21 +86,28 @@ public void setNewUserImage(MultipartFile file, Authentication authentication) { .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "user with login = {%s} not found".formatted(authentication.getName()))); try { - String fileType = file.getContentType().split("/")[1]; - String userLogin = authentication.getName(); + String fileType = getFileType(file); + String fullPath = getFullPath(fileType, authentication.getName()); + File degradePhoto = photoService.degradePhoto(convertMultiPartToFile(file)); - String fullPath = "%s/%s".formatted(userLogin, "image.%s".formatted(fileType)); - File f = photoService.degradePhoto(convertMultiPartToFile(file)); + if (user.getTalent().getImageName() != null) // delete old user image + amazonS3.deleteObject(awsProperties.bucket(), user.getTalent().getImageName()); - if (user.getTalent().getImageName() != null) - s3.deleteObject(awsProperties.bucket(), user.getTalent().getImageName()); + amazonS3.putObject(awsProperties.bucket(), fullPath, degradePhoto); - s3.putObject(awsProperties.bucket(), fullPath, f); + user.getTalent().setImageName(fullPath); - log.info("image = {}", s3.getUrl(awsProperties.bucket(), fullPath).toString()); + GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(awsProperties.bucket(), fullPath) + .withMethod(HttpMethod.GET); - user.getTalent().setImage(s3.getUrl(awsProperties.bucket(), fullPath).toString()); - user.getTalent().setImageName(fullPath); + Instant expiration = Instant.now().plusMillis(1000L * 60 * 60 * 24 * 7); // expiration time + urlRequest.setExpiration(Date.from(expiration)); + URL url = amazonS3.generatePresignedUrl(urlRequest); // generation url with expiration + + log.info("image = {}", amazonS3.getUrl(awsProperties.bucket(), fullPath).toString()); + log.info("image-url = {}", url); + + user.getTalent().setImage(url.toString()); talentRepository.save(user.getTalent()); } catch (Exception e) { @@ -107,6 +116,14 @@ public void setNewUserImage(MultipartFile file, Authentication authentication) { } + private String getFullPath(String fileType, String userLogin) { + return "%s/%s".formatted(userLogin, "image.%s".formatted(fileType)); + } + + private String getFileType(MultipartFile file) { + return file.getContentType().split("/")[1]; + } + private File convertMultiPartToFile(MultipartFile file) throws IOException { File convFile = new File(file.getOriginalFilename()); diff --git a/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java b/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java index 30b12d7..662de41 100644 --- a/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java +++ b/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java @@ -30,8 +30,10 @@ public class Sponsor { @Column(name = "last_name", length = 20) private String lastName; @URL - @Column(name = "image", length = 300) + @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/talent/model/entity/Talent.java b/src/main/java/com/provedcode/talent/model/entity/Talent.java index 9e65c3a..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,7 +33,7 @@ public class Talent { @Column(name = "specialization", length = 30) private String specialization; @URL - @Column(name = "image", length = 300) + @Column(name = "image", length = 1000) private String image; @Column(name = "image_name", length = 100) private String imageName; diff --git a/src/main/resources/db/changelog/changeset/V2/schema-V2.sql b/src/main/resources/db/changelog/changeset/V2/schema-V2.sql index 19ba151..adad4a6 100644 --- a/src/main/resources/db/changelog/changeset/V2/schema-V2.sql +++ b/src/main/resources/db/changelog/changeset/V2/schema-V2.sql @@ -16,7 +16,7 @@ CREATE TABLE talent first_name VARCHAR(20), last_name VARCHAR(20), specialization VARCHAR(30), - image VARCHAR(300), + image VARCHAR(1000), image_name VARCHAR(100), CONSTRAINT pk_talent PRIMARY KEY (id) ); @@ -94,7 +94,8 @@ CREATE TABLE sponsor id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, first_name VARCHAR(20), last_name VARCHAR(20), - image VARCHAR(300), + image VARCHAR(1000), + image_name VARCHAR(100), amount_kudos BIGINT, CONSTRAINT pk_sponsor PRIMARY KEY (id) ); From 63b7c041f65c149818d1cc8b9274f2a79fe9ef65 Mon Sep 17 00:00:00 2001 From: Maslyna Date: Thu, 4 May 2023 18:47:51 +0200 Subject: [PATCH 22/59] AWS update: Scheduler for presigned url --- .../com/provedcode/ProvedCodeApplication.java | 2 ++ .../aws/controller/AWSS3BucketController.java | 21 ++----------- .../aws/scheduler/UpdateScheduler.java | 30 +++++++++++++++++++ .../provedcode/aws/service/FileService.java | 3 ++ .../com/provedcode/aws/service/S3Service.java | 18 ++++++----- 5 files changed, 48 insertions(+), 26 deletions(-) create mode 100644 src/main/java/com/provedcode/aws/scheduler/UpdateScheduler.java diff --git a/src/main/java/com/provedcode/ProvedCodeApplication.java b/src/main/java/com/provedcode/ProvedCodeApplication.java index f88f54e..58b471f 100644 --- a/src/main/java/com/provedcode/ProvedCodeApplication.java +++ b/src/main/java/com/provedcode/ProvedCodeApplication.java @@ -3,9 +3,11 @@ 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); diff --git a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java index 8f72600..28acaf0 100644 --- a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java +++ b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java @@ -1,8 +1,6 @@ package com.provedcode.aws.controller; -import com.amazonaws.HttpMethod; import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; import com.provedcode.aws.service.FileService; import com.provedcode.config.AWSProperties; import com.provedcode.util.annotations.doc.controller.aws.GetAllAWSBucketFilesDevApiDoc; @@ -14,10 +12,7 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import java.net.URL; -import java.time.Instant; import java.util.Arrays; -import java.util.Date; import java.util.List; @RestController @@ -36,14 +31,14 @@ public void setNewUserImage(@RequestParam("file") MultipartFile file, fileService.setNewUserImage(file, authentication); } - @GetFileInfoDevApiDoc + @GetAllAWSBucketFilesDevApiDoc @PreAuthorize("hasRole('TALENT')") @GetMapping("/files") List getAllFiles() { return fileService.listAllFiles(); } - @GetAllAWSBucketFilesDevApiDoc + @GetFileInfoDevApiDoc @PreAuthorize("hasRole('TALENT')") @PostMapping("/aws/test-of-filetype") String testTypeOfFile(@RequestParam("file") MultipartFile file, @@ -51,16 +46,4 @@ String testTypeOfFile(@RequestParam("file") MultipartFile file, return Arrays.stream(file.getContentType().split("/")).toList().get(1) + " " + file.getOriginalFilename() + " " + file.getName() + " " + file.getResource(); } - - @GetMapping("/aws/test") - URL getURL() { - GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(awsProperties.bucket(), "MykhailoOrdyntsev@gmail.com/image.jpeg") - .withMethod(HttpMethod.GET); - Instant expiration = Instant.now().plusMillis(1000L * 60 * 60 * 24 * 7); - urlRequest.setExpiration(Date.from(expiration)); - URL url = amazonS3.generatePresignedUrl(urlRequest); - - return url; - } - } 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 369898a..1c1d9e6 100644 --- a/src/main/java/com/provedcode/aws/service/FileService.java +++ b/src/main/java/com/provedcode/aws/service/FileService.java @@ -3,6 +3,7 @@ import org.springframework.security.core.Authentication; import org.springframework.web.multipart.MultipartFile; +import java.net.URL; import java.util.List; public interface FileService { @@ -16,4 +17,6 @@ public interface FileService { 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 4e4c1a2..61414c9 100644 --- a/src/main/java/com/provedcode/aws/service/S3Service.java +++ b/src/main/java/com/provedcode/aws/service/S3Service.java @@ -97,12 +97,7 @@ public void setNewUserImage(MultipartFile file, Authentication authentication) { user.getTalent().setImageName(fullPath); - GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(awsProperties.bucket(), fullPath) - .withMethod(HttpMethod.GET); - - Instant expiration = Instant.now().plusMillis(1000L * 60 * 60 * 24 * 7); // expiration time - urlRequest.setExpiration(Date.from(expiration)); - URL url = amazonS3.generatePresignedUrl(urlRequest); // generation url with expiration + URL url = generetePresingedUrlFor7Days(fullPath); // generation url with expiration log.info("image = {}", amazonS3.getUrl(awsProperties.bucket(), fullPath).toString()); log.info("image-url = {}", url); @@ -110,12 +105,21 @@ public void setNewUserImage(MultipartFile file, Authentication authentication) { user.getTalent().setImage(url.toString()); talentRepository.save(user.getTalent()); - } catch (Exception e) { + } 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)); } From 64cdb3609b00f5e2e45f6178b7a8e40505764781 Mon Sep 17 00:00:00 2001 From: Ren Date: Thu, 4 May 2023 23:28:53 +0300 Subject: [PATCH 23/59] * Create table: - skill - talent skill * update table relationship * add index in user_info table on login --- .../db/changelog/changeset/V4/drop-V4.sql | 18 +++ .../db/changelog/changeset/V4/schema-V4.sql | 120 ++++++++++++++++++ .../db/changelog/db.changelog-master.yaml | 18 +-- 3 files changed, 148 insertions(+), 8 deletions(-) create mode 100644 src/main/resources/db/changelog/changeset/V4/drop-V4.sql create mode 100644 src/main/resources/db/changelog/changeset/V4/schema-V4.sql diff --git a/src/main/resources/db/changelog/changeset/V4/drop-V4.sql b/src/main/resources/db/changelog/changeset/V4/drop-V4.sql new file mode 100644 index 0000000..091f48d --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V4/drop-V4.sql @@ -0,0 +1,18 @@ +--liquibase formatted sql +--changeset Ren:0 +-- Talent +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_skill cascade; +drop table if exists skill cascade; +-- User +drop table if exists authority cascade; +drop table if exists user_authorities cascade; +drop table if exists user_info cascade; +-- Sponsor +drop table if exists sponsor cascade; +drop table if exists kudos cascade; \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V4/schema-V4.sql b/src/main/resources/db/changelog/changeset/V4/schema-V4.sql new file mode 100644 index 0000000..a8ef942 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V4/schema-V4.sql @@ -0,0 +1,120 @@ +-- liquibase formatted sql +-- changeset Ren:0 +-- tables for sprint 4.1 +-- Talent +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_skill ( + proof_id BIGINT NOT NULL, + skill_id BIGINT NOT NULL, + CONSTRAINT pk_talent_skill PRIMARY KEY (proof_id, skill_id) +); +CREATE TABLE skill ( + id BIGINT NOT NULL, + skill VARCHAR(30), + CONSTRAINT pk_skill PRIMARY KEY (id) +); +-- User +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 authority ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + authority VARCHAR(20) NOT NULL, + CONSTRAINT pk_authority 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) +); +-- Sponsor +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) +); +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) +); +-- Foreign keys +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 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); +ALTER TABLE talent_skill +ADD CONSTRAINT FK_TALENT_SKILL_ON_TALENT_PROOF FOREIGN KEY (proof_id) REFERENCES talent_proofs (id); +ALTER TABLE talent_skill +ADD CONSTRAINT FK_TALENT_SKILL_ON_SKILL FOREIGN KEY (skill_id) REFERENCES skill (id); +-- Indexes +CREATE UNIQUE INDEX idx_login ON user_info (login) \ 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 4a6438c..5febddb 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -1,9 +1,11 @@ databaseChangeLog: - - include: - file: db/changelog/changeset/V1/drop-V1.sql - - include: - 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 + - include: + file: db/changelog/changeset/V1/drop-V1.sql + - include: + file: db/changelog/changeset/V2/drop-V2.sql + - include: + file: db/changelog/changeset/V4/drop-V4.sql + - include: + file: db/changelog/changeset/V4/schema-V4.sql + # - include: + # file: db/changelog/changeset/V2/data-V4.sql From 0933751b4af88fca2a843f0a44f480e9f39eeac6 Mon Sep 17 00:00:00 2001 From: Ren Date: Fri, 5 May 2023 00:06:35 +0300 Subject: [PATCH 24/59] * edit data.sql --- .../db/changelog/changeset/V4/data-V4.sql | 2076 +++++++++++++++++ .../db/changelog/changeset/V4/schema-V4.sql | 4 +- .../db/changelog/db.changelog-master.yaml | 4 +- 3 files changed, 2080 insertions(+), 4 deletions(-) create mode 100644 src/main/resources/db/changelog/changeset/V4/data-V4.sql diff --git a/src/main/resources/db/changelog/changeset/V4/data-V4.sql b/src/main/resources/db/changelog/changeset/V4/data-V4.sql new file mode 100644 index 0000000..4f08749 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V4/data-V4.sql @@ -0,0 +1,2076 @@ +--liquibase formatted sql +--changeset Ren:0 +-- Authority +insert into authority (id, authority) +values (1, 'TALENT'); +insert into authority (id, authority) +values (2, 'SPONSOR'); +-- Skill +insert into skill (id, skill) +values (1, 'Java Core'); +insert into skill (id, skill) +values (2, 'Spring Core'); +insert into skill (id, skill) +values (3, 'Spring boot'); +insert into skill (id, skill) +values (4, 'H2 Database'); +insert into skill (id, skill) +values (5, 'Spring Security'); +insert into skill (id, skill) +values (6, 'REST API'); +insert into skill (id, skill) +values (7, 'Git'); +insert into skill (id, skill) +values (8, 'Docker'); +insert into skill (id, skill) +values (9, 'Jira'); +insert into skill (id, skill) +values (10, 'JavaScript Core'); +insert into skill (id, skill) +values (11, 'React'); +insert into skill (id, skill) +values (12, 'Node.js'); +insert into skill (id, skill) +values (13, 'Angular'); +-- Talent +-- Serhii Soloviov +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_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 + ) + ); +-- Mykhailo Ordyntsev +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_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 + ) + ); +-- Denis Boyko +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_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 + ) + ); +-- Ihor Schurenko +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_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 + ) + ); +-- Dmytro Uzun +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_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 + ) + ); +-- Viktor Voloshko +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_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 + ) + ); +-- Olha Moiseienko +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_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 + ) + ); +-- Maxim Kiyashko +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_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 + ) + ); +-- Nikolaiev Oleksii +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_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 + ) + ); +-- Artem Lytvynenko +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_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 + ) + ); +-- Daniil Yevtukhov +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_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 + ) + ); +-- Ruslan Morozov +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_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 + ) + ); +-- Ihor Kopieichykov +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_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 + ) + ); +-- Sponsor +-- Maksym Khudoliy +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 + ) + ); +-- Oleksandr Butrym +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 + ) + ); +-- Olha Shutylieva +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 + ) + ); +-- Vladyslav Khrychov +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 + ) + ); +-- Kudos +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/V4/schema-V4.sql b/src/main/resources/db/changelog/changeset/V4/schema-V4.sql index a8ef942..b49be00 100644 --- a/src/main/resources/db/changelog/changeset/V4/schema-V4.sql +++ b/src/main/resources/db/changelog/changeset/V4/schema-V4.sql @@ -51,7 +51,7 @@ CREATE TABLE talent_skill ( CONSTRAINT pk_talent_skill PRIMARY KEY (proof_id, skill_id) ); CREATE TABLE skill ( - id BIGINT NOT NULL, + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, skill VARCHAR(30), CONSTRAINT pk_skill PRIMARY KEY (id) ); @@ -70,7 +70,7 @@ CREATE TABLE authority ( CONSTRAINT pk_authority PRIMARY KEY (id) ); CREATE TABLE user_authorities ( - authority_id BIGINT NOT NULL, + authority_id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, user_id BIGINT NOT NULL, CONSTRAINT pk_user_authorities PRIMARY KEY (authority_id, user_id) ); diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 5febddb..8c5dc7c 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -7,5 +7,5 @@ databaseChangeLog: file: db/changelog/changeset/V4/drop-V4.sql - include: file: db/changelog/changeset/V4/schema-V4.sql - # - include: - # file: db/changelog/changeset/V2/data-V4.sql + - include: + file: db/changelog/changeset/V4/data-V4.sql From b537a5efcf83c79304d6abe3c43e7eb371aa180c Mon Sep 17 00:00:00 2001 From: Ren Date: Fri, 5 May 2023 21:29:52 +0300 Subject: [PATCH 25/59] * add entity for Skills * edit existing entity: - remove TalentTalents and their references - add skills to TalentProof --- .../talent/mapper/TalentMapper.java | 4 +-- .../talent/model/entity/Skills.java | 34 +++++++++++++++++++ .../talent/model/entity/Talent.java | 5 ++- .../talent/model/entity/TalentProof.java | 7 ++++ .../talent/model/entity/TalentSkills.java | 25 ++++++++++++++ .../talent/model/entity/TalentTalents.java | 25 -------------- .../talent/model/request/EditTalent.java | 2 +- .../talent/repo/TalentRepository.java | 4 --- .../talent/service/TalentService.java | 21 ++++++------ 9 files changed, 81 insertions(+), 46 deletions(-) create mode 100644 src/main/java/com/provedcode/talent/model/entity/Skills.java create mode 100644 src/main/java/com/provedcode/talent/model/entity/TalentSkills.java delete mode 100644 src/main/java/com/provedcode/talent/model/entity/TalentTalents.java diff --git a/src/main/java/com/provedcode/talent/mapper/TalentMapper.java b/src/main/java/com/provedcode/talent/mapper/TalentMapper.java index 795ac61..336714e 100644 --- a/src/main/java/com/provedcode/talent/mapper/TalentMapper.java +++ b/src/main/java/com/provedcode/talent/mapper/TalentMapper.java @@ -14,10 +14,10 @@ public interface TalentMapper { @Mapping(target = "additionalInfo", expression = "java(talent.getTalentDescription() != null ? talent.getTalentDescription().getAdditionalInfo() : null)") @Mapping(target = "links", expression = "java(talent.getTalentLinks().stream().map(l -> l.getLink()).toList())") @Mapping(target = "contacts", expression = "java(talent.getTalentContacts().stream().map(c -> c.getContact()).toList())") - @Mapping(target = "talents", expression = "java(talent.getTalentTalents().stream().map(t -> t.getTalentName()).toList())") +// @Mapping(target = "talents", expression = "java(talent.getTalentTalents().stream().map(t -> t.getTalentName()).toList())") @Mapping(target = "attachedFiles", expression = "java(talent.getTalentAttachedFiles().stream().map(a -> a.getAttachedFile()).toList())") FullTalentDTO talentToFullTalentDTO(Talent talent); - @Mapping(target = "talents", expression = "java(talent.getTalentTalents().stream().map(t -> t.getTalentName()).toList())") +// @Mapping(target = "talents", expression = "java(talent.getTalentTalents().stream().map(t -> t.getTalentName()).toList())") ShortTalentDTO talentToShortTalentDTO(Talent talent); } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/model/entity/Skills.java b/src/main/java/com/provedcode/talent/model/entity/Skills.java new file mode 100644 index 0000000..009d911 --- /dev/null +++ b/src/main/java/com/provedcode/talent/model/entity/Skills.java @@ -0,0 +1,34 @@ +package com.provedcode.talent.model.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.Hibernate; + +import java.util.Objects; + +@Getter +@Setter +@Entity +@Table(name = "skills") +public class Skills { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", nullable = false) + private Long id; + @Column(name = "skill", length = 30) + private String skill; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false; + Skills skills = (Skills) o; + return getId() != null && Objects.equals(getId(), skills.getId()); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } +} \ No newline at end of file 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 49fdcbf..46ca5db 100644 --- a/src/main/java/com/provedcode/talent/model/entity/Talent.java +++ b/src/main/java/com/provedcode/talent/model/entity/Talent.java @@ -1,6 +1,5 @@ package com.provedcode.talent.model.entity; -import com.provedcode.kudos.model.entity.Kudos; import jakarta.persistence.*; import jakarta.validation.constraints.NotEmpty; import lombok.*; @@ -42,8 +41,8 @@ public class Talent { private TalentDescription talentDescription; @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) private List talentLinks = new ArrayList<>(); - @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) - private List talentTalents = new ArrayList<>(); +// @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) +// private List talentTalents = new ArrayList<>(); @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) private List talentContacts = new ArrayList<>(); @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) diff --git a/src/main/java/com/provedcode/talent/model/entity/TalentProof.java b/src/main/java/com/provedcode/talent/model/entity/TalentProof.java index 0650310..b04ca20 100644 --- a/src/main/java/com/provedcode/talent/model/entity/TalentProof.java +++ b/src/main/java/com/provedcode/talent/model/entity/TalentProof.java @@ -10,7 +10,9 @@ import org.hibernate.validator.constraints.URL; import java.time.LocalDateTime; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; @Accessors(chain = true) @NoArgsConstructor @@ -41,4 +43,9 @@ public class TalentProof { private LocalDateTime created; @OneToMany(fetch = FetchType.EAGER, mappedBy = "proof", cascade = CascadeType.ALL, orphanRemoval = true) private List kudos; + @ManyToMany + @JoinTable(name = "talent_skills", + joinColumns = @JoinColumn(name = "proof_id"), + inverseJoinColumns = @JoinColumn(name = "skill_id")) + private Set skillses = new LinkedHashSet<>(); } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/model/entity/TalentSkills.java b/src/main/java/com/provedcode/talent/model/entity/TalentSkills.java new file mode 100644 index 0000000..f6a10cc --- /dev/null +++ b/src/main/java/com/provedcode/talent/model/entity/TalentSkills.java @@ -0,0 +1,25 @@ +//package com.provedcode.talent.model.entity; +// +//import jakarta.persistence.*; +//import jakarta.validation.constraints.NotNull; +//import lombok.*; +// +//@NoArgsConstructor +//@AllArgsConstructor +//@Builder +//@Getter +//@Setter +//@Entity +//@Table(name = "talent_talents") +//public class TalentSkills { +// @Id +// @GeneratedValue(strategy = GenerationType.IDENTITY) +// @Column(name = "id", nullable = false) +// private Long id; +// @NotNull +// @ManyToOne +// @JoinColumn(name = "talent_id", updatable = false) +// private Talent talent; +// @Column(name = "talent_name") +// private String talentName; +//} \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/model/entity/TalentTalents.java b/src/main/java/com/provedcode/talent/model/entity/TalentTalents.java deleted file mode 100644 index 2c087b0..0000000 --- a/src/main/java/com/provedcode/talent/model/entity/TalentTalents.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.provedcode.talent.model.entity; - -import jakarta.persistence.*; -import jakarta.validation.constraints.NotNull; -import lombok.*; - -@NoArgsConstructor -@AllArgsConstructor -@Builder -@Getter -@Setter -@Entity -@Table(name = "talent_talents") -public class TalentTalents { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", nullable = false) - private Long id; - @NotNull - @ManyToOne - @JoinColumn(name = "talent_id", updatable = false) - private Talent talent; - @Column(name = "talent_name") - private String talentName; -} \ 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 cc3dbc1..d8fac72 100644 --- a/src/main/java/com/provedcode/talent/model/request/EditTalent.java +++ b/src/main/java/com/provedcode/talent/model/request/EditTalent.java @@ -17,7 +17,7 @@ public record EditTalent( @JsonProperty("additional_info") String additionalInfo, String bio, - List talents, +// List talents, @UrlList List links, List contacts, diff --git a/src/main/java/com/provedcode/talent/repo/TalentRepository.java b/src/main/java/com/provedcode/talent/repo/TalentRepository.java index e0359c3..b2bac22 100644 --- a/src/main/java/com/provedcode/talent/repo/TalentRepository.java +++ b/src/main/java/com/provedcode/talent/repo/TalentRepository.java @@ -1,11 +1,7 @@ package com.provedcode.talent.repo; import com.provedcode.talent.model.entity.Talent; -import com.provedcode.talent.model.entity.TalentTalents; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; -import org.springframework.transaction.annotation.Transactional; public interface TalentRepository extends JpaRepository { } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/service/TalentService.java b/src/main/java/com/provedcode/talent/service/TalentService.java index 48a854d..fb35aa9 100644 --- a/src/main/java/com/provedcode/talent/service/TalentService.java +++ b/src/main/java/com/provedcode/talent/service/TalentService.java @@ -56,7 +56,7 @@ public Talent editTalent(long id, EditTalent editTalent, Authentication authenti Talent editableTalent = talent.get(); TalentDescription editableTalentDescription = editableTalent.getTalentDescription(); - List editableTalentTalents = editableTalent.getTalentTalents(); +// List editableTalentTalents = editableTalent.getTalentTalents(); List editableTalentLinks = editableTalent.getTalentLinks(); List editableTalentContacts = editableTalent.getTalentContacts(); List editableTalentAttachedFiles = editableTalent.getTalentAttachedFiles(); @@ -88,14 +88,14 @@ public Talent editTalent(long id, EditTalent editTalent, Authentication authenti } 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.talents() != null) { +// editableTalentTalents.clear(); +// editableTalentTalents.addAll(editTalent.talents().stream().map(s -> TalentSkills.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() @@ -144,8 +144,7 @@ public 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) + 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 From 30156ca3d316912322e5650cf783699dfeacdb73 Mon Sep 17 00:00:00 2001 From: Ren <75202059+LordRenDS@users.noreply.github.com> Date: Sat, 6 May 2023 14:06:36 +0300 Subject: [PATCH 26/59] S4.1T1-3 (#118) * AWS update * US1T3 FINISHED! --------- Co-authored-by: Maslyna --- .../com/provedcode/aws/service/S3Service.java | 3 +- .../controller/TalentSkillsController.java | 28 ++++++++ .../talent/model/dto/ProofSkillsDTO.java | 13 ++++ .../talent/model/entity/Skills.java | 2 +- .../talent/model/entity/TalentProof.java | 4 +- .../talent/repo/SkillsRepository.java | 7 ++ .../talent/service/TalentSkillsService.java | 64 +++++++++++++++++++ 7 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/provedcode/talent/controller/TalentSkillsController.java create mode 100644 src/main/java/com/provedcode/talent/model/dto/ProofSkillsDTO.java create mode 100644 src/main/java/com/provedcode/talent/repo/SkillsRepository.java create mode 100644 src/main/java/com/provedcode/talent/service/TalentSkillsService.java diff --git a/src/main/java/com/provedcode/aws/service/S3Service.java b/src/main/java/com/provedcode/aws/service/S3Service.java index 61414c9..2ec385f 100644 --- a/src/main/java/com/provedcode/aws/service/S3Service.java +++ b/src/main/java/com/provedcode/aws/service/S3Service.java @@ -125,7 +125,8 @@ private String getFullPath(String fileType, String userLogin) { } private String getFileType(MultipartFile file) { - return file.getContentType().split("/")[1]; + String fileName = file.getOriginalFilename(); + return fileName != null ? fileName.substring(fileName.lastIndexOf('.') + 1) : null; } private File convertMultiPartToFile(MultipartFile file) diff --git a/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java b/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java new file mode 100644 index 0000000..35d9acb --- /dev/null +++ b/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java @@ -0,0 +1,28 @@ +package com.provedcode.talent.controller; + +import com.provedcode.talent.model.dto.ProofSkillsDTO; +import com.provedcode.talent.service.TalentSkillsService; +import jakarta.validation.Valid; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.Authentication; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +@Slf4j +@Validated +@AllArgsConstructor + +@RestController +@RequestMapping("/api/v4/talents") +public class TalentSkillsController { + TalentSkillsService talentSkillsService; + + @PostMapping("/{talent-id}/proofs/{proof-id}/skills") + void addSkillOnProof(@PathVariable("talent-id") long talentId, + @PathVariable("proof-id") long proofId, + @RequestBody @Valid ProofSkillsDTO skills, + Authentication authentication) { + talentSkillsService.addSkillsOnProof(talentId, proofId, skills, authentication); + } +} diff --git a/src/main/java/com/provedcode/talent/model/dto/ProofSkillsDTO.java b/src/main/java/com/provedcode/talent/model/dto/ProofSkillsDTO.java new file mode 100644 index 0000000..d65e05e --- /dev/null +++ b/src/main/java/com/provedcode/talent/model/dto/ProofSkillsDTO.java @@ -0,0 +1,13 @@ +package com.provedcode.talent.model.dto; + +import jakarta.validation.constraints.NotEmpty; +import lombok.Builder; + +import java.util.List; + +@Builder +public record ProofSkillsDTO( + @NotEmpty + List skills +) { +} diff --git a/src/main/java/com/provedcode/talent/model/entity/Skills.java b/src/main/java/com/provedcode/talent/model/entity/Skills.java index 009d911..2bc6d0f 100644 --- a/src/main/java/com/provedcode/talent/model/entity/Skills.java +++ b/src/main/java/com/provedcode/talent/model/entity/Skills.java @@ -10,7 +10,7 @@ @Getter @Setter @Entity -@Table(name = "skills") +@Table(name = "skill") public class Skills { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/provedcode/talent/model/entity/TalentProof.java b/src/main/java/com/provedcode/talent/model/entity/TalentProof.java index b04ca20..549dbea 100644 --- a/src/main/java/com/provedcode/talent/model/entity/TalentProof.java +++ b/src/main/java/com/provedcode/talent/model/entity/TalentProof.java @@ -44,8 +44,8 @@ public class TalentProof { @OneToMany(fetch = FetchType.EAGER, mappedBy = "proof", cascade = CascadeType.ALL, orphanRemoval = true) private List kudos; @ManyToMany - @JoinTable(name = "talent_skills", + @JoinTable(name = "talent_skill", joinColumns = @JoinColumn(name = "proof_id"), inverseJoinColumns = @JoinColumn(name = "skill_id")) - private Set skillses = new LinkedHashSet<>(); + private Set skills = new LinkedHashSet<>(); } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/repo/SkillsRepository.java b/src/main/java/com/provedcode/talent/repo/SkillsRepository.java new file mode 100644 index 0000000..0f17989 --- /dev/null +++ b/src/main/java/com/provedcode/talent/repo/SkillsRepository.java @@ -0,0 +1,7 @@ +package com.provedcode.talent.repo; + +import com.provedcode.talent.model.entity.Skills; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface SkillsRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/service/TalentSkillsService.java b/src/main/java/com/provedcode/talent/service/TalentSkillsService.java new file mode 100644 index 0000000..7fdd351 --- /dev/null +++ b/src/main/java/com/provedcode/talent/service/TalentSkillsService.java @@ -0,0 +1,64 @@ +package com.provedcode.talent.service; + +import com.provedcode.talent.model.ProofStatus; +import com.provedcode.talent.model.dto.ProofSkillsDTO; +import com.provedcode.talent.model.entity.Skills; +import com.provedcode.talent.model.entity.TalentProof; +import com.provedcode.talent.repo.SkillsRepository; +import com.provedcode.talent.repo.TalentProofRepository; +import com.provedcode.talent.repo.TalentRepository; +import com.provedcode.user.model.entity.UserInfo; +import com.provedcode.user.repo.UserInfoRepository; +import lombok.AllArgsConstructor; +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.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.BiConsumer; + +import static org.springframework.http.HttpStatus.*; + +@Transactional +@Service +@AllArgsConstructor +public class TalentSkillsService { + SkillsRepository skillsRepository; + TalentRepository talentRepository; + UserInfoRepository userInfoRepository; + TalentProofRepository talentProofRepository; + + static BiConsumer isValidUserEditTalent = (talentId, userInfo) -> { + if (!userInfo.getTalent().getId().equals(talentId)) { + throw new ResponseStatusException(CONFLICT, "you can`t change another talent"); + } + }; + + public void addSkillsOnProof(long talentId, long proofId, ProofSkillsDTO skills, Authentication authentication) { + if (!talentRepository.existsById(talentId)) { + throw new ResponseStatusException(NOT_FOUND, "talent with id = %s not found".formatted(talentId)); + } + UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); + TalentProof talentProof = talentProofRepository.findById(proofId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "proof with id = %s not found".formatted(proofId))); + if (!talentProof.getStatus().equals(ProofStatus.DRAFT)) { + throw new ResponseStatusException(CONFLICT, "proof status must be DRAFT"); + } + + isValidUserEditTalent.accept(talentId, userInfo); + if (skills.skills().stream().anyMatch(i -> !skillsRepository.existsById(i))) { + throw new ResponseStatusException(BAD_REQUEST, "no such skill with id"); + } + + Set skillsSet = new HashSet<>(skillsRepository.findAllById(skills.skills())); + + talentProof.getSkills().addAll(skillsSet); + talentProofRepository.save(talentProof); + } + + +} From d24784e17984054ec77b2dffe553f1b9f599048d Mon Sep 17 00:00:00 2001 From: Denis973 <46610112+Denis973@users.noreply.github.com> Date: Sun, 7 May 2023 14:27:21 +0300 Subject: [PATCH 27/59] S4.1 tasks 4 5 (#119) * add getAllSkillsOnProof * add deleteSkillOnProof --- .../controller/TalentSkillsController.java | 17 ++++++ .../talent/model/dto/SkillsOnProofDTO.java | 12 ++++ .../talent/service/TalentSkillsService.java | 55 ++++++++++++++++++- .../db/changelog/changeset/V4/data-V4.1.sql | 19 +++++++ .../db/changelog/db.changelog-master.yaml | 2 + 5 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/provedcode/talent/model/dto/SkillsOnProofDTO.java create mode 100644 src/main/resources/db/changelog/changeset/V4/data-V4.1.sql diff --git a/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java b/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java index 35d9acb..bc0a57e 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java @@ -1,10 +1,12 @@ package com.provedcode.talent.controller; import com.provedcode.talent.model.dto.ProofSkillsDTO; +import com.provedcode.talent.model.dto.SkillsOnProofDTO; import com.provedcode.talent.service.TalentSkillsService; import jakarta.validation.Valid; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +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.*; @@ -25,4 +27,19 @@ void addSkillOnProof(@PathVariable("talent-id") long talentId, Authentication authentication) { talentSkillsService.addSkillsOnProof(talentId, proofId, skills, authentication); } + + @GetMapping("/{talent-id}/proofs/{proof-id}/skills") + SkillsOnProofDTO getAllSkillsOnProof(@PathVariable("talent-id") long talentId, + @PathVariable("proof-id") long proofId, + Authentication authentication) { + return talentSkillsService.getAllSkillsOnProof(talentId, proofId, authentication); + } + @PreAuthorize("hasRole('TALENT')") + @DeleteMapping("/{talent-id}/proofs/{proof-id}/skills/{skill-id}") + void deleteSkillOnProof(@PathVariable("talent-id") long talentId, + @PathVariable("proof-id") long proofId, + @PathVariable("skill-id") long skillId, + Authentication authentication) { + talentSkillsService.deleteSkillOnProof(talentId, proofId, skillId, authentication); + } } diff --git a/src/main/java/com/provedcode/talent/model/dto/SkillsOnProofDTO.java b/src/main/java/com/provedcode/talent/model/dto/SkillsOnProofDTO.java new file mode 100644 index 0000000..f70ff5e --- /dev/null +++ b/src/main/java/com/provedcode/talent/model/dto/SkillsOnProofDTO.java @@ -0,0 +1,12 @@ +package com.provedcode.talent.model.dto; + +import com.provedcode.talent.model.entity.Skills; +import lombok.Builder; + +import java.util.Set; + +@Builder +public record SkillsOnProofDTO( + Set skills +) { +} diff --git a/src/main/java/com/provedcode/talent/service/TalentSkillsService.java b/src/main/java/com/provedcode/talent/service/TalentSkillsService.java index 7fdd351..0fed22f 100644 --- a/src/main/java/com/provedcode/talent/service/TalentSkillsService.java +++ b/src/main/java/com/provedcode/talent/service/TalentSkillsService.java @@ -2,7 +2,9 @@ import com.provedcode.talent.model.ProofStatus; import com.provedcode.talent.model.dto.ProofSkillsDTO; +import com.provedcode.talent.model.dto.SkillsOnProofDTO; import com.provedcode.talent.model.entity.Skills; +import com.provedcode.talent.model.entity.Talent; import com.provedcode.talent.model.entity.TalentProof; import com.provedcode.talent.repo.SkillsRepository; import com.provedcode.talent.repo.TalentProofRepository; @@ -16,7 +18,6 @@ import org.springframework.web.server.ResponseStatusException; import java.util.HashSet; -import java.util.List; import java.util.Set; import java.util.function.BiConsumer; @@ -60,5 +61,57 @@ public void addSkillsOnProof(long talentId, long proofId, ProofSkillsDTO skills, talentProofRepository.save(talentProof); } + @Transactional(readOnly = true) + public SkillsOnProofDTO getAllSkillsOnProof(long talentId, long proofId, Authentication authentication) { + TalentProof talentProof = talentProofRepository.findById(proofId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "proof with id = %s not found".formatted(proofId))); + Talent talent = talentRepository.findById(talentId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "talent with id = %s not found".formatted(talentId))); + if (!talent.getId().equals(talentProof.getTalent().getId())) { + throw new ResponseStatusException(BAD_REQUEST, + "talentId with id = %s and proofId with id = %s do not match".formatted(talentId, proofId)); + } + + if (talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { + return SkillsOnProofDTO.builder().skills(talentProof.getSkills()).build(); + } else if (authentication != null) { + UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); + if (userInfo.getTalent().getId().equals(talentProof.getTalent().getId())) { + return SkillsOnProofDTO.builder().skills(talentProof.getSkills()).build(); + } else { + throw new ResponseStatusException(FORBIDDEN, "you can't see proofs in DRAFT and HIDDEN status"); + } + } else { + throw new ResponseStatusException(FORBIDDEN, "you can't see proofs in DRAFT and HIDDEN status"); + } + } + public void deleteSkillOnProof(long talentId, long proofId, long skillId, Authentication authentication) { + Talent talent = talentRepository.findById(talentId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "talent with id = %s not found".formatted(talentId))); + UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); + TalentProof talentProof = talentProofRepository.findById(proofId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "proof with id = %s not found".formatted(proofId))); + if (!talentProof.getStatus().equals(ProofStatus.DRAFT)) { + throw new ResponseStatusException(CONFLICT, "proof status must be DRAFT"); + } + if (!talent.getId().equals(talentProof.getTalent().getId())) { + throw new ResponseStatusException(BAD_REQUEST, + "talentId with id = %s and proofId with id = %s do not match".formatted(talentId, proofId)); + } + isValidUserEditTalent.accept(talentId, userInfo); + Skills skills = skillsRepository.findById(skillId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "skill with id = %s not found".formatted(skillId))); + if (!talentProof.getSkills().contains(skills)) { + throw new ResponseStatusException(NOT_FOUND, + "you dont have skill with id = %s on proof with id = %s".formatted(skillId, proofId)); + } + talentProof.getSkills().remove(skills); + } } diff --git a/src/main/resources/db/changelog/changeset/V4/data-V4.1.sql b/src/main/resources/db/changelog/changeset/V4/data-V4.1.sql new file mode 100644 index 0000000..9261f0d --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V4/data-V4.1.sql @@ -0,0 +1,19 @@ +--liquibase formatted sql +--changeset dennis:3 +-- Skill +INSERT INTO talent_skill (proof_id, skill_id) +VALUES (1, 1); +INSERT INTO talent_skill (proof_id, skill_id) +VALUES (1, 2); +INSERT INTO talent_skill (proof_id, skill_id) +VALUES (1, 3); +INSERT INTO talent_skill (proof_id, skill_id) +VALUES (1, 4); +INSERT INTO talent_skill (proof_id, skill_id) +VALUES (4, 1); +INSERT INTO talent_skill (proof_id, skill_id) +VALUES (5, 2); +INSERT INTO talent_skill (proof_id, skill_id) +VALUES (6, 3); + + diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 8c5dc7c..102ca3c 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -9,3 +9,5 @@ databaseChangeLog: file: db/changelog/changeset/V4/schema-V4.sql - include: file: db/changelog/changeset/V4/data-V4.sql + - include: + file: db/changelog/changeset/V4/data-V4.1.sql From a6268c6b19211b5117376bb5b0133af10579e353 Mon Sep 17 00:00:00 2001 From: Mykhailo Ordyntsev <102993813+Maslyna@users.noreply.github.com> Date: Tue, 9 May 2023 19:28:53 +0200 Subject: [PATCH 28/59] S4.1S2T1 (#121) * Story 2 completed: filter by words * bugfix * bug fix in getTalentProofs --------- Co-authored-by: Denis Boyko --- .../aws/scheduler/UpdateScheduler.java | 1 - .../com/provedcode/config/SecurityConfig.java | 1 + .../talent/controller/SkillController.java | 28 +++++++++++++++++++ .../controller/TalentProofController.java | 2 +- .../provedcode/talent/mapper/SkillMapper.java | 12 ++++++++ .../provedcode/talent/model/dto/SkillDTO.java | 7 +++++ .../talent/repo/SkillsRepository.java | 5 ++++ .../talent/service/SkillsService.java | 25 +++++++++++++++++ .../talent/service/TalentProofService.java | 11 +++++--- .../talent/service/TalentSkillsService.java | 12 ++++++-- 10 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/provedcode/talent/controller/SkillController.java create mode 100644 src/main/java/com/provedcode/talent/mapper/SkillMapper.java create mode 100644 src/main/java/com/provedcode/talent/model/dto/SkillDTO.java create mode 100644 src/main/java/com/provedcode/talent/service/SkillsService.java diff --git a/src/main/java/com/provedcode/aws/scheduler/UpdateScheduler.java b/src/main/java/com/provedcode/aws/scheduler/UpdateScheduler.java index c9988dc..acb5b40 100644 --- a/src/main/java/com/provedcode/aws/scheduler/UpdateScheduler.java +++ b/src/main/java/com/provedcode/aws/scheduler/UpdateScheduler.java @@ -11,7 +11,6 @@ @Transactional @AllArgsConstructor public class UpdateScheduler { - FileService fileService; TalentRepository talentRepository; diff --git a/src/main/java/com/provedcode/config/SecurityConfig.java b/src/main/java/com/provedcode/config/SecurityConfig.java index 1997071..dff7a62 100644 --- a/src/main/java/com/provedcode/config/SecurityConfig.java +++ b/src/main/java/com/provedcode/config/SecurityConfig.java @@ -53,6 +53,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .requestMatchers(antMatcher("/api/*/talents/**")).permitAll() .requestMatchers(antMatcher("/api/*/sponsors/**")).permitAll() .requestMatchers(antMatcher("/api/*/login")).permitAll() + .requestMatchers(antMatcher("/api/*/skills")).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/talent/controller/SkillController.java b/src/main/java/com/provedcode/talent/controller/SkillController.java new file mode 100644 index 0000000..91297db --- /dev/null +++ b/src/main/java/com/provedcode/talent/controller/SkillController.java @@ -0,0 +1,28 @@ +package com.provedcode.talent.controller; + +import com.provedcode.talent.model.dto.SkillDTO; +import com.provedcode.talent.service.SkillsService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@Slf4j +@Validated +@AllArgsConstructor + +@RestController +@RequestMapping("/api/v4") +public class SkillController { + SkillsService skillsService; + + @GetMapping("/skills") + List getFilteredSkills(@RequestParam(value = "filter-by", required = false, defaultValue = "") String filterBy) { + return skillsService.getFilteredSkills(filterBy); + } +} diff --git a/src/main/java/com/provedcode/talent/controller/TalentProofController.java b/src/main/java/com/provedcode/talent/controller/TalentProofController.java index 2b5e769..25492f0 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentProofController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentProofController.java @@ -51,7 +51,7 @@ ProofDTO getTalentProof(@PathVariable(value = "proof-id") long proofId, @GetTalentInformationWithProofsApiDoc @GetMapping("/{talent-id}/proofs") - @PreAuthorize("hasRole('TALENT')") + @PreAuthorize("hasAnyRole('TALENT','SPONSOR')") FullProofDTO getTalentInformationWithProofs(Authentication authentication, @PathVariable("talent-id") Long talentId, @RequestParam(value = "page", defaultValue = "0") @PositiveOrZero Integer page, diff --git a/src/main/java/com/provedcode/talent/mapper/SkillMapper.java b/src/main/java/com/provedcode/talent/mapper/SkillMapper.java new file mode 100644 index 0000000..74c30b6 --- /dev/null +++ b/src/main/java/com/provedcode/talent/mapper/SkillMapper.java @@ -0,0 +1,12 @@ +package com.provedcode.talent.mapper; + +import com.provedcode.talent.model.dto.SkillDTO; +import com.provedcode.talent.model.entity.Skills; +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.mapstruct.ReportingPolicy; + +@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING) +public interface SkillMapper { + SkillDTO skillToSkillDTO(Skills skills); +} diff --git a/src/main/java/com/provedcode/talent/model/dto/SkillDTO.java b/src/main/java/com/provedcode/talent/model/dto/SkillDTO.java new file mode 100644 index 0000000..f93fe25 --- /dev/null +++ b/src/main/java/com/provedcode/talent/model/dto/SkillDTO.java @@ -0,0 +1,7 @@ +package com.provedcode.talent.model.dto; + +public record SkillDTO( + Long id, + String skill +) { +} diff --git a/src/main/java/com/provedcode/talent/repo/SkillsRepository.java b/src/main/java/com/provedcode/talent/repo/SkillsRepository.java index 0f17989..384d489 100644 --- a/src/main/java/com/provedcode/talent/repo/SkillsRepository.java +++ b/src/main/java/com/provedcode/talent/repo/SkillsRepository.java @@ -2,6 +2,11 @@ import com.provedcode.talent.model.entity.Skills; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; public interface SkillsRepository extends JpaRepository { + @Query("select s from Skills s where upper(s.skill) like upper(concat('%', ?1, '%'))") + List findBySkillContainsIgnoreCase(String skill); } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/service/SkillsService.java b/src/main/java/com/provedcode/talent/service/SkillsService.java new file mode 100644 index 0000000..9ae77c4 --- /dev/null +++ b/src/main/java/com/provedcode/talent/service/SkillsService.java @@ -0,0 +1,25 @@ +package com.provedcode.talent.service; + +import com.provedcode.talent.mapper.SkillMapper; +import com.provedcode.talent.model.dto.SkillDTO; +import com.provedcode.talent.repo.SkillsRepository; +import com.provedcode.talent.repo.TalentRepository; +import com.provedcode.user.repo.UserInfoRepository; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@AllArgsConstructor +public class SkillsService { + SkillsRepository skillsRepository; + TalentRepository talentRepository; + UserInfoRepository userInfoRepository; + SkillMapper skillMapper; + + public List getFilteredSkills(String filterBy) { + return skillsRepository.findBySkillContainsIgnoreCase(filterBy).stream() + .map(skillMapper::skillToSkillDTO).toList(); + } +} diff --git a/src/main/java/com/provedcode/talent/service/TalentProofService.java b/src/main/java/com/provedcode/talent/service/TalentProofService.java index 3880350..9c92069 100644 --- a/src/main/java/com/provedcode/talent/service/TalentProofService.java +++ b/src/main/java/com/provedcode/talent/service/TalentProofService.java @@ -11,6 +11,7 @@ import com.provedcode.talent.repo.TalentProofRepository; import com.provedcode.talent.repo.TalentRepository; import com.provedcode.talent.utill.ValidateTalentForCompliance; +import com.provedcode.user.model.Role; import com.provedcode.user.model.entity.UserInfo; import com.provedcode.user.repo.UserInfoRepository; import lombok.AllArgsConstructor; @@ -29,6 +30,7 @@ import java.net.URI; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.Objects; import java.util.Optional; import static org.springframework.http.HttpStatus.FORBIDDEN; @@ -81,14 +83,15 @@ public FullProofDTO getTalentProofs(Long talentId, Integer page, Integer size, S talentId))); UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); - Page proofs; PageRequest pageRequest = PageRequest.of(page, size, Sort.Direction.valueOf(direction.toUpperCase()), sortProperties ); - if (!userInfo.getTalent().getId().equals(talentId)) { + Page proofs = talentProofRepository.findByTalentId(talentId, pageRequest); + if (authentication.getAuthorities().contains(Role.SPONSOR)) { + proofs = talentProofRepository.findByTalentIdAndStatus(talentId, ProofStatus.PUBLISHED, pageRequest); + } + if (userInfo.getTalent() != null && !userInfo.getTalent().getId().equals(talentId)) { proofs = talentProofRepository.findByTalentIdAndStatus(talentId, ProofStatus.PUBLISHED, pageRequest); - } else { - proofs = talentProofRepository.findByTalentId(talentId, pageRequest); } return FullProofDTO.builder() .id(talent.getId()) diff --git a/src/main/java/com/provedcode/talent/service/TalentSkillsService.java b/src/main/java/com/provedcode/talent/service/TalentSkillsService.java index 0fed22f..81841b0 100644 --- a/src/main/java/com/provedcode/talent/service/TalentSkillsService.java +++ b/src/main/java/com/provedcode/talent/service/TalentSkillsService.java @@ -51,11 +51,17 @@ public void addSkillsOnProof(long talentId, long proofId, ProofSkillsDTO skills, } isValidUserEditTalent.accept(talentId, userInfo); - if (skills.skills().stream().anyMatch(i -> !skillsRepository.existsById(i))) { - throw new ResponseStatusException(BAD_REQUEST, "no such skill with id"); - } + skills.skills().forEach(skillId -> { + if (!skillsRepository.existsById(skillId)) + throw new ResponseStatusException(NOT_FOUND, "no such skill with id = " + skillId); + }); Set skillsSet = new HashSet<>(skillsRepository.findAllById(skills.skills())); + talentProof.getSkills().forEach(skill -> { + if (skillsSet.contains(skill)) + throw new ResponseStatusException(CONFLICT, + "skill with id = %s already on skill".formatted(skill.getId())); + }); talentProof.getSkills().addAll(skillsSet); talentProofRepository.save(talentProof); From 28309df846449ac1507a559367da1acad433cc97 Mon Sep 17 00:00:00 2001 From: Ren <75202059+LordRenDS@users.noreply.github.com> Date: Thu, 11 May 2023 21:35:36 +0300 Subject: [PATCH 29/59] S4.2US1T1 (#129) * bugfix getProofKudos() in KudosService * Refactor schema and data to enable association of skills with proofs and talents separately Previously, tables were created to relate talent skills with talent proofs. This change separates the association of skills with talent proofs and talent. The `talent_skill` table now only links a talent with a skill, while a new `proof_skill` table relates a proof with a skill. This change also includes modifications to the `schema-V4.sql` file: adding the new `proof_skill` table, setting primary keys, and creating foreign key constraints. * Refactor entity classes and add many-to-many relationships for talents and skills The entity classes 'Skills', 'Talent' and 'TalentProof' have been refactored to add many-to-many relationships between 'Talent' and 'Skills'. The existing 'talent_skills' table has been removed and a new table 'proof_skill' has been added to handle the many-to-many relation. * Rename TalentSkillsService to ProofSkillsService and remove TalentSkills entity - Rename TalentSkillsService to ProofSkillsService for clarity - Remove TalentSkills entity which is no longer used --- .../kudos/service/KudosService.java | 67 +++++++++---------- .../controller/TalentSkillsController.java | 4 +- .../talent/model/entity/Skills.java | 27 ++++++-- .../talent/model/entity/Talent.java | 37 +++++++--- .../talent/model/entity/TalentProof.java | 40 ++++++++--- .../talent/model/entity/TalentSkills.java | 25 ------- ...lsService.java => ProofSkillsService.java} | 2 +- .../db/changelog/changeset/V4/data-V4.1.sql | 23 ++++--- .../db/changelog/changeset/V4/schema-V4.sql | 17 +++-- 9 files changed, 139 insertions(+), 103 deletions(-) delete mode 100644 src/main/java/com/provedcode/talent/model/entity/TalentSkills.java rename src/main/java/com/provedcode/talent/service/{TalentSkillsService.java => ProofSkillsService.java} (99%) diff --git a/src/main/java/com/provedcode/kudos/service/KudosService.java b/src/main/java/com/provedcode/kudos/service/KudosService.java index f506391..599999b 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -89,44 +89,39 @@ public KudosAmount getKudosForSponsor(long sponsorId, Authentication authenticat @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))); + 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.getTalent().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); + Long countOfAllKudos = talentProof.getKudos().stream() + .map(Kudos::getAmount) + .reduce(0L, (prev, next) -> prev + next); - 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 - )); + 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(); - } + return KudosAmountWithSponsor.builder() + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(kudosFromSponsor) + .build(); + } else { + return KudosAmountWithSponsor.builder() + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(null).build(); + } } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java b/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java index bc0a57e..e477280 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java @@ -2,7 +2,7 @@ import com.provedcode.talent.model.dto.ProofSkillsDTO; import com.provedcode.talent.model.dto.SkillsOnProofDTO; -import com.provedcode.talent.service.TalentSkillsService; +import com.provedcode.talent.service.ProofSkillsService; import jakarta.validation.Valid; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -18,7 +18,7 @@ @RestController @RequestMapping("/api/v4/talents") public class TalentSkillsController { - TalentSkillsService talentSkillsService; + ProofSkillsService talentSkillsService; @PostMapping("/{talent-id}/proofs/{proof-id}/skills") void addSkillOnProof(@PathVariable("talent-id") long talentId, diff --git a/src/main/java/com/provedcode/talent/model/entity/Skills.java b/src/main/java/com/provedcode/talent/model/entity/Skills.java index 2bc6d0f..a87af65 100644 --- a/src/main/java/com/provedcode/talent/model/entity/Skills.java +++ b/src/main/java/com/provedcode/talent/model/entity/Skills.java @@ -1,11 +1,20 @@ package com.provedcode.talent.model.entity; -import jakarta.persistence.*; -import lombok.Getter; -import lombok.Setter; +import java.util.LinkedHashSet; +import java.util.Objects; +import java.util.Set; + import org.hibernate.Hibernate; -import java.util.Objects; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.Table; +import lombok.Getter; +import lombok.Setter; @Getter @Setter @@ -18,11 +27,17 @@ public class Skills { private Long id; @Column(name = "skill", length = 30) private String skill; + @ManyToMany(mappedBy = "skills") + private Set talentProofs = new LinkedHashSet<>(); + @ManyToMany(mappedBy = "skills") + private Set talents = new LinkedHashSet<>(); @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false; + if (this == o) + return true; + if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) + return false; Skills skills = (Skills) o; return getId() != null && Objects.equals(getId(), skills.getId()); } 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 46ca5db..c093e16 100644 --- a/src/main/java/com/provedcode/talent/model/entity/Talent.java +++ b/src/main/java/com/provedcode/talent/model/entity/Talent.java @@ -1,13 +1,31 @@ package com.provedcode.talent.model.entity; -import jakarta.persistence.*; -import jakarta.validation.constraints.NotEmpty; -import lombok.*; -import lombok.experimental.Accessors; -import org.hibernate.validator.constraints.URL; - import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; + +import org.hibernate.validator.constraints.URL; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.validation.constraints.NotEmpty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; @Builder @Accessors(chain = true) @@ -41,12 +59,15 @@ public class Talent { private TalentDescription talentDescription; @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) private List talentLinks = new ArrayList<>(); -// @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) -// private List talentTalents = new ArrayList<>(); @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) private List talentContacts = new ArrayList<>(); @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) private List talentAttachedFiles = new ArrayList<>(); @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) private List talentProofs = new ArrayList<>(); + @ManyToMany + @JoinTable(name = "talent_skills", + joinColumns = @JoinColumn(name = "talent_id"), + inverseJoinColumns = @JoinColumn(name = "skill_id")) + private Set skills = new LinkedHashSet<>(); } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/model/entity/TalentProof.java b/src/main/java/com/provedcode/talent/model/entity/TalentProof.java index 549dbea..a4ffd86 100644 --- a/src/main/java/com/provedcode/talent/model/entity/TalentProof.java +++ b/src/main/java/com/provedcode/talent/model/entity/TalentProof.java @@ -1,18 +1,38 @@ package com.provedcode.talent.model.entity; +import java.time.LocalDateTime; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.validator.constraints.URL; + import com.provedcode.kudos.model.entity.Kudos; import com.provedcode.talent.model.ProofStatus; -import jakarta.persistence.*; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; import lombok.experimental.Accessors; -import org.hibernate.validator.constraints.URL; - -import java.time.LocalDateTime; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; @Accessors(chain = true) @NoArgsConstructor @@ -44,8 +64,6 @@ public class TalentProof { @OneToMany(fetch = FetchType.EAGER, mappedBy = "proof", cascade = CascadeType.ALL, orphanRemoval = true) private List kudos; @ManyToMany - @JoinTable(name = "talent_skill", - joinColumns = @JoinColumn(name = "proof_id"), - inverseJoinColumns = @JoinColumn(name = "skill_id")) + @JoinTable(name = "proof_skill", joinColumns = @JoinColumn(name = "proof_id"), inverseJoinColumns = @JoinColumn(name = "skill_id")) private Set skills = new LinkedHashSet<>(); } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/model/entity/TalentSkills.java b/src/main/java/com/provedcode/talent/model/entity/TalentSkills.java deleted file mode 100644 index f6a10cc..0000000 --- a/src/main/java/com/provedcode/talent/model/entity/TalentSkills.java +++ /dev/null @@ -1,25 +0,0 @@ -//package com.provedcode.talent.model.entity; -// -//import jakarta.persistence.*; -//import jakarta.validation.constraints.NotNull; -//import lombok.*; -// -//@NoArgsConstructor -//@AllArgsConstructor -//@Builder -//@Getter -//@Setter -//@Entity -//@Table(name = "talent_talents") -//public class TalentSkills { -// @Id -// @GeneratedValue(strategy = GenerationType.IDENTITY) -// @Column(name = "id", nullable = false) -// private Long id; -// @NotNull -// @ManyToOne -// @JoinColumn(name = "talent_id", updatable = false) -// private Talent talent; -// @Column(name = "talent_name") -// private String talentName; -//} \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/service/TalentSkillsService.java b/src/main/java/com/provedcode/talent/service/ProofSkillsService.java similarity index 99% rename from src/main/java/com/provedcode/talent/service/TalentSkillsService.java rename to src/main/java/com/provedcode/talent/service/ProofSkillsService.java index 81841b0..84c4b2d 100644 --- a/src/main/java/com/provedcode/talent/service/TalentSkillsService.java +++ b/src/main/java/com/provedcode/talent/service/ProofSkillsService.java @@ -26,7 +26,7 @@ @Transactional @Service @AllArgsConstructor -public class TalentSkillsService { +public class ProofSkillsService { SkillsRepository skillsRepository; TalentRepository talentRepository; UserInfoRepository userInfoRepository; diff --git a/src/main/resources/db/changelog/changeset/V4/data-V4.1.sql b/src/main/resources/db/changelog/changeset/V4/data-V4.1.sql index 9261f0d..b7e84e2 100644 --- a/src/main/resources/db/changelog/changeset/V4/data-V4.1.sql +++ b/src/main/resources/db/changelog/changeset/V4/data-V4.1.sql @@ -1,19 +1,22 @@ --liquibase formatted sql --changeset dennis:3 --- Skill -INSERT INTO talent_skill (proof_id, skill_id) +-- Skill in proof +INSERT INTO proof_skill (proof_id, skill_id) VALUES (1, 1); -INSERT INTO talent_skill (proof_id, skill_id) +INSERT INTO proof_skill (proof_id, skill_id) VALUES (1, 2); -INSERT INTO talent_skill (proof_id, skill_id) +INSERT INTO proof_skill (proof_id, skill_id) VALUES (1, 3); -INSERT INTO talent_skill (proof_id, skill_id) +INSERT INTO proof_skill (proof_id, skill_id) VALUES (1, 4); -INSERT INTO talent_skill (proof_id, skill_id) +INSERT INTO proof_skill (proof_id, skill_id) VALUES (4, 1); -INSERT INTO talent_skill (proof_id, skill_id) +INSERT INTO proof_skill (proof_id, skill_id) VALUES (5, 2); -INSERT INTO talent_skill (proof_id, skill_id) +INSERT INTO proof_skill (proof_id, skill_id) VALUES (6, 3); - - +-- Skill in talent +INSERT INTO talent_skill (talent_id, skill_id) +VALUES(1, 1); +INSERT INTO talent_skill (talent_id, skill_id) +VALUES(1, 2); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V4/schema-V4.sql b/src/main/resources/db/changelog/changeset/V4/schema-V4.sql index b49be00..9355c9b 100644 --- a/src/main/resources/db/changelog/changeset/V4/schema-V4.sql +++ b/src/main/resources/db/changelog/changeset/V4/schema-V4.sql @@ -46,9 +46,14 @@ CREATE TABLE talent_proofs ( CONSTRAINT pk_talent_proofs PRIMARY KEY (id) ); CREATE TABLE talent_skill ( + talent_id BIGINT NOT NULL, + skill_id BIGINT NOT NULL, + CONSTRAINT pk_talent_skill PRIMARY KEY (talent_id, skill_id) +); +CREATE TABLE proof_skill ( proof_id BIGINT NOT NULL, skill_id BIGINT NOT NULL, - CONSTRAINT pk_talent_skill PRIMARY KEY (proof_id, skill_id) + CONSTRAINT pk_proof_skill PRIMARY KEY (proof_id, skill_id) ); CREATE TABLE skill ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -70,7 +75,7 @@ CREATE TABLE authority ( CONSTRAINT pk_authority PRIMARY KEY (id) ); CREATE TABLE user_authorities ( - authority_id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + authority_id BIGINT NOT NULL, user_id BIGINT NOT NULL, CONSTRAINT pk_user_authorities PRIMARY KEY (authority_id, user_id) ); @@ -112,9 +117,13 @@ 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); +ALTER TABLE proof_skill +ADD CONSTRAINT FK_proof_skill_ON_TALENT_PROOF FOREIGN KEY (proof_id) REFERENCES talent_proofs (id); +ALTER TABLE proof_skill +ADD CONSTRAINT FK_proof_skill_ON_SKILL FOREIGN KEY (skill_id) REFERENCES skill (id); ALTER TABLE talent_skill -ADD CONSTRAINT FK_TALENT_SKILL_ON_TALENT_PROOF FOREIGN KEY (proof_id) REFERENCES talent_proofs (id); +ADD CONSTRAINT FK_talent_skill_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); ALTER TABLE talent_skill -ADD CONSTRAINT FK_TALENT_SKILL_ON_SKILL FOREIGN KEY (skill_id) REFERENCES skill (id); +ADD CONSTRAINT FK_talent_skill_ON_SKILL FOREIGN KEY (skill_id) REFERENCES skill (id); -- Indexes CREATE UNIQUE INDEX idx_login ON user_info (login) \ No newline at end of file From 3aeb5b1ddecbc8a5abd6059c79bdd2fae2de4708 Mon Sep 17 00:00:00 2001 From: Denis973 <46610112+Denis973@users.noreply.github.com> Date: Sat, 13 May 2023 00:00:31 +0300 Subject: [PATCH 30/59] S4.2US1T2-3 (#131) * bug fix SkillsOnProofDTO * refactor SkillsOnProofDTO * add addSkillOnProof * bug fix addSkillOnProof * bug fix Talent * refactor FullTalentDTO and ShortTalentDTO * add controller deleteSkillFromTalent * add service deleteSkillFromTalent * bug fix * addSkillOnTalent refactor * add @NotEmpty to SkillIdDTO --- .../talent/controller/TalentController.java | 32 +++++-- .../provedcode/talent/mapper/SkillMapper.java | 1 + .../talent/model/dto/FullTalentDTO.java | 3 +- .../talent/model/dto/ShortTalentDTO.java | 4 +- .../provedcode/talent/model/dto/SkillDTO.java | 3 + .../talent/model/dto/SkillIdDTO.java | 11 +++ .../talent/model/dto/SkillsOnProofDTO.java | 3 +- .../talent/model/entity/Talent.java | 2 +- .../talent/service/ProofSkillsService.java | 13 ++- .../talent/service/TalentService.java | 85 ++++++++++++++----- 10 files changed, 120 insertions(+), 37 deletions(-) create mode 100644 src/main/java/com/provedcode/talent/model/dto/SkillIdDTO.java diff --git a/src/main/java/com/provedcode/talent/controller/TalentController.java b/src/main/java/com/provedcode/talent/controller/TalentController.java index 1b9e20d..ff09687 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentController.java @@ -1,9 +1,9 @@ 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.dto.SkillIdDTO; import com.provedcode.talent.model.request.EditTalent; import com.provedcode.talent.service.TalentService; import com.provedcode.user.model.dto.SessionInfoDTO; @@ -19,18 +19,15 @@ import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; -import org.springframework.http.HttpStatus; 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; - @Slf4j @RestController @AllArgsConstructor -@RequestMapping("/api/v2") +@RequestMapping("/api/") @Tag(name = "talent", description = "Talent API") @Validated public class TalentController { @@ -38,7 +35,7 @@ public class TalentController { TalentMapper talentMapper; @GetAllTalentsApiDoc - @GetMapping("/talents") + @GetMapping("v2/talents") @Validated Page getTalents(@RequestParam(value = "page", defaultValue = "0") @PositiveOrZero Integer page, @RequestParam(value = "size", defaultValue = "5") @Min(1) @Max(1000) Integer size) { @@ -47,7 +44,7 @@ Page getTalents(@RequestParam(value = "page", defaultValue = "0" @GetTalentApiDoc @PreAuthorize("hasRole('TALENT')") - @GetMapping("/talents/{id}") + @GetMapping("v2/talents/{id}") FullTalentDTO getTalent(@PathVariable("id") long id, Authentication authentication) { log.info("get-talent auth = {}", authentication); log.info("get-talent auth.name = {}", authentication.getAuthorities()); @@ -56,7 +53,7 @@ FullTalentDTO getTalent(@PathVariable("id") long id, Authentication authenticati @PatchEditTalentApiDoc @PreAuthorize("hasRole('TALENT')") - @PatchMapping("/talents/{talent-id}") + @PatchMapping("v2/talents/{talent-id}") FullTalentDTO editTalent(@PathVariable("talent-id") long id, @RequestBody @Valid EditTalent editTalent, Authentication authentication) { @@ -65,8 +62,25 @@ FullTalentDTO editTalent(@PathVariable("talent-id") long id, @DeleteTalentApiDoc @PreAuthorize("hasRole('TALENT')") - @DeleteMapping("/talents/{id}") + @DeleteMapping("v2/talents/{id}") SessionInfoDTO deleteTalent(@PathVariable("id") long id, Authentication authentication) { return talentService.deleteTalentById(id, authentication); } + + @PreAuthorize("hasRole('TALENT')") + @PostMapping("v4/talents/{talent-id}/skills") + void addSkillOnTalent(@PathVariable("talent-id") long id, + @RequestBody @Valid SkillIdDTO skillIdDTO, + Authentication authentication) { + talentService.addSkillOnTalent(id, skillIdDTO, authentication); + } + + @PreAuthorize("hasRole('TALENT')") + @DeleteMapping("v4/talents/{talent-id}/skills/{skill-id}") + void deleteSkillFromTalent(@PathVariable("talent-id") long talentId, + @PathVariable("skill-id") long skillId, + Authentication authentication) { + talentService.deleteSkillFromTalent(talentId, skillId, authentication); + } + } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/mapper/SkillMapper.java b/src/main/java/com/provedcode/talent/mapper/SkillMapper.java index 74c30b6..319185e 100644 --- a/src/main/java/com/provedcode/talent/mapper/SkillMapper.java +++ b/src/main/java/com/provedcode/talent/mapper/SkillMapper.java @@ -9,4 +9,5 @@ @Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING) public interface SkillMapper { SkillDTO skillToSkillDTO(Skills skills); + } 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 b67b317..8ee5f11 100644 --- a/src/main/java/com/provedcode/talent/model/dto/FullTalentDTO.java +++ b/src/main/java/com/provedcode/talent/model/dto/FullTalentDTO.java @@ -6,6 +6,7 @@ import lombok.Builder; import java.util.List; +import java.util.Set; @Builder public record FullTalentDTO( @@ -22,7 +23,7 @@ public record FullTalentDTO( @JsonProperty("additional_info") String additionalInfo, String bio, - List talents, + Set skills, @UrlList List links, List contacts, diff --git a/src/main/java/com/provedcode/talent/model/dto/ShortTalentDTO.java b/src/main/java/com/provedcode/talent/model/dto/ShortTalentDTO.java index d252bcd..14d2f09 100644 --- a/src/main/java/com/provedcode/talent/model/dto/ShortTalentDTO.java +++ b/src/main/java/com/provedcode/talent/model/dto/ShortTalentDTO.java @@ -2,7 +2,7 @@ import lombok.Builder; -import java.util.List; +import java.util.Set; @Builder public record ShortTalentDTO( @@ -11,6 +11,6 @@ public record ShortTalentDTO( String firstName, String lastName, String specialization, - List talents + Set skills ) { } diff --git a/src/main/java/com/provedcode/talent/model/dto/SkillDTO.java b/src/main/java/com/provedcode/talent/model/dto/SkillDTO.java index f93fe25..e02a54d 100644 --- a/src/main/java/com/provedcode/talent/model/dto/SkillDTO.java +++ b/src/main/java/com/provedcode/talent/model/dto/SkillDTO.java @@ -1,5 +1,8 @@ package com.provedcode.talent.model.dto; +import lombok.Builder; + +@Builder public record SkillDTO( Long id, String skill diff --git a/src/main/java/com/provedcode/talent/model/dto/SkillIdDTO.java b/src/main/java/com/provedcode/talent/model/dto/SkillIdDTO.java new file mode 100644 index 0000000..c6d4013 --- /dev/null +++ b/src/main/java/com/provedcode/talent/model/dto/SkillIdDTO.java @@ -0,0 +1,11 @@ +package com.provedcode.talent.model.dto; + +import jakarta.validation.constraints.NotEmpty; + +import java.util.List; + +public record SkillIdDTO( + @NotEmpty + List id +) { +} diff --git a/src/main/java/com/provedcode/talent/model/dto/SkillsOnProofDTO.java b/src/main/java/com/provedcode/talent/model/dto/SkillsOnProofDTO.java index f70ff5e..c916456 100644 --- a/src/main/java/com/provedcode/talent/model/dto/SkillsOnProofDTO.java +++ b/src/main/java/com/provedcode/talent/model/dto/SkillsOnProofDTO.java @@ -1,12 +1,11 @@ package com.provedcode.talent.model.dto; -import com.provedcode.talent.model.entity.Skills; import lombok.Builder; import java.util.Set; @Builder public record SkillsOnProofDTO( - Set skills + Set skills ) { } 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 c093e16..cbb2f54 100644 --- a/src/main/java/com/provedcode/talent/model/entity/Talent.java +++ b/src/main/java/com/provedcode/talent/model/entity/Talent.java @@ -66,7 +66,7 @@ public class Talent { @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) private List talentProofs = new ArrayList<>(); @ManyToMany - @JoinTable(name = "talent_skills", + @JoinTable(name = "talent_skill", joinColumns = @JoinColumn(name = "talent_id"), inverseJoinColumns = @JoinColumn(name = "skill_id")) private Set skills = new LinkedHashSet<>(); diff --git a/src/main/java/com/provedcode/talent/service/ProofSkillsService.java b/src/main/java/com/provedcode/talent/service/ProofSkillsService.java index 84c4b2d..55580f4 100644 --- a/src/main/java/com/provedcode/talent/service/ProofSkillsService.java +++ b/src/main/java/com/provedcode/talent/service/ProofSkillsService.java @@ -1,7 +1,9 @@ package com.provedcode.talent.service; +import com.provedcode.talent.mapper.SkillMapper; import com.provedcode.talent.model.ProofStatus; import com.provedcode.talent.model.dto.ProofSkillsDTO; +import com.provedcode.talent.model.dto.SkillDTO; import com.provedcode.talent.model.dto.SkillsOnProofDTO; import com.provedcode.talent.model.entity.Skills; import com.provedcode.talent.model.entity.Talent; @@ -18,8 +20,10 @@ import org.springframework.web.server.ResponseStatusException; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.function.BiConsumer; +import java.util.stream.Collectors; import static org.springframework.http.HttpStatus.*; @@ -31,6 +35,8 @@ public class ProofSkillsService { TalentRepository talentRepository; UserInfoRepository userInfoRepository; TalentProofRepository talentProofRepository; + SkillMapper skillMapper; + static BiConsumer isValidUserEditTalent = (talentId, userInfo) -> { if (!userInfo.getTalent().getId().equals(talentId)) { @@ -79,14 +85,15 @@ public SkillsOnProofDTO getAllSkillsOnProof(long talentId, long proofId, Authent throw new ResponseStatusException(BAD_REQUEST, "talentId with id = %s and proofId with id = %s do not match".formatted(talentId, proofId)); } - + Set skills = talentProof.getSkills().stream() + .map(skillMapper::skillToSkillDTO).collect(Collectors.toSet()); if (talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { - return SkillsOnProofDTO.builder().skills(talentProof.getSkills()).build(); + return SkillsOnProofDTO.builder().skills(skills).build(); } else if (authentication != null) { UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); if (userInfo.getTalent().getId().equals(talentProof.getTalent().getId())) { - return SkillsOnProofDTO.builder().skills(talentProof.getSkills()).build(); + return SkillsOnProofDTO.builder().skills(skills).build(); } else { throw new ResponseStatusException(FORBIDDEN, "you can't see proofs in DRAFT and HIDDEN status"); } diff --git a/src/main/java/com/provedcode/talent/service/TalentService.java b/src/main/java/com/provedcode/talent/service/TalentService.java index fb35aa9..0cdb04c 100644 --- a/src/main/java/com/provedcode/talent/service/TalentService.java +++ b/src/main/java/com/provedcode/talent/service/TalentService.java @@ -1,8 +1,10 @@ package com.provedcode.talent.service; import com.provedcode.config.PageProperties; +import com.provedcode.talent.model.dto.SkillIdDTO; import com.provedcode.talent.model.entity.*; import com.provedcode.talent.model.request.EditTalent; +import com.provedcode.talent.repo.SkillsRepository; import com.provedcode.talent.repo.TalentProofRepository; import com.provedcode.talent.repo.TalentRepository; import com.provedcode.talent.utill.ValidateTalentForCompliance; @@ -19,11 +21,13 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.server.ResponseStatusException; +import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; -import static org.springframework.http.HttpStatus.BAD_REQUEST; -import static org.springframework.http.HttpStatus.NOT_FOUND; +import static org.springframework.http.HttpStatus.*; @Service @Slf4j @@ -36,6 +40,7 @@ public class TalentService { UserInfoRepository userInfoRepository; PageProperties pageProperties; ValidateTalentForCompliance validateTalentForCompliance; + SkillsRepository skillsRepository; @Transactional(readOnly = true) public Page getTalentsPage(Integer page, Integer size) { @@ -81,10 +86,10 @@ public Talent editTalent(long id, EditTalent editTalent, Authentication authenti editableTalentDescription.setBio(editTalent.bio()); } else { editableTalentDescription = TalentDescription.builder() - .additionalInfo(editTalent.additionalInfo()) - .bio(editTalent.bio()) - .talent(editableTalent) - .build(); + .additionalInfo(editTalent.additionalInfo()) + .bio(editTalent.bio()) + .talent(editableTalent) + .build(); } editableTalent.setTalentDescription(editableTalentDescription); } @@ -99,27 +104,27 @@ public Talent editTalent(long id, EditTalent editTalent, Authentication authenti if (editTalent.links() != null) { editableTalentLinks.clear(); editableTalentLinks.addAll(editTalent.links().stream().map(s -> TalentLink.builder() - .talent(editableTalent) - .link(s) - .build()).toList()); + .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()); + .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()); + .talent(editableTalent) + .attachedFile( + s) + .build()) + .toList()); editableTalent.setTalentAttachedFiles(editableTalentAttachedFiles); } return talentRepository.save(editableTalent); @@ -143,8 +148,50 @@ public 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.links() == null && editTalent.contacts() == null && editTalent.attachedFiles() == null) + editTalent.specialization() == null && editTalent.additionalInfo() == null && editTalent.bio() == null && + editTalent.links() == null && editTalent.contacts() == null && editTalent.attachedFiles() == null) throw new ResponseStatusException(BAD_REQUEST, "you did not provide information to make changes"); } + + public void addSkillOnTalent(long id, SkillIdDTO skillIdDTO, Authentication authentication) { + Optional talent = talentRepository.findById(id); + Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); + validateTalentForCompliance.userVerification(talent, userInfo, id); + Talent talentObject = talent.get(); + + Set skillsFromRepo = skillIdDTO.id().stream() + .map(element -> skillsRepository.findById(element) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Skill with id = %d not found".formatted(element)))) + .collect(Collectors.toSet()); + + Set skillsFromProofs = talentObject.getTalentProofs().stream() + .flatMap(talentProof -> talentProof.getSkills().stream()) + .collect(Collectors.toSet()); + + skillsFromRepo.stream() + .filter(skill -> !skillsFromProofs.contains(skill)) + .findFirst() + .ifPresent(skill -> { + throw new ResponseStatusException(FORBIDDEN, + "Skill with id = %d not found in talent's proofs".formatted(skill.getId())); + }); + + skillsFromRepo.stream() + .forEach(skill -> talentObject.getSkills().add(skill)); + } + + public void deleteSkillFromTalent(long talentId, long skillId, Authentication authentication) { + Optional talent = talentRepository.findById(talentId); + Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); + Skills skill = skillsRepository.findById(skillId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Skill with id = %d not found".formatted(skillId))); + validateTalentForCompliance.userVerification(talent, userInfo, talentId); + Talent talentObject = talent.get(); + if (!talentObject.getSkills().remove(skill)) { + throw new ResponseStatusException(NOT_FOUND, + "Skill with id = %d not found".formatted(skillId)); + } + } } \ No newline at end of file From 554a6bb17e033e64eb319f9d6c48e884c7a54eb6 Mon Sep 17 00:00:00 2001 From: Mykhailo Ordyntsev <102993813+Maslyna@users.noreply.github.com> Date: Sun, 14 May 2023 20:37:59 +0200 Subject: [PATCH 31/59] S4.2-FULL (#135) * Filter by talent skills * Code refactor: constraintViolationException * Code refactor: delete proof by id now deletes skills on talent, that can`t be approved --- .../handlers/TalentExceptionHandler.java | 3 +- .../talent/controller/TalentController.java | 7 + .../controller/TalentProofController.java | 4 +- .../talent/repo/TalentRepository.java | 16 + .../talent/service/TalentProofService.java | 19 +- .../talent/service/TalentService.java | 14 +- .../controller/proof/DeleteProofApiDoc.java | 4 +- .../db/changelog/changeset/V4/data-V4.1.sql | 6 +- .../db/changelog/changeset/V4/data-V4.2.sql | 25 + .../db/changelog/changeset/V4/data-V4.sql | 1377 ++++++----------- .../db/changelog/changeset/V4/schema-V4.sql | 148 +- .../db/changelog/db.changelog-master.yaml | 2 + 12 files changed, 644 insertions(+), 981 deletions(-) create mode 100644 src/main/resources/db/changelog/changeset/V4/data-V4.2.sql diff --git a/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java b/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java index 7da4cc8..cc31cbf 100644 --- a/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java +++ b/src/main/java/com/provedcode/handlers/TalentExceptionHandler.java @@ -1,5 +1,6 @@ package com.provedcode.handlers; +import com.provedcode.handlers.dto.ErrorDTO; import jakarta.validation.ConstraintViolationException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -65,7 +66,7 @@ private ResponseEntity responseStatusExceptionHandler(ResponseStatusException @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()); + return new ResponseEntity<>(new ErrorDTO(apiError.getMessage()), new HttpHeaders(), apiError.getStatus()); } // @ExceptionHandler({ Exception.class }) diff --git a/src/main/java/com/provedcode/talent/controller/TalentController.java b/src/main/java/com/provedcode/talent/controller/TalentController.java index ff09687..ecff1f5 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentController.java @@ -83,4 +83,11 @@ void deleteSkillFromTalent(@PathVariable("talent-id") long talentId, talentService.deleteSkillFromTalent(talentId, skillId, authentication); } + @GetMapping("v4/talents") + Page getFilteredBySkillsTalents(@RequestParam(value = "page", defaultValue = "0") @PositiveOrZero Integer page, + @RequestParam(value = "size", defaultValue = "5") @Min(1) @Max(1000) Integer size, + @RequestParam(value = "filter-by", required = false) String... filterBy) { + return talentService.getFilteredBySkillsTalentsPage(page, size, filterBy).map(talentMapper::talentToShortTalentDTO); + } + } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/controller/TalentProofController.java b/src/main/java/com/provedcode/talent/controller/TalentProofController.java index 25492f0..ff89e09 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentProofController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentProofController.java @@ -88,9 +88,9 @@ ProofDTO editProof(Authentication authentication, @DeleteProofApiDoc @DeleteMapping("/{talent-id}/proofs/{proof-id}") @PreAuthorize("hasRole('TALENT')") - StatusDTO deleteProof(@PathVariable(value = "talent-id") long talentId, + void deleteProof(@PathVariable(value = "talent-id") long talentId, @PathVariable(value = "proof-id") long proofId, Authentication authentication) { - return talentProofService.deleteProofById(talentId, proofId, authentication); + talentProofService.deleteProofById(talentId, proofId, authentication); } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/repo/TalentRepository.java b/src/main/java/com/provedcode/talent/repo/TalentRepository.java index b2bac22..e253032 100644 --- a/src/main/java/com/provedcode/talent/repo/TalentRepository.java +++ b/src/main/java/com/provedcode/talent/repo/TalentRepository.java @@ -1,7 +1,23 @@ package com.provedcode.talent.repo; import com.provedcode.talent.model.entity.Talent; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; public interface TalentRepository extends JpaRepository { +// @Query("select t from Talent t left join t.skills skills where upper(skills.skill) like upper(concat('%', ?2, '%'))") +// Page findBySkills_SkillContainsIgnoreCase(Pageable pageable, String... skill); +// @Query("SELECT t FROM Talent t LEFT JOIN t.skills skills WHERE UPPER(skills.skill) LIKE UPPER(CONCAT('%', :skills, '%'))") // if by-symbol contains +// Page findBySkills_SkillContainsIgnoreCase(Pageable pageable, @Param("skills") String... skills); + @Query("SELECT t FROM Talent t INNER JOIN t.skills s WHERE UPPER(s.skill) IN (:filter_by)") //if only contains all + Page findBySkills_SkillsInIgnoreCase(Pageable pageable, @Param("filter_by") List skills); +// @Query("select t from Talent t inner join t.skills skills where upper(skills.skill) like upper(?1)") +// Page findBySkillsLikeIgnoreCase(String skill, Pageable pageable); + } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/service/TalentProofService.java b/src/main/java/com/provedcode/talent/service/TalentProofService.java index 9c92069..06b5463 100644 --- a/src/main/java/com/provedcode/talent/service/TalentProofService.java +++ b/src/main/java/com/provedcode/talent/service/TalentProofService.java @@ -5,6 +5,7 @@ import com.provedcode.talent.model.dto.FullProofDTO; import com.provedcode.talent.model.dto.ProofDTO; import com.provedcode.talent.model.dto.StatusDTO; +import com.provedcode.talent.model.entity.Skills; import com.provedcode.talent.model.entity.Talent; import com.provedcode.talent.model.entity.TalentProof; import com.provedcode.talent.model.request.AddProof; @@ -30,8 +31,8 @@ import java.net.URI; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.Objects; -import java.util.Optional; +import java.util.*; +import java.util.stream.Collectors; import static org.springframework.http.HttpStatus.FORBIDDEN; import static org.springframework.http.HttpStatus.NOT_FOUND; @@ -159,14 +160,22 @@ public TalentProof editTalentProof(long talentId, long proofId, ProofDTO proof, return talentProofRepository.save(oldProof); } - public StatusDTO deleteProofById(long talentId, long proofId, Authentication authentication) { + public void deleteProofById(long talentId, long proofId, Authentication authentication) { Optional talent = talentRepository.findById(talentId); Optional talentProof = talentProofRepository.findById(proofId); Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); validateTalentForCompliance.userAndProofVerification(talent, talentProof, userInfo, talentId, proofId); - talent.get().getTalentProofs().remove(talentProof.get()); - return new StatusDTO("deleted"); + Talent updatableTalent = talent.get(); + List talentSkills = updatableTalent.getTalentProofs().stream() + .flatMap(proof -> proof.getSkills().stream()).collect(Collectors.toCollection(ArrayList::new)); + log.info("talent-skills = {}", talentSkills.stream().map(i -> i.getSkill()).toList()); + List skillsOnProof = talentProof.get().getSkills().stream().toList(); + talentSkills.removeAll(skillsOnProof); + Set newTalentSkills = new HashSet<>(talentSkills); + updatableTalent.setSkills(newTalentSkills); + log.info("new talent-skills = {}", newTalentSkills.stream().map(Skills::getSkill).toList()); + updatableTalent.getTalentProofs().remove(talentProof.get()); } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/service/TalentService.java b/src/main/java/com/provedcode/talent/service/TalentService.java index 0cdb04c..2abcb7d 100644 --- a/src/main/java/com/provedcode/talent/service/TalentService.java +++ b/src/main/java/com/provedcode/talent/service/TalentService.java @@ -12,6 +12,9 @@ import com.provedcode.user.model.entity.UserInfo; import com.provedcode.user.repo.AuthorityRepository; import com.provedcode.user.repo.UserInfoRepository; +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; @@ -21,7 +24,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.server.ResponseStatusException; -import java.util.HashSet; +import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.Set; @@ -194,4 +197,13 @@ public void deleteSkillFromTalent(long talentId, long skillId, Authentication au "Skill with id = %d not found".formatted(skillId)); } } + + @Transactional(readOnly = true) + public Page getFilteredBySkillsTalentsPage(@PositiveOrZero Integer page, + @Min(1) @Max(1000) Integer size, + String... filterBy) { + return filterBy != null ? + talentRepository.findBySkills_SkillsInIgnoreCase(PageRequest.of(page, size), Arrays.stream(filterBy).map(String::toUpperCase).toList()) + : talentRepository.findAll(PageRequest.of(page, size)); + } } \ No newline at end of file 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 index 5f77466..f2e8868 100644 --- 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 @@ -19,9 +19,7 @@ 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))), + description = "SUCCESS"), @ApiResponse(responseCode = "404", description = "NOT FOUND", content = @Content), diff --git a/src/main/resources/db/changelog/changeset/V4/data-V4.1.sql b/src/main/resources/db/changelog/changeset/V4/data-V4.1.sql index b7e84e2..2f86411 100644 --- a/src/main/resources/db/changelog/changeset/V4/data-V4.1.sql +++ b/src/main/resources/db/changelog/changeset/V4/data-V4.1.sql @@ -15,8 +15,4 @@ INSERT INTO proof_skill (proof_id, skill_id) VALUES (5, 2); INSERT INTO proof_skill (proof_id, skill_id) VALUES (6, 3); --- Skill in talent -INSERT INTO talent_skill (talent_id, skill_id) -VALUES(1, 1); -INSERT INTO talent_skill (talent_id, skill_id) -VALUES(1, 2); \ No newline at end of file + diff --git a/src/main/resources/db/changelog/changeset/V4/data-V4.2.sql b/src/main/resources/db/changelog/changeset/V4/data-V4.2.sql new file mode 100644 index 0000000..09cd767 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V4/data-V4.2.sql @@ -0,0 +1,25 @@ +--liquibase formatted sql +--changeset mykhailo:3 + +-- Skill on proof + + +-- Skill on talent +INSERT INTO talent_skill (talent_id, skill_id) +VALUES(1, 1); +INSERT INTO talent_skill (talent_id, skill_id) +VALUES(1, 2); +INSERT INTO talent_skill (talent_id, skill_id) +VALUES(5, 1); +INSERT INTO talent_skill (talent_id, skill_id) +VALUES(5, 2); +INSERT INTO talent_skill (talent_id, skill_id) +VALUES(5, 3); + +-- Skills on proof +INSERT INTO proof_skill (proof_id, skill_id) +VALUES (13, 1); +INSERT INTO proof_skill (proof_id, skill_id) +VALUES (13, 2); +INSERT INTO proof_skill (proof_id, skill_id) +VALUES (13, 3); diff --git a/src/main/resources/db/changelog/changeset/V4/data-V4.sql b/src/main/resources/db/changelog/changeset/V4/data-V4.sql index 4f08749..c1b0ebb 100644 --- a/src/main/resources/db/changelog/changeset/V4/data-V4.sql +++ b/src/main/resources/db/changelog/changeset/V4/data-V4.sql @@ -35,2036 +35,1619 @@ values (13, 'Angular'); -- Talent -- Serhii Soloviov insert into talent (first_name, last_name, specialization, image) -values ( - 'Serhii', +values ('Serhii', 'Soloviov', 'Java-Developer', - 'https://i.pinimg.com/564x/e1/08/49/e10849923a8b2e85a7adf494ebd063e6.jpg' - ); + 'https://i.pinimg.com/564x/e1/08/49/e10849923a8b2e85a7adf494ebd063e6.jpg'); insert into talent_description (talent_id, BIO, addition_info) -values( - ( +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' - ); + ), + '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'first_contact' - ); + ), 'first_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'second_contact' - ); + ), 'second_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'third_contact' - ); + ), 'third_contact'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_proofs (talent_id, link, text, status, created) -values ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'SerhiiSoloviov@gmail.com', '$2a$10$EzYxG1DEUek/veK.HzP7B.ynSKE42VbLb4pvFd/v4OwGPNol6buEC' - ); + ), 'SerhiiSoloviov@gmail.com', '$2a$10$EzYxG1DEUek/veK.HzP7B.ynSKE42VbLb4pvFd/v4OwGPNol6buEC'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 1 - ) - ); + )); -- Mykhailo Ordyntsev insert into talent (first_name, last_name, specialization, image) -values ( - 'Mykhailo', +values ('Mykhailo', 'Ordyntsev', 'Java-Developer', - 'https://i.pinimg.com/564x/c2/41/31/c24131fe00218467721ba5bacdf0a256.jpg' - ); + 'https://i.pinimg.com/564x/c2/41/31/c24131fe00218467721ba5bacdf0a256.jpg'); insert into talent_description (talent_id, BIO, addition_info) -values( - ( +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' - ); + ), + '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'MykhailoOrdyntsev_first_contact' - ); + ), 'MykhailoOrdyntsev_first_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'MykhailoOrdyntsev_second_contact' - ); + ), 'MykhailoOrdyntsev_second_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'MykhailoOrdyntsev_third_contact' - ); + ), 'MykhailoOrdyntsev_third_contact'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_proofs (talent_id, link, text, status, created) -values ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'MykhailoOrdyntsev@gmail.com', '$2a$10$XD60M86n1MDf3AMIixgnnOQq9JVYnnX/umlNFcre0GoC2XgSN/Cfq' - ); + ), 'MykhailoOrdyntsev@gmail.com', '$2a$10$XD60M86n1MDf3AMIixgnnOQq9JVYnnX/umlNFcre0GoC2XgSN/Cfq'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 1 - ) - ); + )); -- Denis Boyko insert into talent (first_name, last_name, specialization, image) -values ( - 'Denis', +values ('Denis', 'Boyko', 'Java-Developer', - 'https://i.pinimg.com/564x/2a/0c/08/2a0c08c421e253ca895c3fdc8c9e08d9.jpg' - ); + 'https://i.pinimg.com/564x/2a/0c/08/2a0c08c421e253ca895c3fdc8c9e08d9.jpg'); insert into talent_description (talent_id, BIO, addition_info) -values( - ( +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 ' - ); + ), + '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'DenisBoyko_first_contact' - ); + ), 'DenisBoyko_first_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'DenisBoyko_second_contact' - ); + ), 'DenisBoyko_second_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'DenisBoyko_third_contact' - ); + ), 'DenisBoyko_third_contact'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_proofs (talent_id, link, text, status, created) -values ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'DenisBoyko@gmail.com', '$2a$10$tLm27FGH8Sabz57eNkTwm.bSnhmJHINcqt7dNfZI0NfOwD2o/Drse' - ); + ), 'DenisBoyko@gmail.com', '$2a$10$tLm27FGH8Sabz57eNkTwm.bSnhmJHINcqt7dNfZI0NfOwD2o/Drse'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 1 - ) - ); + )); -- Ihor Schurenko insert into talent (first_name, last_name, specialization, image) -values ( - 'Ihor', +values ('Ihor', 'Schurenko', 'Java-Developer', - 'https://i.pinimg.com/564x/e1/11/2f/e1112f0b7b63644dc3e313084936dedb.jpg' - ); + 'https://i.pinimg.com/564x/e1/11/2f/e1112f0b7b63644dc3e313084936dedb.jpg'); insert into talent_description (talent_id, BIO, addition_info) -values( - ( +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' - ); + ), + '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'IhorShchurenko_first_contact' - ); + ), 'IhorShchurenko_first_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'IhorShchurenko_second_contact' - ); + ), 'IhorShchurenko_second_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'IhorShchurenko_third_contact' - ); + ), 'IhorShchurenko_third_contact'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_proofs (talent_id, link, text, status, created) -values ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'IhorShchurenko@gmail.com', '$2a$10$X.d4hR.yRf3cK0Go20aTTukOI9u/Zu2cj5WU0iTcDihyhJ5vUHXkq' - ); + ), 'IhorShchurenko@gmail.com', '$2a$10$X.d4hR.yRf3cK0Go20aTTukOI9u/Zu2cj5WU0iTcDihyhJ5vUHXkq'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 1 - ) - ); + )); -- Dmytro Uzun insert into talent (first_name, last_name, specialization, image) -values ( - 'Dmytro', +values ('Dmytro', 'Uzun', 'Dev-Ops', - 'https://i.pinimg.com/564x/1c/af/87/1caf8771ef3edf351f6f2bf6f1c0a276.jpg' - ); + 'https://i.pinimg.com/564x/1c/af/87/1caf8771ef3edf351f6f2bf6f1c0a276.jpg'); insert into talent_description (talent_id, BIO, addition_info) -values( - ( +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!' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'DmytroUzun_first_contact' - ); + ), 'DmytroUzun_first_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'DmytroUzun_second_contact' - ); + ), 'DmytroUzun_second_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'DmytroUzun_third_contact' - ); + ), 'DmytroUzun_third_contact'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_proofs (talent_id, link, text, status, created) -values ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'DmytroUzun@gmail.com', '$2a$10$J2Yuh10BWHy8XYk.T5rd2uOwk/h5EYG1eVXTAOkTkTdQcc5Qzd9.y' - ); + ), 'DmytroUzun@gmail.com', '$2a$10$J2Yuh10BWHy8XYk.T5rd2uOwk/h5EYG1eVXTAOkTkTdQcc5Qzd9.y'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 1 - ) - ); + )); -- Viktor Voloshko insert into talent (first_name, last_name, specialization, image) -values ( - 'Viktor', +values ('Viktor', 'Voloshko', 'Dev-Ops', - 'https://i.pinimg.com/564x/a9/51/ab/a951ab682413b89617235e65564c1e5e.jpg' - ); + 'https://i.pinimg.com/564x/a9/51/ab/a951ab682413b89617235e65564c1e5e.jpg'); insert into talent_description (talent_id, BIO, addition_info) -values( - ( +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!' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'ViktorVoloshko_first_contact' - ); + ), 'ViktorVoloshko_first_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'ViktorVoloshko_second_contact' - ); + ), 'ViktorVoloshko_second_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'ViktorVoloshko_third_contact' - ); + ), 'ViktorVoloshko_third_contact'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_proofs (talent_id, link, text, status, created) -values ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'ViktorVoloshko@gmail.com', '$2a$10$eZX3hBvllxkmH.juZzN72uvFYtphkrxsj14K5BnHHKy4coRV9FMvq' - ); + ), 'ViktorVoloshko@gmail.com', '$2a$10$eZX3hBvllxkmH.juZzN72uvFYtphkrxsj14K5BnHHKy4coRV9FMvq'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 1 - ) - ); + )); -- Olha Moiseienko insert into talent (first_name, last_name, specialization, image) -values ( - 'Olha', +values ('Olha', 'Moiseienko', 'QA', - 'https://i.pinimg.com/564x/6d/9d/43/6d9d437baf4db114c047d927307beb84.jpg' - ); + 'https://i.pinimg.com/564x/6d/9d/43/6d9d437baf4db114c047d927307beb84.jpg'); insert into talent_description (talent_id, BIO, addition_info) -values( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'OlhaMoiseienko_first_contact' - ); + ), 'OlhaMoiseienko_first_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'OlhaMoiseienko_second_contact' - ); + ), 'OlhaMoiseienko_second_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'OlhaMoiseienko_third_contact' - ); + ), 'OlhaMoiseienko_third_contact'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_proofs (talent_id, link, text, status, created) -values ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'OlhaMoiseienko@gmail.com', '$2a$10$lvvX7DZOwCS/Q7zSo.k.oeayTcKHh8rO1yBBkgIbU4VAC7abPfIa2' - ); + ), 'OlhaMoiseienko@gmail.com', '$2a$10$lvvX7DZOwCS/Q7zSo.k.oeayTcKHh8rO1yBBkgIbU4VAC7abPfIa2'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 1 - ) - ); + )); -- Maxim Kiyashko insert into talent (first_name, last_name, specialization, image) -values ( - 'Maxim', +values ('Maxim', 'Kiyashko', 'QA', - 'https://i.pinimg.com/564x/80/2d/58/802d58b0302985f9486893d499d3634d.jpg' - ); + 'https://i.pinimg.com/564x/80/2d/58/802d58b0302985f9486893d499d3634d.jpg'); insert into talent_description (talent_id, BIO, addition_info) -values( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'MaximKiyashko_first_contact' - ); + ), 'MaximKiyashko_first_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'MaximKiyashko_second_contact' - ); + ), 'MaximKiyashko_second_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'MaximKiyashko_third_contact' - ); + ), 'MaximKiyashko_third_contact'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_proofs (talent_id, link, text, status, created) -values ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'MaximKiyashko@gmail.com', '$2a$10$y.g9qHYUOPEkIL8xDc2h1.EdVAG5DYh6OKxf9CRb6s16oHHbr8Bny' - ); + ), 'MaximKiyashko@gmail.com', '$2a$10$y.g9qHYUOPEkIL8xDc2h1.EdVAG5DYh6OKxf9CRb6s16oHHbr8Bny'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 1 - ) - ); + )); -- Nikolaiev Oleksii insert into talent (first_name, last_name, specialization, image) -values ( - 'Nikolaiev', +values ('Nikolaiev', 'Oleksii', 'QA', - 'https://i.pinimg.com/564x/54/d1/0d/54d10dfce64afefabc9fbbce5de82c87.jpg' - ); + 'https://i.pinimg.com/564x/54/d1/0d/54d10dfce64afefabc9fbbce5de82c87.jpg'); insert into talent_description (talent_id, BIO, addition_info) -values( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'NikolaievOleksii_first_contact' - ); + ), 'NikolaievOleksii_first_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'NikolaievOleksii_second_contact' - ); + ), 'NikolaievOleksii_second_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'NikolaievOleksii_third_contact' - ); + ), 'NikolaievOleksii_third_contact'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_proofs (talent_id, link, text, status, created) -values ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'NikolaievOleksiio@gmail.com', '$2a$10$nDObO3nDlhWev29qCnzNuOszdg/.ANaMlTirDVWVyLMapYmtSSqza' - ); + ), 'NikolaievOleksiio@gmail.com', '$2a$10$nDObO3nDlhWev29qCnzNuOszdg/.ANaMlTirDVWVyLMapYmtSSqza'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 1 - ) - ); + )); -- Artem Lytvynenko insert into talent (first_name, last_name, specialization, image) -values ( - 'Artem', +values ('Artem', 'Lytvynenko', 'QA', - 'https://i.pinimg.com/564x/87/63/55/87635509c5fa7ee496ec351fa7e67eaa.jpg' - ); + 'https://i.pinimg.com/564x/87/63/55/87635509c5fa7ee496ec351fa7e67eaa.jpg'); insert into talent_description (talent_id, BIO, addition_info) -values( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'ArtemLytvynenko_first_contact' - ); + ), 'ArtemLytvynenko_first_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'ArtemLytvynenko_second_contact' - ); + ), 'ArtemLytvynenko_second_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'ArtemLytvynenko_third_contact' - ); + ), 'ArtemLytvynenko_third_contact'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_proofs (talent_id, link, text, status, created) -values ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'ArtemLytvynenko@gmail.com', '$2a$10$.M2fHh9NXbkbnrVHeT.lYeInA8K2khuMUL08iG4NuXs18KIeFBmwG' - ); + ), 'ArtemLytvynenko@gmail.com', '$2a$10$.M2fHh9NXbkbnrVHeT.lYeInA8K2khuMUL08iG4NuXs18KIeFBmwG'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 1 - ) - ); + )); -- Daniil Yevtukhov insert into talent (first_name, last_name, specialization, image) -values ( - 'Daniil', +values ('Daniil', 'Yevtukhov', 'Java-Script-Developer', - 'https://i.pinimg.com/564x/fe/b1/37/feb137d88a3d1c8fb28796db6cbc576f.jpg' - ); + 'https://i.pinimg.com/564x/fe/b1/37/feb137d88a3d1c8fb28796db6cbc576f.jpg'); insert into talent_description (talent_id, BIO, addition_info) -values( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'DaniilYevtukhov_first_contact' - ); + ), 'DaniilYevtukhov_first_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'DaniilYevtukhov_second_contact' - ); + ), 'DaniilYevtukhov_second_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'DaniilYevtukhov_third_contact' - ); + ), 'DaniilYevtukhov_third_contact'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_proofs (talent_id, link, text, status, created) -values ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'DaniilYevtukhov@gmail.com', '$2a$10$cDxp6U/YcObKMwZNgtEB5eZFLWXuwFU0lIUSPIkfPdvq9l8JUqGea' - ); + ), 'DaniilYevtukhov@gmail.com', '$2a$10$cDxp6U/YcObKMwZNgtEB5eZFLWXuwFU0lIUSPIkfPdvq9l8JUqGea'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 1 - ) - ); + )); -- Ruslan Morozov insert into talent (first_name, last_name, specialization, image) -values ( - 'Ruslan', +values ('Ruslan', 'Morozov', 'Java-Script-Developer', - 'https://i.pinimg.com/736x/36/ae/0e/36ae0ea4aad656f7c3d3175bc33b8399.jpg' - ); + 'https://i.pinimg.com/736x/36/ae/0e/36ae0ea4aad656f7c3d3175bc33b8399.jpg'); insert into talent_description (talent_id, BIO, addition_info) -values( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'RuslanMorozov_first_contact' - ); + ), 'RuslanMorozov_first_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'RuslanMorozov_second_contact' - ); + ), 'RuslanMorozov_second_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'RuslanMorozov_third_contact' - ); + ), 'RuslanMorozov_third_contact'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_proofs (talent_id, link, text, status, created) -values ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'RuslanMorozov@gmail.com', '$2a$10$Hfzp4b6r825g1ZqGzxmal..VNKvo7F4v4YFpBZZ036hmO.7UIWlaK' - ); + ), 'RuslanMorozov@gmail.com', '$2a$10$Hfzp4b6r825g1ZqGzxmal..VNKvo7F4v4YFpBZZ036hmO.7UIWlaK'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 1 - ) - ); + )); -- Ihor Kopieichykov insert into talent (first_name, last_name, specialization, image) -values ( - 'Ihor', +values ('Ihor', 'Kopieichykov', 'Java-Script-Developer', - 'https://i.pinimg.com/564x/0d/f0/83/0df083121bac75f64e3d93c7c5682d04.jpg' - ); + 'https://i.pinimg.com/564x/0d/f0/83/0df083121bac75f64e3d93c7c5682d04.jpg'); insert into talent_description (talent_id, BIO, addition_info) -values( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_link (talent_id, link) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'IhorKopieichykov_first_contact' - ); + ), 'IhorKopieichykov_first_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'IhorKopieichykov_second_contact' - ); + ), 'IhorKopieichykov_second_contact'); insert into talent_contact (talent_id, contact) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'IhorKopieichykov_third_contact' - ); + ), 'IhorKopieichykov_third_contact'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_attached_file (talent_id, attached_file) -values ( - ( +values (( select id from talent order by id desc limit 1 - ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' - ); + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'); insert into talent_proofs (talent_id, link, text, status, created) -values ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +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' - ); + ), '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 ( - ( +values (( select id from talent order by id desc limit 1 - ), 'IhorKopieichykov@gmail.com', '$2a$10$D4KM50WemOahkFv1fkrPX.MvVESsE0TYWlkh5TypTE/q4nlv8ooyS' - ); + ), 'IhorKopieichykov@gmail.com', '$2a$10$D4KM50WemOahkFv1fkrPX.MvVESsE0TYWlkh5TypTE/q4nlv8ooyS'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 1 - ) - ); + )); -- Sponsor -- Maksym Khudoliy insert into sponsor (amount_kudos, first_name, last_name, image) -values ( - 888, +values (888, 'Maksym', 'Khudoliy', - 'https://i.pinimg.com/564x/e1/08/49/e10849923a8b2e85a7adf494ebd063e6.jpg' - ); + 'https://i.pinimg.com/564x/e1/08/49/e10849923a8b2e85a7adf494ebd063e6.jpg'); insert into user_info (sponsor_id, login, password) -values ( - ( +values (( select id from sponsor order by id desc limit 1 - ), 'MaksymKhudoliy@gmail.com', '$2a$10$pDrAuawhi3ADZpVDDr7C6eAcaQwDr5oQ9GdZUUZHSsqyM/vVkpruy' - ); + ), 'MaksymKhudoliy@gmail.com', '$2a$10$pDrAuawhi3ADZpVDDr7C6eAcaQwDr5oQ9GdZUUZHSsqyM/vVkpruy'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 2 - ) - ); + )); -- Oleksandr Butrym insert into sponsor (amount_kudos, first_name, last_name, image) -values ( - 888, +values (888, 'Oleksandr', 'Butrym', - 'https://i.pinimg.com/564x/c2/41/31/c24131fe00218467721ba5bacdf0a256.jpg' - ); + 'https://i.pinimg.com/564x/c2/41/31/c24131fe00218467721ba5bacdf0a256.jpg'); insert into user_info (sponsor_id, login, password) -values ( - ( +values (( select id from sponsor order by id desc limit 1 - ), 'OleksandrButrym@gmail.com', '$2a$10$R0o8os0t86qyBvg0bO/a6ukuy9VesLapxIkZFLjNupWjvr5Hdjyge' - ); + ), 'OleksandrButrym@gmail.com', '$2a$10$R0o8os0t86qyBvg0bO/a6ukuy9VesLapxIkZFLjNupWjvr5Hdjyge'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 2 - ) - ); + )); -- Olha Shutylieva insert into sponsor (amount_kudos, first_name, last_name, image) -values ( - 888, +values (888, 'Olha', 'Shutylieva', - 'https://i.pinimg.com/564x/2a/0c/08/2a0c08c421e253ca895c3fdc8c9e08d9.jpg' - ); + 'https://i.pinimg.com/564x/2a/0c/08/2a0c08c421e253ca895c3fdc8c9e08d9.jpg'); insert into user_info (sponsor_id, login, password) -values ( - ( +values (( select id from sponsor order by id desc limit 1 - ), 'OlhaShutylieva@gmail.com', '$2a$10$UzwVTVR7E2BW.5hA4XWgy.g0XcM.UbIMBoY1cDnYNPQDhCXEa7eGm' - ); + ), 'OlhaShutylieva@gmail.com', '$2a$10$UzwVTVR7E2BW.5hA4XWgy.g0XcM.UbIMBoY1cDnYNPQDhCXEa7eGm'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 2 - ) - ); + )); -- Vladyslav Khrychov insert into sponsor (amount_kudos, first_name, last_name, image) -values ( - 888, +values (888, 'Vladyslav', 'Khrychov', - 'https://i.pinimg.com/564x/e1/11/2f/e1112f0b7b63644dc3e313084936dedb.jpg' - ); + 'https://i.pinimg.com/564x/e1/11/2f/e1112f0b7b63644dc3e313084936dedb.jpg'); insert into user_info (sponsor_id, login, password) -values ( - ( +values (( select id from sponsor order by id desc limit 1 - ), 'VladyslavKhrychov@gmail.com', '$2a$10$o2va23ZPVVSptyCaSBO/oubpML4xEPZo9Ie0ASt154zNVSKdFrN02' - ); + ), 'VladyslavKhrychov@gmail.com', '$2a$10$o2va23ZPVVSptyCaSBO/oubpML4xEPZo9Ie0ASt154zNVSKdFrN02'); insert into user_authorities (user_id, authority_id) -values ( - ( +values (( select id from user_info order by id desc limit 1 - ), ( + ), ( select authority.id from authority where id = 2 - ) - ); + )); -- Kudos insert into kudos (amount, sponsor_id, proof_id) values (100, 1, 1); diff --git a/src/main/resources/db/changelog/changeset/V4/schema-V4.sql b/src/main/resources/db/changelog/changeset/V4/schema-V4.sql index 9355c9b..7608822 100644 --- a/src/main/resources/db/changelog/changeset/V4/schema-V4.sql +++ b/src/main/resources/db/changelog/changeset/V4/schema-V4.sql @@ -2,128 +2,142 @@ -- changeset Ren:0 -- tables for sprint 4.1 -- Talent -CREATE TABLE talent ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - first_name VARCHAR(20), - last_name VARCHAR(20), +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), + 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, +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), +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), +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), +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, +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_skill ( +CREATE TABLE talent_skill +( talent_id BIGINT NOT NULL, - skill_id BIGINT NOT NULL, + skill_id BIGINT NOT NULL, CONSTRAINT pk_talent_skill PRIMARY KEY (talent_id, skill_id) ); -CREATE TABLE proof_skill ( +CREATE TABLE proof_skill +( proof_id BIGINT NOT NULL, skill_id BIGINT NOT NULL, CONSTRAINT pk_proof_skill PRIMARY KEY (proof_id, skill_id) ); -CREATE TABLE skill ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, +CREATE TABLE skill +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, skill VARCHAR(30), CONSTRAINT pk_skill PRIMARY KEY (id) ); -- User -CREATE TABLE user_info ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - talent_id BIGINT, +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, + login VARCHAR(100) NOT NULL, + password VARCHAR(255) NOT NULL, CONSTRAINT pk_user_info PRIMARY KEY (id) ); -CREATE TABLE authority ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - authority VARCHAR(20) NOT NULL, +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 user_authorities ( +CREATE TABLE user_authorities +( authority_id BIGINT NOT NULL, - user_id BIGINT NOT NULL, + user_id BIGINT NOT NULL, CONSTRAINT pk_user_authorities PRIMARY KEY (authority_id, user_id) ); -- Sponsor -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), +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) ); -CREATE TABLE kudos ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, +CREATE TABLE kudos +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, sponsor_id BIGINT, - proof_id BIGINT, - amount BIGINT, + proof_id BIGINT, + amount BIGINT, CONSTRAINT pk_kudos PRIMARY KEY (id) ); -- Foreign keys ALTER TABLE talent_attached_file -ADD CONSTRAINT FK_TALENT_ATTACHED_FILE_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); + 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); + 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); + 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); + 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); + ADD CONSTRAINT FK_TALENT_PROOFS_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); + 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); + 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); + 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); + 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); + ADD CONSTRAINT FK_KUDOS_ON_SPONSOR FOREIGN KEY (sponsor_id) REFERENCES sponsor (id); ALTER TABLE proof_skill -ADD CONSTRAINT FK_proof_skill_ON_TALENT_PROOF FOREIGN KEY (proof_id) REFERENCES talent_proofs (id); + ADD CONSTRAINT FK_proof_skill_ON_TALENT_PROOF FOREIGN KEY (proof_id) REFERENCES talent_proofs (id); ALTER TABLE proof_skill -ADD CONSTRAINT FK_proof_skill_ON_SKILL FOREIGN KEY (skill_id) REFERENCES skill (id); + ADD CONSTRAINT FK_proof_skill_ON_SKILL FOREIGN KEY (skill_id) REFERENCES skill (id); ALTER TABLE talent_skill -ADD CONSTRAINT FK_talent_skill_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); + ADD CONSTRAINT FK_talent_skill_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); ALTER TABLE talent_skill -ADD CONSTRAINT FK_talent_skill_ON_SKILL FOREIGN KEY (skill_id) REFERENCES skill (id); + ADD CONSTRAINT FK_talent_skill_ON_SKILL FOREIGN KEY (skill_id) REFERENCES skill (id); -- Indexes CREATE UNIQUE INDEX idx_login ON user_info (login) \ 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 102ca3c..e5dec38 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -11,3 +11,5 @@ databaseChangeLog: file: db/changelog/changeset/V4/data-V4.sql - include: file: db/changelog/changeset/V4/data-V4.1.sql + - include: + file: db/changelog/changeset/V4/data-V4.2.sql From 22accbcb5995cd2041108025b708e774ed81a676 Mon Sep 17 00:00:00 2001 From: Maslyna Date: Tue, 16 May 2023 19:50:00 +0200 Subject: [PATCH 32/59] Code refactor: JWT token update --- .../user/model/dto/UserInfoDTO.java | 4 +-- .../impl/AuthenticationServiceImpl.java | 36 +++++++++---------- 2 files changed, 17 insertions(+), 23 deletions(-) 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 4c2671d..67985e9 100644 --- a/src/main/java/com/provedcode/user/model/dto/UserInfoDTO.java +++ b/src/main/java/com/provedcode/user/model/dto/UserInfoDTO.java @@ -4,8 +4,6 @@ @Builder public record UserInfoDTO( - String token, - Long id, - String role + String token ) { } \ No newline at end of file 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 9fbd2b2..dbcce3e 100644 --- a/src/main/java/com/provedcode/user/service/impl/AuthenticationServiceImpl.java +++ b/src/main/java/com/provedcode/user/service/impl/AuthenticationServiceImpl.java @@ -15,9 +15,11 @@ import com.provedcode.user.service.AuthenticationService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.catalina.User; import org.springframework.http.HttpStatus; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.oauth2.jwt.JwtClaimsSet; import org.springframework.security.oauth2.jwt.JwtEncoder; import org.springframework.security.oauth2.jwt.JwtEncoderParameters; @@ -28,6 +30,7 @@ import java.time.Instant; import java.util.Collection; import java.util.Set; +import java.util.function.BiFunction; import java.util.stream.Collectors; import static java.time.temporal.ChronoUnit.MINUTES; @@ -53,12 +56,10 @@ public UserInfoDTO login(String name, Collection aut Role userRole = userInfo.getAuthorities().stream().findFirst().orElseThrow().getAuthority(); - return UserInfoDTO.builder() - .token(generateJWTToken(name, authorities)) - .id(userRole.equals(Role.TALENT) ? userInfo.getTalent().getId() - : userInfo.getSponsor().getId()) - .role(userRole.name()) - .build(); + BiFunction getUserIdFunction = (user, role) -> role.equals(Role.TALENT) ? user.getTalent().getId() + : user.getSponsor().getId(); + + return new UserInfoDTO(generateJWTToken(getUserIdFunction.apply(userInfo, userRole), name, authorities).getTokenValue()); } public UserInfoDTO register(TalentRegistrationDTO user) { @@ -88,11 +89,7 @@ public UserInfoDTO register(TalentRegistrationDTO 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()) - .role(Role.TALENT.name()) - .build(); + return new UserInfoDTO(generateJWTToken(talent.getId(), userLogin, userAuthorities).getTokenValue()); } public UserInfoDTO register(SponsorRegistrationDTO user) { @@ -123,25 +120,24 @@ public UserInfoDTO register(SponsorRegistrationDTO user) { log.info("user with login {%s} was saved, his authorities: %s".formatted(userLogin, userAuthorities)); - return UserInfoDTO.builder() - .token(generateJWTToken(userLogin, userAuthorities)) - .id(sponsor.getId()) - .role(Role.SPONSOR.name()) - .build(); + return new UserInfoDTO(generateJWTToken(sponsor.getId(), userLogin, userAuthorities).getTokenValue()); } - private String generateJWTToken(String name, Collection authorities) { - log.info("=== POST /login === auth.name = {}", name); + private Jwt generateJWTToken(Long id, String login, Collection authorities) { + log.info("=== POST /login === auth.login = {}", login); log.info("=== POST /login === auth = {}", authorities); var now = Instant.now(); var claims = JwtClaimsSet.builder() .issuer("self") .issuedAt(now) .expiresAt(now.plus(60, MINUTES)) - .subject(name) + .subject(login) .claim("scope", authorities.stream().map(GrantedAuthority::getAuthority) .collect(Collectors.joining(" "))) + .claim("role", authorities.stream().map(GrantedAuthority::getAuthority) + .collect(Collectors.joining(" ")).replace("ROLE_", "")) + .claim("id", id) .build(); - return jwtEncoder.encode(JwtEncoderParameters.from(claims)).getTokenValue(); + return jwtEncoder.encode(JwtEncoderParameters.from(claims)); } } \ No newline at end of file From d2c1cefc51e9607933945f01605d454447e77cd7 Mon Sep 17 00:00:00 2001 From: Ren Date: Wed, 17 May 2023 22:21:29 +0300 Subject: [PATCH 33/59] feat: Add tables for talent and sponsorship data This commit adds tables for talent skills and proofs. Sponsorship tables are also added, including sponsorship kudos. Foreign keys and indexes are defined. Signed-off-by: Ren --- .../db/changelog/changeset/V5/schema-V5.sql | 133 ++++++++++++++++++ .../db/changelog/db.changelog-master.yaml | 28 ++-- 2 files changed, 147 insertions(+), 14 deletions(-) create mode 100644 src/main/resources/db/changelog/changeset/V5/schema-V5.sql diff --git a/src/main/resources/db/changelog/changeset/V5/schema-V5.sql b/src/main/resources/db/changelog/changeset/V5/schema-V5.sql new file mode 100644 index 0000000..9d914a8 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V5/schema-V5.sql @@ -0,0 +1,133 @@ +-- liquibase formatted sql +-- changeset Ren:0 +-- tables for sprint 5 +-- Talent +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_skill ( + talent_id BIGINT NOT NULL, + skill_id BIGINT NOT NULL, + CONSTRAINT pk_talent_skill PRIMARY KEY (talent_id, skill_id) +); +CREATE TABLE proof_skill ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + proof_id BIGINT NOT NULL, + skill_id BIGINT NOT NULL, + CONSTRAINT pk_proof_skill PRIMARY KEY (id) +); +CREATE TABLE skill ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + skill VARCHAR(30), + CONSTRAINT pk_skill PRIMARY KEY (id) +); +-- User +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 authority ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + authority VARCHAR(20) NOT NULL, + CONSTRAINT pk_authority 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) +); +-- Sponsor +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) +); +CREATE TABLE kudos ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + sponsor_id BIGINT, + proof_id BIGINT, + proof_skill_id BIGINT, + amount BIGINT, + CONSTRAINT pk_kudos PRIMARY KEY (id) +); +-- Foreign keys +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 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); +ALTER TABLE kudos +ADD CONSTRAINT FK_KUDOS_ON_PROOF_SKILL FOREIGN KEY (proof_skill_id) REFERENCES proof_skill(id); +ALTER TABLE proof_skill +ADD CONSTRAINT FK_proof_skill_ON_TALENT_PROOF FOREIGN KEY (proof_id) REFERENCES talent_proofs (id); +ALTER TABLE proof_skill +ADD CONSTRAINT FK_proof_skill_ON_SKILL FOREIGN KEY (skill_id) REFERENCES skill (id); +ALTER TABLE talent_skill +ADD CONSTRAINT FK_talent_skill_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); +ALTER TABLE talent_skill +ADD CONSTRAINT FK_talent_skill_ON_SKILL FOREIGN KEY (skill_id) REFERENCES skill (id); +-- Indexes +CREATE UNIQUE INDEX idx_login ON user_info (login) \ 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 e5dec38..428c0cf 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -1,15 +1,15 @@ databaseChangeLog: - - include: - file: db/changelog/changeset/V1/drop-V1.sql - - include: - file: db/changelog/changeset/V2/drop-V2.sql - - include: - file: db/changelog/changeset/V4/drop-V4.sql - - include: - file: db/changelog/changeset/V4/schema-V4.sql - - include: - file: db/changelog/changeset/V4/data-V4.sql - - include: - file: db/changelog/changeset/V4/data-V4.1.sql - - include: - file: db/changelog/changeset/V4/data-V4.2.sql +# - include: +# file: db/changelog/changeset/V1/drop-V1.sql +# - include: +# file: db/changelog/changeset/V2/drop-V2.sql +# - include: +# file: db/changelog/changeset/V4/drop-V4.sql + - include: + file: db/changelog/changeset/V5/schema-V5.sql +# - include: +# file: db/changelog/changeset/V4/data-V4.sql +# - include: +# file: db/changelog/changeset/V4/data-V4.1.sql +# - include: +# file: db/changelog/changeset/V4/data-V4.2.sql From 58155cb5198498b70f19652d282c6ea8b747a7a6 Mon Sep 17 00:00:00 2001 From: Ren Date: Wed, 17 May 2023 22:39:29 +0300 Subject: [PATCH 34/59] Add ProofSkill entity and refactor TalentProof entity to use it. The changes in this commit add a new "ProofSkill" entity and update the "TalentProof" entity to use it for the skills previously stored in a direct many-to-many relationship. This represents a more structured approach to modeling the relationship and better decouples the entities involved. Signed-off-by: Ren --- .../talent/model/entity/ProofSkill.java | 48 +++++++++++++++++++ .../talent/model/entity/TalentProof.java | 5 +- 2 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/provedcode/talent/model/entity/ProofSkill.java diff --git a/src/main/java/com/provedcode/talent/model/entity/ProofSkill.java b/src/main/java/com/provedcode/talent/model/entity/ProofSkill.java new file mode 100644 index 0000000..96f2245 --- /dev/null +++ b/src/main/java/com/provedcode/talent/model/entity/ProofSkill.java @@ -0,0 +1,48 @@ +package com.provedcode.talent.model.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.Hibernate; + +import java.util.Objects; + +@Builder +@Entity +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@Table(name = "proof_skill") +public class ProofSkill { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(nullable = false, insertable = false, updatable = false) + private Long id; + + @ManyToOne + @JoinColumn(name = "proof_id") + private TalentProof talentProof; + + @ManyToOne + @JoinColumn(name = "skill_id") + private Skills skill; + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) + return false; + ProofSkill that = (ProofSkill) o; + return getId() != null && Objects.equals(getId(), that.getId()); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } +} diff --git a/src/main/java/com/provedcode/talent/model/entity/TalentProof.java b/src/main/java/com/provedcode/talent/model/entity/TalentProof.java index a4ffd86..b0c5a8f 100644 --- a/src/main/java/com/provedcode/talent/model/entity/TalentProof.java +++ b/src/main/java/com/provedcode/talent/model/entity/TalentProof.java @@ -63,7 +63,6 @@ public class TalentProof { private LocalDateTime created; @OneToMany(fetch = FetchType.EAGER, mappedBy = "proof", cascade = CascadeType.ALL, orphanRemoval = true) private List kudos; - @ManyToMany - @JoinTable(name = "proof_skill", joinColumns = @JoinColumn(name = "proof_id"), inverseJoinColumns = @JoinColumn(name = "skill_id")) - private Set skills = new LinkedHashSet<>(); + @OneToMany(mappedBy = "talentProof", cascade = CascadeType.ALL, orphanRemoval = true) + private Set proofSkills = new LinkedHashSet<>(); } \ No newline at end of file From 348b6ea652e9766ab391f3c0595d19a496e3f0fb Mon Sep 17 00:00:00 2001 From: Ren Date: Thu, 18 May 2023 20:49:44 +0300 Subject: [PATCH 35/59] Refactor Kudos entity to use ProofSkill instead of TalentProof in the skill field The Kudos entity is refactored to use the ProofSkill entity in the skill field instead of the TalentProof entity. ProofSkill entity is updated to add a OneToMany relationship to Kudos entity. The TalentProof entity is updated to remove the OneToMany relationship to Kudos entity. Signed-off-by: Ren --- src/main/java/com/provedcode/kudos/model/entity/Kudos.java | 7 ++++--- .../com/provedcode/talent/model/entity/ProofSkill.java | 7 +++++++ .../com/provedcode/talent/model/entity/TalentProof.java | 2 -- 3 files changed, 11 insertions(+), 5 deletions(-) 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 259c387..45e118d 100644 --- a/src/main/java/com/provedcode/kudos/model/entity/Kudos.java +++ b/src/main/java/com/provedcode/kudos/model/entity/Kudos.java @@ -1,6 +1,7 @@ package com.provedcode.kudos.model.entity; import com.provedcode.sponsor.model.entity.Sponsor; +import com.provedcode.talent.model.entity.ProofSkill; import com.provedcode.talent.model.entity.TalentProof; import jakarta.persistence.*; import lombok.*; @@ -22,7 +23,7 @@ public class Kudos { @ManyToOne @JoinColumn(name = "sponsor_id") private Sponsor sponsor; - @ManyToOne(cascade = CascadeType.ALL) - @JoinColumn(name = "proof_id") - private TalentProof proof; + @ManyToOne + @JoinColumn(name = "proof_skill_id") + private ProofSkill skill; } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/model/entity/ProofSkill.java b/src/main/java/com/provedcode/talent/model/entity/ProofSkill.java index 96f2245..a61bbc7 100644 --- a/src/main/java/com/provedcode/talent/model/entity/ProofSkill.java +++ b/src/main/java/com/provedcode/talent/model/entity/ProofSkill.java @@ -8,6 +8,10 @@ import lombok.Setter; import org.hibernate.Hibernate; +import com.provedcode.kudos.model.entity.Kudos; + +import java.util.ArrayList; +import java.util.List; import java.util.Objects; @Builder @@ -31,6 +35,9 @@ public class ProofSkill { @JoinColumn(name = "skill_id") private Skills skill; + @OneToMany(mappedBy = "skill", orphanRemoval = true) + private List kudoses = new ArrayList<>(); + @Override public boolean equals(Object o) { if (this == o) diff --git a/src/main/java/com/provedcode/talent/model/entity/TalentProof.java b/src/main/java/com/provedcode/talent/model/entity/TalentProof.java index b0c5a8f..4f4f178 100644 --- a/src/main/java/com/provedcode/talent/model/entity/TalentProof.java +++ b/src/main/java/com/provedcode/talent/model/entity/TalentProof.java @@ -61,8 +61,6 @@ public class TalentProof { @Column(length = 20) private ProofStatus status; private LocalDateTime created; - @OneToMany(fetch = FetchType.EAGER, mappedBy = "proof", cascade = CascadeType.ALL, orphanRemoval = true) - private List kudos; @OneToMany(mappedBy = "talentProof", cascade = CascadeType.ALL, orphanRemoval = true) private Set proofSkills = new LinkedHashSet<>(); } \ No newline at end of file From 39a4dbb35a898aec2233dc186b2a5be312642b35 Mon Sep 17 00:00:00 2001 From: Denis Boyko Date: Fri, 19 May 2023 16:20:25 +0300 Subject: [PATCH 36/59] fix bug --- .../kudos/controller/KudosController.java | 88 +++---- .../kudos/repository/KudosRepository.java | 10 +- .../kudos/service/KudosService.java | 244 +++++++++--------- .../talent/controller/TalentController.java | 14 +- .../controller/TalentProofController.java | 16 +- .../controller/TalentSkillsController.java | 44 ++-- .../talent/model/entity/Skills.java | 2 - .../talent/service/ProofSkillsService.java | 162 ++++++------ .../talent/service/TalentProofService.java | 36 +-- .../talent/service/TalentService.java | 54 ++-- .../db/changelog/changeset/V5/drop-V5.sql | 19 ++ .../db/changelog/db.changelog-master.yaml | 34 ++- 12 files changed, 373 insertions(+), 350 deletions(-) create mode 100644 src/main/resources/db/changelog/changeset/V5/drop-V5.sql diff --git a/src/main/java/com/provedcode/kudos/controller/KudosController.java b/src/main/java/com/provedcode/kudos/controller/KudosController.java index 7f18175..edef91e 100644 --- a/src/main/java/com/provedcode/kudos/controller/KudosController.java +++ b/src/main/java/com/provedcode/kudos/controller/KudosController.java @@ -1,48 +1,48 @@ package com.provedcode.kudos.controller; -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 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 +//@Validated +//@RequestMapping("/api/v3/") +//public class KudosController { +// KudosService kudosService; -import java.util.Optional; +// @GetKudosForSponsorApiDoc +// @PreAuthorize("hasRole('SPONSOR')") +// @GetMapping("/sponsors/{sponsor-id}/kudos") +// KudosAmount getKudosForSponsor(@PathVariable("sponsor-id") long sponsorId, Authentication authentication) { +// return kudosService.getKudosForSponsor(sponsorId, authentication); +// } -@RestController -@AllArgsConstructor -@Validated -@RequestMapping("/api/v3/") -public class KudosController { - KudosService kudosService; - - @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')") - @GetMapping("/proofs/{proof-id}/kudos") - KudosAmountWithSponsor getProofKudos(@PathVariable("proof-id") long proofId, Authentication authentication) { - return kudosService.getProofKudos(proofId, 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 +// @GetAmountOfKudosApiDoc +// @PreAuthorize("hasRole('TALENT')") +// @GetMapping("/proofs/{proof-id}/kudos") +// KudosAmountWithSponsor getProofKudos(@PathVariable("proof-id") long proofId, Authentication authentication) { +// return kudosService.getProofKudos(proofId, 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/repository/KudosRepository.java b/src/main/java/com/provedcode/kudos/repository/KudosRepository.java index 3b0f629..e18d47e 100644 --- a/src/main/java/com/provedcode/kudos/repository/KudosRepository.java +++ b/src/main/java/com/provedcode/kudos/repository/KudosRepository.java @@ -3,8 +3,8 @@ import com.provedcode.kudos.model.entity.Kudos; import org.springframework.data.jpa.repository.JpaRepository; -public interface KudosRepository extends JpaRepository { - long countByProofId(Long id); - - boolean existsBySponsorIdAndProofId(Long sponsorId, Long proofId); -} \ No newline at end of file +//public interface KudosRepository extends JpaRepository { +// long countByProofId(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 599999b..e392c02 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -1,127 +1,127 @@ 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; -import com.provedcode.talent.repo.TalentProofRepository; -import com.provedcode.talent.repo.TalentRepository; -import com.provedcode.user.model.entity.UserInfo; -import com.provedcode.user.repo.UserInfoRepository; -import lombok.AllArgsConstructor; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.server.ResponseStatusException; +//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; +//import com.provedcode.talent.repo.TalentProofRepository; +//import com.provedcode.talent.repo.TalentRepository; +//import com.provedcode.user.model.entity.UserInfo; +//import com.provedcode.user.repo.UserInfoRepository; +//import lombok.AllArgsConstructor; +//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.HashMap; +//import java.util.Map; +//import java.util.Optional; +//import java.util.stream.Collectors; +// +//import static org.springframework.http.HttpStatus.*; +// +//@Service +//@AllArgsConstructor +//@Transactional +//public class KudosService { +// KudosRepository kudosRepository; +// TalentProofRepository talentProofRepository; +// UserInfoRepository userInfoRepository; +// SponsorRepository sponsorRepository; +// TalentRepository talentRepository; +// SponsorMapper sponsorMapper; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; +// 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"); +// } +// sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); +// kudosRepository.save(Kudos.builder() +// .amount(obtainedAmount) +// .proof(talentProof) +// .sponsor(sponsor) +// .build()); +// } -import static org.springframework.http.HttpStatus.*; +// @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"); +// } +// Sponsor sponsor = sponsorRepository.findById(sponsorId).orElseThrow( +// () -> new ResponseStatusException(NOT_FOUND, +// String.format("Sponsor with id = %d not found", sponsorId))); +// return new KudosAmount(sponsor.getAmountKudos()); +// } -@Service -@AllArgsConstructor -@Transactional -public class KudosService { - KudosRepository kudosRepository; - TalentProofRepository talentProofRepository; - UserInfoRepository userInfoRepository; - 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"); - } - sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); - kudosRepository.save(Kudos.builder() - .amount(obtainedAmount) - .proof(talentProof) - .sponsor(sponsor) - .build()); - } - - @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"); - } - Sponsor sponsor = sponsorRepository.findById(sponsorId).orElseThrow( - () -> new ResponseStatusException(NOT_FOUND, - String.format("Sponsor with id = %d not found", sponsorId))); - return new KudosAmount(sponsor.getAmountKudos()); - } - - @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.getTalent().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 (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(); - } - } -} \ No newline at end of file +// @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.getTalent().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 (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(); +// } +// } +//} \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/controller/TalentController.java b/src/main/java/com/provedcode/talent/controller/TalentController.java index ecff1f5..9e41f63 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentController.java @@ -67,13 +67,13 @@ SessionInfoDTO deleteTalent(@PathVariable("id") long id, Authentication authenti return talentService.deleteTalentById(id, authentication); } - @PreAuthorize("hasRole('TALENT')") - @PostMapping("v4/talents/{talent-id}/skills") - void addSkillOnTalent(@PathVariable("talent-id") long id, - @RequestBody @Valid SkillIdDTO skillIdDTO, - Authentication authentication) { - talentService.addSkillOnTalent(id, skillIdDTO, authentication); - } +// @PreAuthorize("hasRole('TALENT')") +// @PostMapping("v4/talents/{talent-id}/skills") +// void addSkillOnTalent(@PathVariable("talent-id") long id, +// @RequestBody @Valid SkillIdDTO skillIdDTO, +// Authentication authentication) { +// talentService.addSkillOnTalent(id, skillIdDTO, authentication); +// } @PreAuthorize("hasRole('TALENT')") @DeleteMapping("v4/talents/{talent-id}/skills/{skill-id}") diff --git a/src/main/java/com/provedcode/talent/controller/TalentProofController.java b/src/main/java/com/provedcode/talent/controller/TalentProofController.java index ff89e09..1613c67 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentProofController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentProofController.java @@ -85,12 +85,12 @@ ProofDTO editProof(Authentication authentication, talentProofService.editTalentProof(talentId, proofId, proof, authentication)); } - @DeleteProofApiDoc - @DeleteMapping("/{talent-id}/proofs/{proof-id}") - @PreAuthorize("hasRole('TALENT')") - void deleteProof(@PathVariable(value = "talent-id") long talentId, - @PathVariable(value = "proof-id") long proofId, - Authentication authentication) { - talentProofService.deleteProofById(talentId, proofId, authentication); - } +// @DeleteProofApiDoc +// @DeleteMapping("/{talent-id}/proofs/{proof-id}") +// @PreAuthorize("hasRole('TALENT')") +// void deleteProof(@PathVariable(value = "talent-id") long talentId, +// @PathVariable(value = "proof-id") long proofId, +// Authentication authentication) { +// talentProofService.deleteProofById(talentId, proofId, authentication); +// } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java b/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java index e477280..c0cebf0 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java @@ -20,26 +20,26 @@ public class TalentSkillsController { ProofSkillsService talentSkillsService; - @PostMapping("/{talent-id}/proofs/{proof-id}/skills") - void addSkillOnProof(@PathVariable("talent-id") long talentId, - @PathVariable("proof-id") long proofId, - @RequestBody @Valid ProofSkillsDTO skills, - Authentication authentication) { - talentSkillsService.addSkillsOnProof(talentId, proofId, skills, authentication); - } - - @GetMapping("/{talent-id}/proofs/{proof-id}/skills") - SkillsOnProofDTO getAllSkillsOnProof(@PathVariable("talent-id") long talentId, - @PathVariable("proof-id") long proofId, - Authentication authentication) { - return talentSkillsService.getAllSkillsOnProof(talentId, proofId, authentication); - } - @PreAuthorize("hasRole('TALENT')") - @DeleteMapping("/{talent-id}/proofs/{proof-id}/skills/{skill-id}") - void deleteSkillOnProof(@PathVariable("talent-id") long talentId, - @PathVariable("proof-id") long proofId, - @PathVariable("skill-id") long skillId, - Authentication authentication) { - talentSkillsService.deleteSkillOnProof(talentId, proofId, skillId, authentication); - } +// @PostMapping("/{talent-id}/proofs/{proof-id}/skills") +// void addSkillOnProof(@PathVariable("talent-id") long talentId, +// @PathVariable("proof-id") long proofId, +// @RequestBody @Valid ProofSkillsDTO skills, +// Authentication authentication) { +// talentSkillsService.addSkillsOnProof(talentId, proofId, skills, authentication); +// } +// +// @GetMapping("/{talent-id}/proofs/{proof-id}/skills") +// SkillsOnProofDTO getAllSkillsOnProof(@PathVariable("talent-id") long talentId, +// @PathVariable("proof-id") long proofId, +// Authentication authentication) { +// return talentSkillsService.getAllSkillsOnProof(talentId, proofId, authentication); +// } +// @PreAuthorize("hasRole('TALENT')") +// @DeleteMapping("/{talent-id}/proofs/{proof-id}/skills/{skill-id}") +// void deleteSkillOnProof(@PathVariable("talent-id") long talentId, +// @PathVariable("proof-id") long proofId, +// @PathVariable("skill-id") long skillId, +// Authentication authentication) { +// talentSkillsService.deleteSkillOnProof(talentId, proofId, skillId, authentication); +// } } diff --git a/src/main/java/com/provedcode/talent/model/entity/Skills.java b/src/main/java/com/provedcode/talent/model/entity/Skills.java index a87af65..2bc15bd 100644 --- a/src/main/java/com/provedcode/talent/model/entity/Skills.java +++ b/src/main/java/com/provedcode/talent/model/entity/Skills.java @@ -28,8 +28,6 @@ public class Skills { @Column(name = "skill", length = 30) private String skill; @ManyToMany(mappedBy = "skills") - private Set talentProofs = new LinkedHashSet<>(); - @ManyToMany(mappedBy = "skills") private Set talents = new LinkedHashSet<>(); @Override diff --git a/src/main/java/com/provedcode/talent/service/ProofSkillsService.java b/src/main/java/com/provedcode/talent/service/ProofSkillsService.java index 55580f4..a851c7d 100644 --- a/src/main/java/com/provedcode/talent/service/ProofSkillsService.java +++ b/src/main/java/com/provedcode/talent/service/ProofSkillsService.java @@ -44,87 +44,87 @@ public class ProofSkillsService { } }; - public void addSkillsOnProof(long talentId, long proofId, ProofSkillsDTO skills, Authentication authentication) { - if (!talentRepository.existsById(talentId)) { - throw new ResponseStatusException(NOT_FOUND, "talent with id = %s not found".formatted(talentId)); - } - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); - TalentProof talentProof = talentProofRepository.findById(proofId) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "proof with id = %s not found".formatted(proofId))); - if (!talentProof.getStatus().equals(ProofStatus.DRAFT)) { - throw new ResponseStatusException(CONFLICT, "proof status must be DRAFT"); - } - - isValidUserEditTalent.accept(talentId, userInfo); - skills.skills().forEach(skillId -> { - if (!skillsRepository.existsById(skillId)) - throw new ResponseStatusException(NOT_FOUND, "no such skill with id = " + skillId); - }); - - Set skillsSet = new HashSet<>(skillsRepository.findAllById(skills.skills())); - talentProof.getSkills().forEach(skill -> { - if (skillsSet.contains(skill)) - throw new ResponseStatusException(CONFLICT, - "skill with id = %s already on skill".formatted(skill.getId())); - }); - - talentProof.getSkills().addAll(skillsSet); - talentProofRepository.save(talentProof); - } +// public void addSkillsOnProof(long talentId, long proofId, ProofSkillsDTO skills, Authentication authentication) { +// if (!talentRepository.existsById(talentId)) { +// throw new ResponseStatusException(NOT_FOUND, "talent with id = %s not found".formatted(talentId)); +// } +// UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) +// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); +// TalentProof talentProof = talentProofRepository.findById(proofId) +// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "proof with id = %s not found".formatted(proofId))); +// if (!talentProof.getStatus().equals(ProofStatus.DRAFT)) { +// throw new ResponseStatusException(CONFLICT, "proof status must be DRAFT"); +// } +// +// isValidUserEditTalent.accept(talentId, userInfo); +// skills.skills().forEach(skillId -> { +// if (!skillsRepository.existsById(skillId)) +// throw new ResponseStatusException(NOT_FOUND, "no such skill with id = " + skillId); +// }); +// +// Set skillsSet = new HashSet<>(skillsRepository.findAllById(skills.skills())); +// talentProof.getSkills().forEach(skill -> { +// if (skillsSet.contains(skill)) +// throw new ResponseStatusException(CONFLICT, +// "skill with id = %s already on skill".formatted(skill.getId())); +// }); +// +// talentProof.getSkills().addAll(skillsSet); +// talentProofRepository.save(talentProof); +// } - @Transactional(readOnly = true) - public SkillsOnProofDTO getAllSkillsOnProof(long talentId, long proofId, Authentication authentication) { - TalentProof talentProof = talentProofRepository.findById(proofId) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "proof with id = %s not found".formatted(proofId))); - Talent talent = talentRepository.findById(talentId) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "talent with id = %s not found".formatted(talentId))); - if (!talent.getId().equals(talentProof.getTalent().getId())) { - throw new ResponseStatusException(BAD_REQUEST, - "talentId with id = %s and proofId with id = %s do not match".formatted(talentId, proofId)); - } - Set skills = talentProof.getSkills().stream() - .map(skillMapper::skillToSkillDTO).collect(Collectors.toSet()); - if (talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { - return SkillsOnProofDTO.builder().skills(skills).build(); - } else if (authentication != null) { - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); - if (userInfo.getTalent().getId().equals(talentProof.getTalent().getId())) { - return SkillsOnProofDTO.builder().skills(skills).build(); - } else { - throw new ResponseStatusException(FORBIDDEN, "you can't see proofs in DRAFT and HIDDEN status"); - } - } else { - throw new ResponseStatusException(FORBIDDEN, "you can't see proofs in DRAFT and HIDDEN status"); - } - } +// @Transactional(readOnly = true) +// public SkillsOnProofDTO getAllSkillsOnProof(long talentId, long proofId, Authentication authentication) { +// TalentProof talentProof = talentProofRepository.findById(proofId) +// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, +// "proof with id = %s not found".formatted(proofId))); +// Talent talent = talentRepository.findById(talentId) +// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, +// "talent with id = %s not found".formatted(talentId))); +// if (!talent.getId().equals(talentProof.getTalent().getId())) { +// throw new ResponseStatusException(BAD_REQUEST, +// "talentId with id = %s and proofId with id = %s do not match".formatted(talentId, proofId)); +// } +// Set skills = talentProof.getSkills().stream() +// .map(skillMapper::skillToSkillDTO).collect(Collectors.toSet()); +// if (talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { +// return SkillsOnProofDTO.builder().skills(skills).build(); +// } else if (authentication != null) { +// UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) +// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); +// if (userInfo.getTalent().getId().equals(talentProof.getTalent().getId())) { +// return SkillsOnProofDTO.builder().skills(skills).build(); +// } else { +// throw new ResponseStatusException(FORBIDDEN, "you can't see proofs in DRAFT and HIDDEN status"); +// } +// } else { +// throw new ResponseStatusException(FORBIDDEN, "you can't see proofs in DRAFT and HIDDEN status"); +// } +// } - public void deleteSkillOnProof(long talentId, long proofId, long skillId, Authentication authentication) { - Talent talent = talentRepository.findById(talentId) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "talent with id = %s not found".formatted(talentId))); - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); - TalentProof talentProof = talentProofRepository.findById(proofId) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "proof with id = %s not found".formatted(proofId))); - if (!talentProof.getStatus().equals(ProofStatus.DRAFT)) { - throw new ResponseStatusException(CONFLICT, "proof status must be DRAFT"); - } - if (!talent.getId().equals(talentProof.getTalent().getId())) { - throw new ResponseStatusException(BAD_REQUEST, - "talentId with id = %s and proofId with id = %s do not match".formatted(talentId, proofId)); - } - isValidUserEditTalent.accept(talentId, userInfo); - Skills skills = skillsRepository.findById(skillId) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "skill with id = %s not found".formatted(skillId))); - if (!talentProof.getSkills().contains(skills)) { - throw new ResponseStatusException(NOT_FOUND, - "you dont have skill with id = %s on proof with id = %s".formatted(skillId, proofId)); - } - talentProof.getSkills().remove(skills); - } +// public void deleteSkillOnProof(long talentId, long proofId, long skillId, Authentication authentication) { +// Talent talent = talentRepository.findById(talentId) +// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, +// "talent with id = %s not found".formatted(talentId))); +// UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) +// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); +// TalentProof talentProof = talentProofRepository.findById(proofId) +// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "proof with id = %s not found".formatted(proofId))); +// if (!talentProof.getStatus().equals(ProofStatus.DRAFT)) { +// throw new ResponseStatusException(CONFLICT, "proof status must be DRAFT"); +// } +// if (!talent.getId().equals(talentProof.getTalent().getId())) { +// throw new ResponseStatusException(BAD_REQUEST, +// "talentId with id = %s and proofId with id = %s do not match".formatted(talentId, proofId)); +// } +// isValidUserEditTalent.accept(talentId, userInfo); +// Skills skills = skillsRepository.findById(skillId) +// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, +// "skill with id = %s not found".formatted(skillId))); +// if (!talentProof.getSkills().contains(skills)) { +// throw new ResponseStatusException(NOT_FOUND, +// "you dont have skill with id = %s on proof with id = %s".formatted(skillId, proofId)); +// } +// talentProof.getSkills().remove(skills); +// } } diff --git a/src/main/java/com/provedcode/talent/service/TalentProofService.java b/src/main/java/com/provedcode/talent/service/TalentProofService.java index 06b5463..4c58c93 100644 --- a/src/main/java/com/provedcode/talent/service/TalentProofService.java +++ b/src/main/java/com/provedcode/talent/service/TalentProofService.java @@ -160,22 +160,22 @@ public TalentProof editTalentProof(long talentId, long proofId, ProofDTO proof, return talentProofRepository.save(oldProof); } - public void deleteProofById(long talentId, long proofId, Authentication authentication) { - Optional talent = talentRepository.findById(talentId); - Optional talentProof = talentProofRepository.findById(proofId); - Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); - - validateTalentForCompliance.userAndProofVerification(talent, talentProof, userInfo, talentId, proofId); - - Talent updatableTalent = talent.get(); - List talentSkills = updatableTalent.getTalentProofs().stream() - .flatMap(proof -> proof.getSkills().stream()).collect(Collectors.toCollection(ArrayList::new)); - log.info("talent-skills = {}", talentSkills.stream().map(i -> i.getSkill()).toList()); - List skillsOnProof = talentProof.get().getSkills().stream().toList(); - talentSkills.removeAll(skillsOnProof); - Set newTalentSkills = new HashSet<>(talentSkills); - updatableTalent.setSkills(newTalentSkills); - log.info("new talent-skills = {}", newTalentSkills.stream().map(Skills::getSkill).toList()); - updatableTalent.getTalentProofs().remove(talentProof.get()); - } +// public void deleteProofById(long talentId, long proofId, Authentication authentication) { +// Optional talent = talentRepository.findById(talentId); +// Optional talentProof = talentProofRepository.findById(proofId); +// Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); +// +// validateTalentForCompliance.userAndProofVerification(talent, talentProof, userInfo, talentId, proofId); +// +// Talent updatableTalent = talent.get(); +// List talentSkills = updatableTalent.getTalentProofs().stream() +// .flatMap(proof -> proof.getSkills().stream()).collect(Collectors.toCollection(ArrayList::new)); +// log.info("talent-skills = {}", talentSkills.stream().map(i -> i.getSkill()).toList()); +// List skillsOnProof = talentProof.get().getSkills().stream().toList(); +// talentSkills.removeAll(skillsOnProof); +// Set newTalentSkills = new HashSet<>(talentSkills); +// updatableTalent.setSkills(newTalentSkills); +// log.info("new talent-skills = {}", newTalentSkills.stream().map(Skills::getSkill).toList()); +// updatableTalent.getTalentProofs().remove(talentProof.get()); +// } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/service/TalentService.java b/src/main/java/com/provedcode/talent/service/TalentService.java index 2abcb7d..d187a00 100644 --- a/src/main/java/com/provedcode/talent/service/TalentService.java +++ b/src/main/java/com/provedcode/talent/service/TalentService.java @@ -156,33 +156,33 @@ private void checkEditTalentNull(EditTalent editTalent) { throw new ResponseStatusException(BAD_REQUEST, "you did not provide information to make changes"); } - public void addSkillOnTalent(long id, SkillIdDTO skillIdDTO, Authentication authentication) { - Optional talent = talentRepository.findById(id); - Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); - validateTalentForCompliance.userVerification(talent, userInfo, id); - Talent talentObject = talent.get(); - - Set skillsFromRepo = skillIdDTO.id().stream() - .map(element -> skillsRepository.findById(element) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Skill with id = %d not found".formatted(element)))) - .collect(Collectors.toSet()); - - Set skillsFromProofs = talentObject.getTalentProofs().stream() - .flatMap(talentProof -> talentProof.getSkills().stream()) - .collect(Collectors.toSet()); - - skillsFromRepo.stream() - .filter(skill -> !skillsFromProofs.contains(skill)) - .findFirst() - .ifPresent(skill -> { - throw new ResponseStatusException(FORBIDDEN, - "Skill with id = %d not found in talent's proofs".formatted(skill.getId())); - }); - - skillsFromRepo.stream() - .forEach(skill -> talentObject.getSkills().add(skill)); - } +// public void addSkillOnTalent(long id, SkillIdDTO skillIdDTO, Authentication authentication) { +// Optional talent = talentRepository.findById(id); +// Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); +// validateTalentForCompliance.userVerification(talent, userInfo, id); +// Talent talentObject = talent.get(); +// +// Set skillsFromRepo = skillIdDTO.id().stream() +// .map(element -> skillsRepository.findById(element) +// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, +// "Skill with id = %d not found".formatted(element)))) +// .collect(Collectors.toSet()); +// +// Set skillsFromProofs = talentObject.getTalentProofs().stream() +// .flatMap(talentProof -> talentProof.getSkills().stream()) +// .collect(Collectors.toSet()); +// +// skillsFromRepo.stream() +// .filter(skill -> !skillsFromProofs.contains(skill)) +// .findFirst() +// .ifPresent(skill -> { +// throw new ResponseStatusException(FORBIDDEN, +// "Skill with id = %d not found in talent's proofs".formatted(skill.getId())); +// }); +// +// skillsFromRepo.stream() +// .forEach(skill -> talentObject.getSkills().add(skill)); +// } public void deleteSkillFromTalent(long talentId, long skillId, Authentication authentication) { Optional talent = talentRepository.findById(talentId); diff --git a/src/main/resources/db/changelog/changeset/V5/drop-V5.sql b/src/main/resources/db/changelog/changeset/V5/drop-V5.sql new file mode 100644 index 0000000..b2a74c6 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V5/drop-V5.sql @@ -0,0 +1,19 @@ +--liquibase formatted sql +--changeset Ren:0 +-- Talent +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_skill cascade; +drop table if exists proof_skill cascade; +drop table if exists skill cascade; +-- User +drop table if exists authority cascade; +drop table if exists user_authorities cascade; +drop table if exists user_info cascade; +-- Sponsor +drop table if exists sponsor cascade; +drop table if exists kudos cascade; \ 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 428c0cf..baad890 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -1,15 +1,21 @@ databaseChangeLog: -# - include: -# file: db/changelog/changeset/V1/drop-V1.sql -# - include: -# file: db/changelog/changeset/V2/drop-V2.sql -# - include: -# file: db/changelog/changeset/V4/drop-V4.sql - - include: - file: db/changelog/changeset/V5/schema-V5.sql -# - include: -# file: db/changelog/changeset/V4/data-V4.sql -# - include: -# file: db/changelog/changeset/V4/data-V4.1.sql -# - include: -# file: db/changelog/changeset/V4/data-V4.2.sql + - include: + file: db/changelog/changeset/V1/drop-V1.sql + - include: + file: db/changelog/changeset/V2/drop-V2.sql + - include: + file: db/changelog/changeset/V4/drop-V4.sql + - include: + file: db/changelog/changeset/V4/schema-V4.sql + - include: + file: db/changelog/changeset/V4/data-V4.sql + - include: + file: db/changelog/changeset/V4/data-V4.1.sql + - include: + file: db/changelog/changeset/V4/data-V4.2.sql + - include: + file: db/changelog/changeset/V5/drop-V5.sql + - include: + file: db/changelog/changeset/V5/schema-V5.sql + + From 6b130900199c97e37432f5153f7d18a940e59387 Mon Sep 17 00:00:00 2001 From: Denis Boyko Date: Fri, 19 May 2023 16:24:02 +0300 Subject: [PATCH 37/59] add data-V5.sql --- .../db/changelog/changeset/V5/data-V5.sql | 1650 +++++++++++++++++ .../db/changelog/db.changelog-master.yaml | 2 + 2 files changed, 1652 insertions(+) create mode 100644 src/main/resources/db/changelog/changeset/V5/data-V5.sql diff --git a/src/main/resources/db/changelog/changeset/V5/data-V5.sql b/src/main/resources/db/changelog/changeset/V5/data-V5.sql new file mode 100644 index 0000000..ff60b1d --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V5/data-V5.sql @@ -0,0 +1,1650 @@ +--liquibase formatted sql +--changeset Ren:0 +-- Authority +insert into authority (id, authority) +values (1, 'TALENT'); +insert into authority (id, authority) +values (2, 'SPONSOR'); +-- Skill +insert into skill (id, skill) +values (1, 'Java Core'); +insert into skill (id, skill) +values (2, 'Spring Core'); +insert into skill (id, skill) +values (3, 'Spring boot'); +insert into skill (id, skill) +values (4, 'H2 Database'); +insert into skill (id, skill) +values (5, 'Spring Security'); +insert into skill (id, skill) +values (6, 'REST API'); +insert into skill (id, skill) +values (7, 'Git'); +insert into skill (id, skill) +values (8, 'Docker'); +insert into skill (id, skill) +values (9, 'Jira'); +insert into skill (id, skill) +values (10, 'JavaScript Core'); +insert into skill (id, skill) +values (11, 'React'); +insert into skill (id, skill) +values (12, 'Node.js'); +insert into skill (id, skill) +values (13, 'Angular'); +-- Talent +-- Serhii Soloviov +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_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 + )); +-- Mykhailo Ordyntsev +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_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 + )); +-- Denis Boyko +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_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 + )); +-- Ihor Schurenko +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_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 + )); +-- Dmytro Uzun +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_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 + )); +-- Viktor Voloshko +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_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 + )); +-- Olha Moiseienko +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_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 + )); +-- Maxim Kiyashko +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_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 + )); +-- Nikolaiev Oleksii +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_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 + )); +-- Artem Lytvynenko +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_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 + )); +-- Daniil Yevtukhov +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_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 + )); +-- Ruslan Morozov +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_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 + )); +-- Ihor Kopieichykov +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_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 + )); +-- Sponsor +-- Maksym Khudoliy +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 + )); +-- Oleksandr Butrym +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 + )); +-- Olha Shutylieva +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 + )); +-- Vladyslav Khrychov +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 + )); diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index baad890..1144ccb 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -17,5 +17,7 @@ databaseChangeLog: file: db/changelog/changeset/V5/drop-V5.sql - include: file: db/changelog/changeset/V5/schema-V5.sql + - include: + file: db/changelog/changeset/V5/data-V5.sql From 726c2e1c9e59a00d16ba46e39dcffdef837450dc Mon Sep 17 00:00:00 2001 From: Denis Boyko Date: Fri, 19 May 2023 16:44:40 +0300 Subject: [PATCH 38/59] bug fix --- .../resources/db/changelog/changeset/V5/dataKudos-V5.sql | 6 ++++++ .../resources/db/changelog/changeset/V5/dataSkill-V5.sql | 6 ++++++ src/main/resources/db/changelog/changeset/V5/schema-V5.sql | 3 --- src/main/resources/db/changelog/db.changelog-master.yaml | 5 +++++ 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/main/resources/db/changelog/changeset/V5/dataKudos-V5.sql create mode 100644 src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql diff --git a/src/main/resources/db/changelog/changeset/V5/dataKudos-V5.sql b/src/main/resources/db/changelog/changeset/V5/dataKudos-V5.sql new file mode 100644 index 0000000..00ebd56 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V5/dataKudos-V5.sql @@ -0,0 +1,6 @@ +--liquibase formatted sql +--changeset dennis:5 +insert into kudos(amount, sponsor_id, proof_skill_id) +values (10, 1, 1); +insert into kudos(amount, sponsor_id, proof_skill_id) +values (20, 2, 1); diff --git a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql new file mode 100644 index 0000000..c19807c --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql @@ -0,0 +1,6 @@ +--liquibase formatted sql +--changeset dennis:5 +insert into proof_skill (id, skill_id, proof_id) +values (1, 1, 1); +insert into proof_skill (id, skill_id, proof_id) +values (2, 2, 1) \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V5/schema-V5.sql b/src/main/resources/db/changelog/changeset/V5/schema-V5.sql index 9d914a8..52064ef 100644 --- a/src/main/resources/db/changelog/changeset/V5/schema-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/schema-V5.sql @@ -93,7 +93,6 @@ CREATE TABLE sponsor ( CREATE TABLE kudos ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, sponsor_id BIGINT, - proof_id BIGINT, proof_skill_id BIGINT, amount BIGINT, CONSTRAINT pk_kudos PRIMARY KEY (id) @@ -116,8 +115,6 @@ ADD CONSTRAINT FK_useaut_on_authority FOREIGN KEY (authority_id) REFERENCES auth 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); ALTER TABLE kudos ADD CONSTRAINT FK_KUDOS_ON_PROOF_SKILL FOREIGN KEY (proof_skill_id) REFERENCES proof_skill(id); diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 1144ccb..736b716 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -19,5 +19,10 @@ databaseChangeLog: file: db/changelog/changeset/V5/schema-V5.sql - include: file: db/changelog/changeset/V5/data-V5.sql + - include: + file: db/changelog/changeset/V5/dataSkill-V5.sql + - include: + file: db/changelog/changeset/V5/dataKudos-V5.sql + From 2c8a7a85adce2e411db2ac85862bfccbae560321 Mon Sep 17 00:00:00 2001 From: Denis Boyko Date: Fri, 19 May 2023 17:09:58 +0300 Subject: [PATCH 39/59] refactor TalentService.java addSkillOnTalent --- .../talent/controller/TalentController.java | 14 ++--- .../talent/service/TalentService.java | 54 +++++++++---------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/provedcode/talent/controller/TalentController.java b/src/main/java/com/provedcode/talent/controller/TalentController.java index 9e41f63..ecff1f5 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentController.java @@ -67,13 +67,13 @@ SessionInfoDTO deleteTalent(@PathVariable("id") long id, Authentication authenti return talentService.deleteTalentById(id, authentication); } -// @PreAuthorize("hasRole('TALENT')") -// @PostMapping("v4/talents/{talent-id}/skills") -// void addSkillOnTalent(@PathVariable("talent-id") long id, -// @RequestBody @Valid SkillIdDTO skillIdDTO, -// Authentication authentication) { -// talentService.addSkillOnTalent(id, skillIdDTO, authentication); -// } + @PreAuthorize("hasRole('TALENT')") + @PostMapping("v4/talents/{talent-id}/skills") + void addSkillOnTalent(@PathVariable("talent-id") long id, + @RequestBody @Valid SkillIdDTO skillIdDTO, + Authentication authentication) { + talentService.addSkillOnTalent(id, skillIdDTO, authentication); + } @PreAuthorize("hasRole('TALENT')") @DeleteMapping("v4/talents/{talent-id}/skills/{skill-id}") diff --git a/src/main/java/com/provedcode/talent/service/TalentService.java b/src/main/java/com/provedcode/talent/service/TalentService.java index d187a00..a576e98 100644 --- a/src/main/java/com/provedcode/talent/service/TalentService.java +++ b/src/main/java/com/provedcode/talent/service/TalentService.java @@ -156,33 +156,33 @@ private void checkEditTalentNull(EditTalent editTalent) { throw new ResponseStatusException(BAD_REQUEST, "you did not provide information to make changes"); } -// public void addSkillOnTalent(long id, SkillIdDTO skillIdDTO, Authentication authentication) { -// Optional talent = talentRepository.findById(id); -// Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); -// validateTalentForCompliance.userVerification(talent, userInfo, id); -// Talent talentObject = talent.get(); -// -// Set skillsFromRepo = skillIdDTO.id().stream() -// .map(element -> skillsRepository.findById(element) -// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, -// "Skill with id = %d not found".formatted(element)))) -// .collect(Collectors.toSet()); -// -// Set skillsFromProofs = talentObject.getTalentProofs().stream() -// .flatMap(talentProof -> talentProof.getSkills().stream()) -// .collect(Collectors.toSet()); -// -// skillsFromRepo.stream() -// .filter(skill -> !skillsFromProofs.contains(skill)) -// .findFirst() -// .ifPresent(skill -> { -// throw new ResponseStatusException(FORBIDDEN, -// "Skill with id = %d not found in talent's proofs".formatted(skill.getId())); -// }); -// -// skillsFromRepo.stream() -// .forEach(skill -> talentObject.getSkills().add(skill)); -// } + public void addSkillOnTalent(long id, SkillIdDTO skillIdDTO, Authentication authentication) { + Optional talent = talentRepository.findById(id); + Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); + validateTalentForCompliance.userVerification(talent, userInfo, id); + Talent talentObject = talent.get(); + + Set skillsFromRepo = skillIdDTO.id().stream() + .map(element -> skillsRepository.findById(element) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Skill with id = %d not found".formatted(element)))) + .collect(Collectors.toSet()); + + Set skillsFromProofs = talentObject.getTalentProofs().stream() + .flatMap(talentProof -> talentProof.getProofSkills() + .stream().map(skill -> skill.getSkill())).collect(Collectors.toSet()); + + skillsFromRepo.stream() + .filter(skill -> !skillsFromProofs.contains(skill)) + .findFirst() + .ifPresent(skill -> { + throw new ResponseStatusException(FORBIDDEN, + "Skill with id = %d not found in talent's proofs".formatted(skill.getId())); + }); + + skillsFromRepo.stream() + .forEach(skill -> talentObject.getSkills().add(skill)); + } public void deleteSkillFromTalent(long talentId, long skillId, Authentication authentication) { Optional talent = talentRepository.findById(talentId); From 725e39aa02bec63d042696ec4e9d9bf061c0b987 Mon Sep 17 00:00:00 2001 From: Denis Boyko Date: Fri, 19 May 2023 17:20:34 +0300 Subject: [PATCH 40/59] refactor TalentService.java addSkillOnTalent --- .../java/com/provedcode/talent/service/TalentService.java | 8 ++++++++ .../resources/db/changelog/changeset/V5/dataKudos-V5.sql | 6 ++++++ .../resources/db/changelog/changeset/V5/dataSkill-V5.sql | 6 +++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/provedcode/talent/service/TalentService.java b/src/main/java/com/provedcode/talent/service/TalentService.java index a576e98..50f63ac 100644 --- a/src/main/java/com/provedcode/talent/service/TalentService.java +++ b/src/main/java/com/provedcode/talent/service/TalentService.java @@ -172,6 +172,14 @@ public void addSkillOnTalent(long id, SkillIdDTO skillIdDTO, Authentication auth .flatMap(talentProof -> talentProof.getProofSkills() .stream().map(skill -> skill.getSkill())).collect(Collectors.toSet()); + for (Skills skill : talentObject.getSkills()) { + for (Skills skillForAdd : skillsFromRepo) { + if (skill.equals(skillForAdd)) { + throw new ResponseStatusException(BAD_REQUEST, + "Skill with id = %d found in talent's skills".formatted(skill.getId())); + } + } + } skillsFromRepo.stream() .filter(skill -> !skillsFromProofs.contains(skill)) .findFirst() diff --git a/src/main/resources/db/changelog/changeset/V5/dataKudos-V5.sql b/src/main/resources/db/changelog/changeset/V5/dataKudos-V5.sql index 00ebd56..7b94fe3 100644 --- a/src/main/resources/db/changelog/changeset/V5/dataKudos-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/dataKudos-V5.sql @@ -4,3 +4,9 @@ insert into kudos(amount, sponsor_id, proof_skill_id) values (10, 1, 1); insert into kudos(amount, sponsor_id, proof_skill_id) values (20, 2, 1); +insert into kudos(amount, sponsor_id, proof_skill_id) +values (30, 3, 3); +insert into kudos(amount, sponsor_id, proof_skill_id) +values (10, 4, 1); +insert into kudos(amount, sponsor_id, proof_skill_id) +values (10, 1, 4); diff --git a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql index c19807c..85f124b 100644 --- a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql @@ -3,4 +3,8 @@ insert into proof_skill (id, skill_id, proof_id) values (1, 1, 1); insert into proof_skill (id, skill_id, proof_id) -values (2, 2, 1) \ No newline at end of file +values (2, 2, 1); +insert into proof_skill (id, skill_id, proof_id) +values (3, 2, 2); +insert into proof_skill (id, skill_id, proof_id) +values (4, 3, 3) \ No newline at end of file From 1f5d67a0ee363209daeffa395b7c630dc2c2ee87 Mon Sep 17 00:00:00 2001 From: Denis Boyko Date: Fri, 19 May 2023 18:19:16 +0300 Subject: [PATCH 41/59] refactor TalentProofController: deleteProofById --- .../controller/TalentProofController.java | 16 +++---- .../talent/mapper/TalentMapper.java | 2 - .../talent/service/TalentProofService.java | 43 +++++++++++-------- .../talent/service/TalentService.java | 2 +- .../changelog/changeset/V5/dataSkill-V5.sql | 17 +++++++- 5 files changed, 49 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/provedcode/talent/controller/TalentProofController.java b/src/main/java/com/provedcode/talent/controller/TalentProofController.java index 1613c67..ff89e09 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentProofController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentProofController.java @@ -85,12 +85,12 @@ ProofDTO editProof(Authentication authentication, talentProofService.editTalentProof(talentId, proofId, proof, authentication)); } -// @DeleteProofApiDoc -// @DeleteMapping("/{talent-id}/proofs/{proof-id}") -// @PreAuthorize("hasRole('TALENT')") -// void deleteProof(@PathVariable(value = "talent-id") long talentId, -// @PathVariable(value = "proof-id") long proofId, -// Authentication authentication) { -// talentProofService.deleteProofById(talentId, proofId, authentication); -// } + @DeleteProofApiDoc + @DeleteMapping("/{talent-id}/proofs/{proof-id}") + @PreAuthorize("hasRole('TALENT')") + void deleteProof(@PathVariable(value = "talent-id") long talentId, + @PathVariable(value = "proof-id") long proofId, + Authentication authentication) { + talentProofService.deleteProofById(talentId, proofId, authentication); + } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/mapper/TalentMapper.java b/src/main/java/com/provedcode/talent/mapper/TalentMapper.java index 336714e..b8cd37d 100644 --- a/src/main/java/com/provedcode/talent/mapper/TalentMapper.java +++ b/src/main/java/com/provedcode/talent/mapper/TalentMapper.java @@ -14,10 +14,8 @@ public interface TalentMapper { @Mapping(target = "additionalInfo", expression = "java(talent.getTalentDescription() != null ? talent.getTalentDescription().getAdditionalInfo() : null)") @Mapping(target = "links", expression = "java(talent.getTalentLinks().stream().map(l -> l.getLink()).toList())") @Mapping(target = "contacts", expression = "java(talent.getTalentContacts().stream().map(c -> c.getContact()).toList())") -// @Mapping(target = "talents", expression = "java(talent.getTalentTalents().stream().map(t -> t.getTalentName()).toList())") @Mapping(target = "attachedFiles", expression = "java(talent.getTalentAttachedFiles().stream().map(a -> a.getAttachedFile()).toList())") FullTalentDTO talentToFullTalentDTO(Talent talent); -// @Mapping(target = "talents", expression = "java(talent.getTalentTalents().stream().map(t -> t.getTalentName()).toList())") ShortTalentDTO talentToShortTalentDTO(Talent talent); } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/service/TalentProofService.java b/src/main/java/com/provedcode/talent/service/TalentProofService.java index 4c58c93..3b86545 100644 --- a/src/main/java/com/provedcode/talent/service/TalentProofService.java +++ b/src/main/java/com/provedcode/talent/service/TalentProofService.java @@ -4,7 +4,6 @@ import com.provedcode.talent.model.ProofStatus; import com.provedcode.talent.model.dto.FullProofDTO; import com.provedcode.talent.model.dto.ProofDTO; -import com.provedcode.talent.model.dto.StatusDTO; import com.provedcode.talent.model.entity.Skills; import com.provedcode.talent.model.entity.Talent; import com.provedcode.talent.model.entity.TalentProof; @@ -160,22 +159,28 @@ public TalentProof editTalentProof(long talentId, long proofId, ProofDTO proof, return talentProofRepository.save(oldProof); } -// public void deleteProofById(long talentId, long proofId, Authentication authentication) { -// Optional talent = talentRepository.findById(talentId); -// Optional talentProof = talentProofRepository.findById(proofId); -// Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); -// -// validateTalentForCompliance.userAndProofVerification(talent, talentProof, userInfo, talentId, proofId); -// -// Talent updatableTalent = talent.get(); -// List talentSkills = updatableTalent.getTalentProofs().stream() -// .flatMap(proof -> proof.getSkills().stream()).collect(Collectors.toCollection(ArrayList::new)); -// log.info("talent-skills = {}", talentSkills.stream().map(i -> i.getSkill()).toList()); -// List skillsOnProof = talentProof.get().getSkills().stream().toList(); -// talentSkills.removeAll(skillsOnProof); -// Set newTalentSkills = new HashSet<>(talentSkills); -// updatableTalent.setSkills(newTalentSkills); -// log.info("new talent-skills = {}", newTalentSkills.stream().map(Skills::getSkill).toList()); -// updatableTalent.getTalentProofs().remove(talentProof.get()); -// } + public void deleteProofById(long talentId, long proofId, Authentication authentication) { + Optional talent = talentRepository.findById(talentId); + Optional talentProof = talentProofRepository.findById(proofId); + Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); + + validateTalentForCompliance.userAndProofVerification(talent, talentProof, userInfo, talentId, proofId); + + Talent updatableTalent = talent.get(); + + List allTalentSkills = updatableTalent.getTalentProofs().stream() + .flatMap(proof -> proof.getProofSkills() + .stream().map(skill -> skill.getSkill())).collect(Collectors.toList()); + + log.info("talent-skills = {}", allTalentSkills.stream().map(i -> i.getSkill()).toList()); + + List skillsOnProofForDelete = talentProof.get().getProofSkills() + .stream().map(skill -> skill.getSkill()).toList(); + + allTalentSkills.removeAll(skillsOnProofForDelete); + Set newTalentSkills = new HashSet<>(allTalentSkills); + updatableTalent.setSkills(newTalentSkills); + log.info("new talent-skills = {}", newTalentSkills.stream().map(Skills::getSkill).toList()); + updatableTalent.getTalentProofs().remove(talentProof.get()); + } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/service/TalentService.java b/src/main/java/com/provedcode/talent/service/TalentService.java index 50f63ac..8d3e730 100644 --- a/src/main/java/com/provedcode/talent/service/TalentService.java +++ b/src/main/java/com/provedcode/talent/service/TalentService.java @@ -175,7 +175,7 @@ public void addSkillOnTalent(long id, SkillIdDTO skillIdDTO, Authentication auth for (Skills skill : talentObject.getSkills()) { for (Skills skillForAdd : skillsFromRepo) { if (skill.equals(skillForAdd)) { - throw new ResponseStatusException(BAD_REQUEST, + throw new ResponseStatusException(CONFLICT, "Skill with id = %d found in talent's skills".formatted(skill.getId())); } } diff --git a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql index 85f124b..49a11f2 100644 --- a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql @@ -7,4 +7,19 @@ values (2, 2, 1); insert into proof_skill (id, skill_id, proof_id) values (3, 2, 2); insert into proof_skill (id, skill_id, proof_id) -values (4, 3, 3) \ No newline at end of file +values (4, 3, 3); + +insert into talent_skill(talent_id, skill_id) +values (1,1); +insert into talent_skill(talent_id, skill_id) +values (1,2); +insert into talent_skill(talent_id, skill_id) +values (1,3); +insert into talent_skill(talent_id, skill_id) +values (2,1); +insert into talent_skill(talent_id, skill_id) +values (2,2); +insert into talent_skill(talent_id, skill_id) +values (2,6); +insert into talent_skill(talent_id, skill_id) +values (3,1); \ No newline at end of file From c9ca7315d9663288e828be1d9ecc2b43b2fa81c0 Mon Sep 17 00:00:00 2001 From: Maslyna Date: Fri, 19 May 2023 17:49:04 +0200 Subject: [PATCH 42/59] Code refactor: - TalentSkillsController: - addSkillOnProof now works - getAllSkillsOnProof now works --- .../controller/TalentSkillsController.java | 35 +++--- .../talent/repo/ProofSkillRepository.java | 7 ++ .../talent/service/ProofSkillsService.java | 102 ++++++++++++------ .../changelog/changeset/V5/dataSkill-V5.sql | 16 +-- 4 files changed, 105 insertions(+), 55 deletions(-) create mode 100644 src/main/java/com/provedcode/talent/repo/ProofSkillRepository.java diff --git a/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java b/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java index c0cebf0..eb20d38 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java @@ -16,30 +16,31 @@ @AllArgsConstructor @RestController -@RequestMapping("/api/v4/talents") +@RequestMapping("/api/v5/talents") public class TalentSkillsController { - ProofSkillsService talentSkillsService; + ProofSkillsService proofSkillsService; + + @PostMapping("/{talent-id}/proofs/{proof-id}/skills") + void addSkillOnProof(@PathVariable("talent-id") long talentId, + @PathVariable("proof-id") long proofId, + @RequestBody @Valid ProofSkillsDTO skills, + Authentication authentication) { + proofSkillsService.addSkillsOnProof(talentId, proofId, skills, authentication); + } + + @GetMapping("/{talent-id}/proofs/{proof-id}/skills") + SkillsOnProofDTO getAllSkillsOnProof(@PathVariable("talent-id") long talentId, + @PathVariable("proof-id") long proofId, + Authentication authentication) { + return proofSkillsService.getAllSkillsOnProof(talentId, proofId, authentication); + } -// @PostMapping("/{talent-id}/proofs/{proof-id}/skills") -// void addSkillOnProof(@PathVariable("talent-id") long talentId, -// @PathVariable("proof-id") long proofId, -// @RequestBody @Valid ProofSkillsDTO skills, -// Authentication authentication) { -// talentSkillsService.addSkillsOnProof(talentId, proofId, skills, authentication); -// } -// -// @GetMapping("/{talent-id}/proofs/{proof-id}/skills") -// SkillsOnProofDTO getAllSkillsOnProof(@PathVariable("talent-id") long talentId, -// @PathVariable("proof-id") long proofId, -// Authentication authentication) { -// return talentSkillsService.getAllSkillsOnProof(talentId, proofId, authentication); -// } // @PreAuthorize("hasRole('TALENT')") // @DeleteMapping("/{talent-id}/proofs/{proof-id}/skills/{skill-id}") // void deleteSkillOnProof(@PathVariable("talent-id") long talentId, // @PathVariable("proof-id") long proofId, // @PathVariable("skill-id") long skillId, // Authentication authentication) { -// talentSkillsService.deleteSkillOnProof(talentId, proofId, skillId, authentication); +// proofSkillsService.deleteSkillOnProof(talentId, proofId, skillId, authentication); // } } diff --git a/src/main/java/com/provedcode/talent/repo/ProofSkillRepository.java b/src/main/java/com/provedcode/talent/repo/ProofSkillRepository.java new file mode 100644 index 0000000..20b4536 --- /dev/null +++ b/src/main/java/com/provedcode/talent/repo/ProofSkillRepository.java @@ -0,0 +1,7 @@ +package com.provedcode.talent.repo; + +import com.provedcode.talent.model.entity.ProofSkill; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ProofSkillRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/service/ProofSkillsService.java b/src/main/java/com/provedcode/talent/service/ProofSkillsService.java index a851c7d..a82237d 100644 --- a/src/main/java/com/provedcode/talent/service/ProofSkillsService.java +++ b/src/main/java/com/provedcode/talent/service/ProofSkillsService.java @@ -5,9 +5,11 @@ import com.provedcode.talent.model.dto.ProofSkillsDTO; import com.provedcode.talent.model.dto.SkillDTO; import com.provedcode.talent.model.dto.SkillsOnProofDTO; +import com.provedcode.talent.model.entity.ProofSkill; import com.provedcode.talent.model.entity.Skills; import com.provedcode.talent.model.entity.Talent; import com.provedcode.talent.model.entity.TalentProof; +import com.provedcode.talent.repo.ProofSkillRepository; import com.provedcode.talent.repo.SkillsRepository; import com.provedcode.talent.repo.TalentProofRepository; import com.provedcode.talent.repo.TalentRepository; @@ -22,6 +24,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.TreeSet; import java.util.function.BiConsumer; import java.util.stream.Collectors; @@ -35,43 +38,82 @@ public class ProofSkillsService { TalentRepository talentRepository; UserInfoRepository userInfoRepository; TalentProofRepository talentProofRepository; + ProofSkillRepository proofSkillRepository; SkillMapper skillMapper; - - static BiConsumer isValidUserEditTalent = (talentId, userInfo) -> { + final BiConsumer isValidUserEditTalent = (talentId, userInfo) -> { if (!userInfo.getTalent().getId().equals(talentId)) { throw new ResponseStatusException(CONFLICT, "you can`t change another talent"); } }; -// public void addSkillsOnProof(long talentId, long proofId, ProofSkillsDTO skills, Authentication authentication) { -// if (!talentRepository.existsById(talentId)) { -// throw new ResponseStatusException(NOT_FOUND, "talent with id = %s not found".formatted(talentId)); -// } -// UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) -// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); -// TalentProof talentProof = talentProofRepository.findById(proofId) -// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "proof with id = %s not found".formatted(proofId))); -// if (!talentProof.getStatus().equals(ProofStatus.DRAFT)) { -// throw new ResponseStatusException(CONFLICT, "proof status must be DRAFT"); -// } -// -// isValidUserEditTalent.accept(talentId, userInfo); -// skills.skills().forEach(skillId -> { -// if (!skillsRepository.existsById(skillId)) -// throw new ResponseStatusException(NOT_FOUND, "no such skill with id = " + skillId); -// }); -// -// Set skillsSet = new HashSet<>(skillsRepository.findAllById(skills.skills())); -// talentProof.getSkills().forEach(skill -> { -// if (skillsSet.contains(skill)) -// throw new ResponseStatusException(CONFLICT, -// "skill with id = %s already on skill".formatted(skill.getId())); -// }); -// -// talentProof.getSkills().addAll(skillsSet); -// talentProofRepository.save(talentProof); -// } + + public void addSkillsOnProof(long talentId, long proofId, ProofSkillsDTO skills, Authentication authentication) { + if (!talentRepository.existsById(talentId)) { + throw new ResponseStatusException(NOT_FOUND, "talent with id = %s not found".formatted(talentId)); + } + UserInfo user = userInfoRepository.findByLogin(authentication.getName()) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "user with id = %s not found")); + TalentProof proof = talentProofRepository.findById(proofId). + orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "proof with id = %s not found".formatted(proofId))); + if (!proof.getStatus().equals(ProofStatus.DRAFT)) { + throw new ResponseStatusException(CONFLICT, "proof status must be DRAFT"); + } + isValidUserEditTalent.accept(talentId, user); + + // Set of new skills + Set addedSkillsId = new TreeSet<>(skills.skills()); + addedSkillsId.forEach(skillId -> { + if (!skillsRepository.existsById(skillId)) + throw new ResponseStatusException(NOT_FOUND, "no such skill with id = " + skillId); + }); + + // check if skill already on proof + proof.getProofSkills().forEach(proofSkill -> { + if (addedSkillsId.contains(proofSkill.getSkill().getId())) { + throw new ResponseStatusException(CONFLICT, + "skill with id = %s already on skill".formatted(proofSkill.getSkill().getId())); + } + }); + + Set addedSkills = new HashSet<>(skillsRepository.findAllById(addedSkillsId)).stream() + .map(skill -> ProofSkill.builder().talentProof(proof).skill(skill).build()) + .collect(Collectors.toSet()); // skills to add on proof + + proof.getProofSkills().addAll(addedSkills); + } + + public SkillsOnProofDTO getAllSkillsOnProof(long talentId, long proofId, Authentication authentication) { + TalentProof talentProof = talentProofRepository.findById(proofId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "proof with id = %s not found".formatted(proofId))); + Talent talent = talentRepository.findById(talentId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "talent with id = %s not found".formatted(talentId))); + if (!talent.getId().equals(talentProof.getTalent().getId())) { + throw new ResponseStatusException(BAD_REQUEST, + "talentId with id = %s and proofId with id = %s do not match".formatted(talentId, proofId)); + } + Set skills = talentProof.getProofSkills().stream() + .map(ProofSkill::getSkill) + .map(skillMapper::skillToSkillDTO).collect(Collectors.toSet()); + + if (talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { + return SkillsOnProofDTO.builder().skills(skills).build(); + } else if (authentication != null) { + UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); + if (userInfo.getTalent().getId().equals(talentProof.getTalent().getId())) { + return SkillsOnProofDTO.builder().skills(skills).build(); + } else { + throw new ResponseStatusException(FORBIDDEN, "you can't see proofs in DRAFT and HIDDEN status"); + } + } else { + throw new ResponseStatusException(FORBIDDEN, "you can't see proofs in DRAFT and HIDDEN status"); + } + + } + // @Transactional(readOnly = true) // public SkillsOnProofDTO getAllSkillsOnProof(long talentId, long proofId, Authentication authentication) { diff --git a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql index 85f124b..800c6b7 100644 --- a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql @@ -1,10 +1,10 @@ --liquibase formatted sql --changeset dennis:5 -insert into proof_skill (id, skill_id, proof_id) -values (1, 1, 1); -insert into proof_skill (id, skill_id, proof_id) -values (2, 2, 1); -insert into proof_skill (id, skill_id, proof_id) -values (3, 2, 2); -insert into proof_skill (id, skill_id, proof_id) -values (4, 3, 3) \ No newline at end of file +insert into proof_skill (skill_id, proof_id) +values (1, 1); +insert into proof_skill (skill_id, proof_id) +values (2, 1); +insert into proof_skill (skill_id, proof_id) +values (2, 2); +insert into proof_skill (skill_id, proof_id) +values (3, 3) \ No newline at end of file From 2749931828f3aa2d0812a4a4ee26836d5c6cfdfe Mon Sep 17 00:00:00 2001 From: Maslyna Date: Fri, 19 May 2023 18:21:16 +0200 Subject: [PATCH 43/59] Code refactor: - TalentSkillsController: - deleteSkillOnProof now works --- .../controller/TalentSkillsController.java | 19 ++- .../talent/service/ProofSkillsService.java | 55 +++---- .../db/changelog/changeset/V5/schema-V5.sql | 154 ++++++++++-------- 3 files changed, 122 insertions(+), 106 deletions(-) diff --git a/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java b/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java index eb20d38..7d58afd 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentSkillsController.java @@ -10,6 +10,9 @@ import org.springframework.security.core.Authentication; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; @Slf4j @Validated @@ -35,12 +38,12 @@ SkillsOnProofDTO getAllSkillsOnProof(@PathVariable("talent-id") long talentId, return proofSkillsService.getAllSkillsOnProof(talentId, proofId, authentication); } -// @PreAuthorize("hasRole('TALENT')") -// @DeleteMapping("/{talent-id}/proofs/{proof-id}/skills/{skill-id}") -// void deleteSkillOnProof(@PathVariable("talent-id") long talentId, -// @PathVariable("proof-id") long proofId, -// @PathVariable("skill-id") long skillId, -// Authentication authentication) { -// proofSkillsService.deleteSkillOnProof(talentId, proofId, skillId, authentication); -// } + @PreAuthorize("hasRole('TALENT')") + @DeleteMapping("/{talent-id}/proofs/{proof-id}/skills/{skill-id}") + void deleteSkillOnProof(@PathVariable("talent-id") long talentId, + @PathVariable("proof-id") long proofId, + @PathVariable("skill-id") long skillId, + Authentication authentication) { + proofSkillsService.deleteSkillOnProof(talentId, proofId, skillId, authentication); + } } diff --git a/src/main/java/com/provedcode/talent/service/ProofSkillsService.java b/src/main/java/com/provedcode/talent/service/ProofSkillsService.java index a82237d..c464041 100644 --- a/src/main/java/com/provedcode/talent/service/ProofSkillsService.java +++ b/src/main/java/com/provedcode/talent/service/ProofSkillsService.java @@ -41,6 +41,14 @@ public class ProofSkillsService { ProofSkillRepository proofSkillRepository; SkillMapper skillMapper; + final BiConsumer isValidTalentEditProof = (talent, talentProof) -> { + if (!talent.getId().equals(talentProof.getTalent().getId())) { + throw new ResponseStatusException(BAD_REQUEST, + "talentId with id = %s and proofId with id = %s do not match" + .formatted(talent.getId(), talentProof.getId())); + } + }; + final BiConsumer isValidUserEditTalent = (talentId, userInfo) -> { if (!userInfo.getTalent().getId().equals(talentId)) { throw new ResponseStatusException(CONFLICT, "you can`t change another talent"); @@ -83,6 +91,7 @@ public void addSkillsOnProof(long talentId, long proofId, ProofSkillsDTO skills, proof.getProofSkills().addAll(addedSkills); } + @Transactional(readOnly = true) public SkillsOnProofDTO getAllSkillsOnProof(long talentId, long proofId, Authentication authentication) { TalentProof talentProof = talentProofRepository.findById(proofId) .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, @@ -114,35 +123,25 @@ public SkillsOnProofDTO getAllSkillsOnProof(long talentId, long proofId, Authent } + public void deleteSkillOnProof(long talentId, long proofId, long skillId, Authentication authentication) { + UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); + isValidUserEditTalent.accept(talentId, userInfo); + + Talent talent = talentRepository.findById(talentId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "talent with id = %s not found".formatted(talentId))); + + TalentProof talentProof = talentProofRepository.findById(proofId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "proof with id = %s not found".formatted(proofId))); + if (!talentProof.getStatus().equals(ProofStatus.DRAFT)) { + throw new ResponseStatusException(CONFLICT, "proof status must be DRAFT"); + } + isValidTalentEditProof.accept(talent, talentProof); + + talentProof.getProofSkills().removeIf(i -> i.getSkill().getId().equals(skillId)); + } -// @Transactional(readOnly = true) -// public SkillsOnProofDTO getAllSkillsOnProof(long talentId, long proofId, Authentication authentication) { -// TalentProof talentProof = talentProofRepository.findById(proofId) -// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, -// "proof with id = %s not found".formatted(proofId))); -// Talent talent = talentRepository.findById(talentId) -// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, -// "talent with id = %s not found".formatted(talentId))); -// if (!talent.getId().equals(talentProof.getTalent().getId())) { -// throw new ResponseStatusException(BAD_REQUEST, -// "talentId with id = %s and proofId with id = %s do not match".formatted(talentId, proofId)); -// } -// Set skills = talentProof.getSkills().stream() -// .map(skillMapper::skillToSkillDTO).collect(Collectors.toSet()); -// if (talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { -// return SkillsOnProofDTO.builder().skills(skills).build(); -// } else if (authentication != null) { -// UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) -// .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); -// if (userInfo.getTalent().getId().equals(talentProof.getTalent().getId())) { -// return SkillsOnProofDTO.builder().skills(skills).build(); -// } else { -// throw new ResponseStatusException(FORBIDDEN, "you can't see proofs in DRAFT and HIDDEN status"); -// } -// } else { -// throw new ResponseStatusException(FORBIDDEN, "you can't see proofs in DRAFT and HIDDEN status"); -// } -// } // public void deleteSkillOnProof(long talentId, long proofId, long skillId, Authentication authentication) { // Talent talent = talentRepository.findById(talentId) diff --git a/src/main/resources/db/changelog/changeset/V5/schema-V5.sql b/src/main/resources/db/changelog/changeset/V5/schema-V5.sql index 52064ef..85940f7 100644 --- a/src/main/resources/db/changelog/changeset/V5/schema-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/schema-V5.sql @@ -2,129 +2,143 @@ -- changeset Ren:0 -- tables for sprint 5 -- Talent -CREATE TABLE talent ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - first_name VARCHAR(20), - last_name VARCHAR(20), +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), + 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, +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), +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), +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), +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, +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_skill ( +CREATE TABLE talent_skill +( talent_id BIGINT NOT NULL, - skill_id BIGINT NOT NULL, + skill_id BIGINT NOT NULL, CONSTRAINT pk_talent_skill PRIMARY KEY (talent_id, skill_id) ); -CREATE TABLE proof_skill ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - proof_id BIGINT NOT NULL, - skill_id BIGINT NOT NULL, +CREATE TABLE proof_skill +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + proof_id BIGINT NOT NULL, + skill_id BIGINT NOT NULL, CONSTRAINT pk_proof_skill PRIMARY KEY (id) ); -CREATE TABLE skill ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, +CREATE TABLE skill +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, skill VARCHAR(30), CONSTRAINT pk_skill PRIMARY KEY (id) ); -- User -CREATE TABLE user_info ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - talent_id BIGINT, +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, + login VARCHAR(100) NOT NULL, + password VARCHAR(255) NOT NULL, CONSTRAINT pk_user_info PRIMARY KEY (id) ); -CREATE TABLE authority ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - authority VARCHAR(20) NOT NULL, +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 user_authorities ( +CREATE TABLE user_authorities +( authority_id BIGINT NOT NULL, - user_id BIGINT NOT NULL, + user_id BIGINT NOT NULL, CONSTRAINT pk_user_authorities PRIMARY KEY (authority_id, user_id) ); -- Sponsor -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), +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) ); -CREATE TABLE kudos ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - sponsor_id BIGINT, +CREATE TABLE kudos +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + sponsor_id BIGINT, proof_skill_id BIGINT, - amount BIGINT, + amount BIGINT, CONSTRAINT pk_kudos PRIMARY KEY (id) ); -- Foreign keys ALTER TABLE talent_attached_file -ADD CONSTRAINT FK_TALENT_ATTACHED_FILE_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); + 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); + 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); + 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); + 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); + ADD CONSTRAINT FK_TALENT_PROOFS_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); + 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); + 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); + ADD CONSTRAINT FK_useaut_on_user_info FOREIGN KEY (user_id) REFERENCES user_info (id); ALTER TABLE kudos -ADD CONSTRAINT FK_KUDOS_ON_SPONSOR FOREIGN KEY (sponsor_id) REFERENCES sponsor (id); + ADD CONSTRAINT FK_KUDOS_ON_SPONSOR FOREIGN KEY (sponsor_id) REFERENCES sponsor (id); ALTER TABLE kudos -ADD CONSTRAINT FK_KUDOS_ON_PROOF_SKILL FOREIGN KEY (proof_skill_id) REFERENCES proof_skill(id); + ADD CONSTRAINT FK_KUDOS_ON_PROOF_SKILL FOREIGN KEY (proof_skill_id) REFERENCES proof_skill (id); ALTER TABLE proof_skill -ADD CONSTRAINT FK_proof_skill_ON_TALENT_PROOF FOREIGN KEY (proof_id) REFERENCES talent_proofs (id); + ADD CONSTRAINT FK_proof_skill_ON_TALENT_PROOF FOREIGN KEY (proof_id) REFERENCES talent_proofs (id); ALTER TABLE proof_skill -ADD CONSTRAINT FK_proof_skill_ON_SKILL FOREIGN KEY (skill_id) REFERENCES skill (id); + ADD CONSTRAINT FK_proof_skill_ON_SKILL FOREIGN KEY (skill_id) REFERENCES skill (id); ALTER TABLE talent_skill -ADD CONSTRAINT FK_talent_skill_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); + ADD CONSTRAINT FK_talent_skill_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); ALTER TABLE talent_skill -ADD CONSTRAINT FK_talent_skill_ON_SKILL FOREIGN KEY (skill_id) REFERENCES skill (id); + ADD CONSTRAINT FK_talent_skill_ON_SKILL FOREIGN KEY (skill_id) REFERENCES skill (id); -- Indexes CREATE UNIQUE INDEX idx_login ON user_info (login) \ No newline at end of file From da61771bda962f5e74bf855eb5930dd82bc4027f Mon Sep 17 00:00:00 2001 From: Denis Boyko Date: Fri, 19 May 2023 19:22:50 +0300 Subject: [PATCH 44/59] refactor --- .../kudos/controller/KudosController.java | 70 +++---- .../kudos/repository/KudosRepository.java | 4 +- .../kudos/service/KudosService.java | 172 +++++++++--------- .../changelog/changeset/V5/dataSkill-V5.sql | 34 ++-- 4 files changed, 141 insertions(+), 139 deletions(-) diff --git a/src/main/java/com/provedcode/kudos/controller/KudosController.java b/src/main/java/com/provedcode/kudos/controller/KudosController.java index edef91e..a2315dc 100644 --- a/src/main/java/com/provedcode/kudos/controller/KudosController.java +++ b/src/main/java/com/provedcode/kudos/controller/KudosController.java @@ -1,41 +1,41 @@ package com.provedcode.kudos.controller; -//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 -//@Validated -//@RequestMapping("/api/v3/") -//public class KudosController { -// KudosService 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.*; -// @GetKudosForSponsorApiDoc -// @PreAuthorize("hasRole('SPONSOR')") -// @GetMapping("/sponsors/{sponsor-id}/kudos") -// KudosAmount getKudosForSponsor(@PathVariable("sponsor-id") long sponsorId, Authentication authentication) { -// return kudosService.getKudosForSponsor(sponsorId, authentication); -// } +import java.util.Optional; -// @GetAmountOfKudosApiDoc -// @PreAuthorize("hasRole('TALENT')") -// @GetMapping("/proofs/{proof-id}/kudos") -// KudosAmountWithSponsor getProofKudos(@PathVariable("proof-id") long proofId, Authentication authentication) { -// return kudosService.getProofKudos(proofId, authentication); -// } +@RestController +@AllArgsConstructor +@Validated +@RequestMapping("/api/v3/") +public class KudosController { + KudosService kudosService; + + @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')") + @GetMapping("/proofs/{proof-id}/kudos") + KudosAmountWithSponsor getProofKudos(@PathVariable("proof-id") long proofId, Authentication authentication) { + return kudosService.getProofKudos(proofId, authentication); + } // // @PostAddKudosToProofApiDoc // @PreAuthorize("hasRole('SPONSOR')") @@ -45,4 +45,4 @@ // Authentication authentication) { // kudosService.addKudosToProof(proofId, amount, authentication); // } -//} \ No newline at end of file +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/kudos/repository/KudosRepository.java b/src/main/java/com/provedcode/kudos/repository/KudosRepository.java index e18d47e..8f489c9 100644 --- a/src/main/java/com/provedcode/kudos/repository/KudosRepository.java +++ b/src/main/java/com/provedcode/kudos/repository/KudosRepository.java @@ -3,8 +3,8 @@ import com.provedcode.kudos.model.entity.Kudos; import org.springframework.data.jpa.repository.JpaRepository; -//public interface KudosRepository extends JpaRepository { +public interface KudosRepository extends JpaRepository { // long countByProofId(Long id); // // boolean existsBySponsorIdAndProofId(Long sponsorId, Long proofId); -//} \ No newline at end of file +} \ 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 e392c02..5a91ce7 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -1,44 +1,45 @@ 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; -//import com.provedcode.talent.repo.TalentProofRepository; -//import com.provedcode.talent.repo.TalentRepository; -//import com.provedcode.user.model.entity.UserInfo; -//import com.provedcode.user.repo.UserInfoRepository; -//import lombok.AllArgsConstructor; -//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.HashMap; -//import java.util.Map; -//import java.util.Optional; -//import java.util.stream.Collectors; -// -//import static org.springframework.http.HttpStatus.*; -// -//@Service -//@AllArgsConstructor -//@Transactional -//public class KudosService { -// KudosRepository kudosRepository; -// TalentProofRepository talentProofRepository; -// UserInfoRepository userInfoRepository; -// SponsorRepository sponsorRepository; -// TalentRepository talentRepository; -// SponsorMapper sponsorMapper; +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.ProofSkill; +import com.provedcode.talent.model.entity.Talent; +import com.provedcode.talent.model.entity.TalentProof; +import com.provedcode.talent.repo.TalentProofRepository; +import com.provedcode.talent.repo.TalentRepository; +import com.provedcode.user.model.entity.UserInfo; +import com.provedcode.user.repo.UserInfoRepository; +import lombok.AllArgsConstructor; +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.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import static org.springframework.http.HttpStatus.*; + +@Service +@AllArgsConstructor +@Transactional +public class KudosService { + KudosRepository kudosRepository; + TalentProofRepository talentProofRepository; + UserInfoRepository userInfoRepository; + SponsorRepository sponsorRepository; + TalentRepository talentRepository; + SponsorMapper sponsorMapper; // public void addKudosToProof(long proofId, Optional setAmountKudos, Authentication authentication) { // String login = authentication.getName(); @@ -71,57 +72,58 @@ // .build()); // } + @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"); + } + Sponsor sponsor = sponsorRepository.findById(sponsorId).orElseThrow( + () -> new ResponseStatusException(NOT_FOUND, + String.format("Sponsor with id = %d not found", sponsorId))); + return new KudosAmount(sponsor.getAmountKudos()); + } + // @Transactional(readOnly = true) -// public KudosAmount getKudosForSponsor(long sponsorId, Authentication authentication) { +// 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))); -// if (!userInfo.getSponsor().getId().equals(sponsorId)) { -// throw new ResponseStatusException(FORBIDDEN, "Only the account owner can view the number of kudos"); -// } -// Sponsor sponsor = sponsorRepository.findById(sponsorId).orElseThrow( -// () -> new ResponseStatusException(NOT_FOUND, -// String.format("Sponsor with id = %d not found", sponsorId))); -// return new KudosAmount(sponsor.getAmountKudos()); -// } - -// @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.getTalent().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))); +// "User with login = %s not found".formatted(login))); +// Talent talent = talentRepository.findById(userInfo.getTalent().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); +// Long countOfAllKudos = talentProof.getProofSkills() +// .stream().flatMap(proofSkills -> proofSkills.getKudoses() +// .stream().map(kudos -> kudos.getAmount())) +// .reduce(0L, (prev, next) -> prev + next); // -// 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)); +// 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(); -// } +// return KudosAmountWithSponsor.builder() +// .allKudosOnProof(countOfAllKudos) +// .kudosFromSponsor(kudosFromSponsor) +// .build(); +// } else { +// return KudosAmountWithSponsor.builder() +// .allKudosOnProof(countOfAllKudos) +// .kudosFromSponsor(null).build(); +// } // } -//} \ No newline at end of file +} \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql index 49a11f2..c82f309 100644 --- a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql @@ -1,25 +1,25 @@ --liquibase formatted sql --changeset dennis:5 -insert into proof_skill (id, skill_id, proof_id) -values (1, 1, 1); -insert into proof_skill (id, skill_id, proof_id) -values (2, 2, 1); -insert into proof_skill (id, skill_id, proof_id) -values (3, 2, 2); -insert into proof_skill (id, skill_id, proof_id) -values (4, 3, 3); - +insert into proof_skill (skill_id, proof_id) +values (1, 1); +insert into proof_skill (skill_id, proof_id) +values (2, 1); +insert into proof_skill (skill_id, proof_id) +values (2, 2); +insert into proof_skill (skill_id, proof_id) +values (3, 3); +insert +into talent_skill(talent_id, skill_id) +values (1, 1); insert into talent_skill(talent_id, skill_id) -values (1,1); +values (1, 2); insert into talent_skill(talent_id, skill_id) -values (1,2); +values (1, 3); insert into talent_skill(talent_id, skill_id) -values (1,3); +values (2, 1); insert into talent_skill(talent_id, skill_id) -values (2,1); +values (2, 2); insert into talent_skill(talent_id, skill_id) -values (2,2); +values (2, 6); insert into talent_skill(talent_id, skill_id) -values (2,6); -insert into talent_skill(talent_id, skill_id) -values (3,1); \ No newline at end of file +values (3, 1); \ No newline at end of file From dc85c7a82314ffaee8a55e9f39e15121e38c2dcb Mon Sep 17 00:00:00 2001 From: Ren Date: Fri, 19 May 2023 20:08:34 +0300 Subject: [PATCH 45/59] Refactor database schema for sprint 5 This commit changes the database schema for sprint 5, creating new tables and moving columns from one table to another. New tables include talents, sponsors, attached_files, contacts, descriptions, links, proofs, skills, talents_skills, proofs_skills, users_info, authorities, and users_authorities. ForeignKey constraints show table relationships. New data inserts and deletions also reflect the changes made to the schema. --- .../db/changelog/changeset/V5/schema-V5.sql | 80 ------------------- .../changeset/V5/sponsor-schema-V5.sql | 20 +++++ .../changeset/V5/talent-schema-V5.sql | 65 +++++++++++++++ .../changeset/V5/user-info-schema-V5.sql | 22 +++++ .../db/changelog/db.changelog-master.yaml | 55 ++++++------- 5 files changed, 135 insertions(+), 107 deletions(-) create mode 100644 src/main/resources/db/changelog/changeset/V5/sponsor-schema-V5.sql create mode 100644 src/main/resources/db/changelog/changeset/V5/talent-schema-V5.sql create mode 100644 src/main/resources/db/changelog/changeset/V5/user-info-schema-V5.sql diff --git a/src/main/resources/db/changelog/changeset/V5/schema-V5.sql b/src/main/resources/db/changelog/changeset/V5/schema-V5.sql index 52064ef..cc43a0b 100644 --- a/src/main/resources/db/changelog/changeset/V5/schema-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/schema-V5.sql @@ -1,66 +1,3 @@ --- liquibase formatted sql --- changeset Ren:0 --- tables for sprint 5 --- Talent -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_skill ( - talent_id BIGINT NOT NULL, - skill_id BIGINT NOT NULL, - CONSTRAINT pk_talent_skill PRIMARY KEY (talent_id, skill_id) -); -CREATE TABLE proof_skill ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - proof_id BIGINT NOT NULL, - skill_id BIGINT NOT NULL, - CONSTRAINT pk_proof_skill PRIMARY KEY (id) -); -CREATE TABLE skill ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - skill VARCHAR(30), - CONSTRAINT pk_skill PRIMARY KEY (id) -); -- User CREATE TABLE user_info ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, @@ -80,23 +17,6 @@ CREATE TABLE user_authorities ( user_id BIGINT NOT NULL, CONSTRAINT pk_user_authorities PRIMARY KEY (authority_id, user_id) ); --- Sponsor -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) -); -CREATE TABLE kudos ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - sponsor_id BIGINT, - proof_skill_id BIGINT, - amount BIGINT, - CONSTRAINT pk_kudos PRIMARY KEY (id) -); -- Foreign keys ALTER TABLE talent_attached_file ADD CONSTRAINT FK_TALENT_ATTACHED_FILE_ON_TALENT FOREIGN KEY (talent_id) REFERENCES talent (id); diff --git a/src/main/resources/db/changelog/changeset/V5/sponsor-schema-V5.sql b/src/main/resources/db/changelog/changeset/V5/sponsor-schema-V5.sql new file mode 100644 index 0000000..e73f302 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V5/sponsor-schema-V5.sql @@ -0,0 +1,20 @@ +-- liquibase formatted sql +-- changeset Ren:0 +-- tables for sprint 5 +-- Sponsor +CREATE TABLE sponsors ( + 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, + PRIMARY KEY (id) +); +CREATE TABLE kudos ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + sponsor_id BIGINT REFERENCES sponsors, + proof_skill_id BIGINT REFERENCES proofs_skills, + amount BIGINT, + PRIMARY KEY (id) +); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V5/talent-schema-V5.sql b/src/main/resources/db/changelog/changeset/V5/talent-schema-V5.sql new file mode 100644 index 0000000..5871498 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V5/talent-schema-V5.sql @@ -0,0 +1,65 @@ +-- liquibase formatted sql +-- changeset Ren:0 +-- tables for sprint 5 +-- Talent +CREATE TABLE talents ( + 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), + PRIMARY KEY (id) +); +CREATE TABLE attached_files ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL REFERENCES talents, + attached_file VARCHAR(100), + PRIMARY KEY (id) +); +CREATE TABLE contacts ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL REFERENCES talents, + contact VARCHAR(255), + PRIMARY KEY (id) +); +CREATE TABLE descriptions ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL REFERENCES talents, + bio VARCHAR(2000), + addition_info VARCHAR(500), + PRIMARY KEY (id) +); +CREATE TABLE links ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL REFERENCES talents, + link VARCHAR(500), + PRIMARY KEY (id) +); +CREATE TABLE proofs ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT NOT NULL REFERENCES talents, + link VARCHAR(500), + text VARCHAR(1000), + status VARCHAR(20) NOT NULL, + created TIMESTAMP, + PRIMARY KEY (id) +); +CREATE TABLE skills ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + skill VARCHAR(30), + PRIMARY KEY (id) +); +CREATE TABLE talents_skills ( + talent_id BIGINT NOT NULL REFERENCES talents, + skill_id BIGINT NOT NULL REFERENCES skills, + PRIMARY KEY (talent_id, skill_id) +); +CREATE TABLE proofs_skills ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + proof_id BIGINT NOT NULL REFERENCES proofs, + skill_id BIGINT NOT NULL REFERENCES skills, + PRIMARY KEY (id) +); +-- Створення складеного унікального індексу +CREATE UNIQUE INDEX ON proofs_skills (id, proof_id, skill_id); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V5/user-info-schema-V5.sql b/src/main/resources/db/changelog/changeset/V5/user-info-schema-V5.sql new file mode 100644 index 0000000..97b1109 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V5/user-info-schema-V5.sql @@ -0,0 +1,22 @@ +-- liquibase formatted sql +-- changeset Ren:0 +-- tables for sprint 5 +-- User +CREATE TABLE users_info ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + talent_id BIGINT REFERENCES talents, + sponsor_id BIGINT REFERENCES sponsors, + login VARCHAR(100) NOT NULL, + password VARCHAR(255) NOT NULL, + PRIMARY KEY (id) +); +CREATE TABLE authorities ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + authority VARCHAR(20) NOT NULL, + PRIMARY KEY (id) +); +CREATE TABLE users_authorities ( + authority_id BIGINT NOT NULL REFERENCES authorities, + user_id BIGINT NOT NULL REFERENCES users_info, + PRIMARY KEY (authority_id, user_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 736b716..77eb9b2 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -1,28 +1,29 @@ databaseChangeLog: - - include: - file: db/changelog/changeset/V1/drop-V1.sql - - include: - file: db/changelog/changeset/V2/drop-V2.sql - - include: - file: db/changelog/changeset/V4/drop-V4.sql - - include: - file: db/changelog/changeset/V4/schema-V4.sql - - include: - file: db/changelog/changeset/V4/data-V4.sql - - include: - file: db/changelog/changeset/V4/data-V4.1.sql - - include: - file: db/changelog/changeset/V4/data-V4.2.sql - - include: - file: db/changelog/changeset/V5/drop-V5.sql - - include: - file: db/changelog/changeset/V5/schema-V5.sql - - include: - file: db/changelog/changeset/V5/data-V5.sql - - include: - file: db/changelog/changeset/V5/dataSkill-V5.sql - - include: - file: db/changelog/changeset/V5/dataKudos-V5.sql - - - + - include: + file: db/changelog/changeset/V1/drop-V1.sql + - include: + file: db/changelog/changeset/V2/drop-V2.sql + - include: + file: db/changelog/changeset/V4/drop-V4.sql + - include: + file: db/changelog/changeset/V4/schema-V4.sql + - include: + file: db/changelog/changeset/V4/data-V4.sql + - include: + file: db/changelog/changeset/V4/data-V4.1.sql + - include: + file: db/changelog/changeset/V4/data-V4.2.sql + - include: + file: db/changelog/changeset/V5/drop-V5.sql + - include: + file: db/changelog/changeset/V5/talent-schema-V5.sql + - include: + file: db/changelog/changeset/V5/sponsor-schema-V5.sql + - include: + file: db/changelog/changeset/V5/user-info-schema-V5.sql + - include: + file: db/changelog/changeset/V5/data-V5.sql + - include: + file: db/changelog/changeset/V5/dataSkill-V5.sql + - include: + file: db/changelog/changeset/V5/dataKudos-V5.sql From ca771aa95a95e0d79e4096a6d1cc642c428b8d62 Mon Sep 17 00:00:00 2001 From: Maslyna Date: Fri, 19 May 2023 20:05:51 +0200 Subject: [PATCH 46/59] Code refactor: old method from KudosController now works --- .../kudos/controller/KudosController.java | 20 +-- .../response/KudosAmountWithSponsor.java | 2 +- .../kudos/service/KudosService.java | 159 ++++++++++-------- src/main/resources/application-dev.properties | 3 +- .../changelog/changeset/V5/dataSkill-V5.sql | 17 +- 5 files changed, 116 insertions(+), 85 deletions(-) diff --git a/src/main/java/com/provedcode/kudos/controller/KudosController.java b/src/main/java/com/provedcode/kudos/controller/KudosController.java index a2315dc..878474b 100644 --- a/src/main/java/com/provedcode/kudos/controller/KudosController.java +++ b/src/main/java/com/provedcode/kudos/controller/KudosController.java @@ -19,7 +19,7 @@ @RestController @AllArgsConstructor @Validated -@RequestMapping("/api/v3/") +@RequestMapping("/api/v5/") public class KudosController { KudosService kudosService; @@ -36,13 +36,13 @@ KudosAmount getKudosForSponsor(@PathVariable("sponsor-id") long sponsorId, Authe KudosAmountWithSponsor getProofKudos(@PathVariable("proof-id") long proofId, Authentication authentication) { return kudosService.getProofKudos(proofId, 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); -// } + + @PostAddKudosToProofApiDoc + @PreAuthorize("hasRole('SPONSOR')") + @PostMapping("/proofs/{proof-id}/kudos") + void addKudosToProof(@PathVariable("proof-id") long proofId, + @RequestBody @Valid SetAmountKudos amount, + Authentication authentication) { + kudosService.addKudosToProof(proofId, amount, authentication); + } } \ 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 index 75b80f9..f7460c2 100644 --- a/src/main/java/com/provedcode/kudos/model/response/KudosAmountWithSponsor.java +++ b/src/main/java/com/provedcode/kudos/model/response/KudosAmountWithSponsor.java @@ -8,6 +8,6 @@ @Builder public record KudosAmountWithSponsor( Long allKudosOnProof, - Map kudosFromSponsor + Map> kudosFromSponsor ) { } diff --git a/src/main/java/com/provedcode/kudos/service/KudosService.java b/src/main/java/com/provedcode/kudos/service/KudosService.java index 5a91ce7..e880c54 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -10,9 +10,9 @@ 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.ProofSkill; import com.provedcode.talent.model.entity.Talent; import com.provedcode.talent.model.entity.TalentProof; +import com.provedcode.talent.repo.ProofSkillRepository; import com.provedcode.talent.repo.TalentProofRepository; import com.provedcode.talent.repo.TalentRepository; import com.provedcode.user.model.entity.UserInfo; @@ -25,7 +25,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.Optional; import java.util.stream.Collectors; import static org.springframework.http.HttpStatus.*; @@ -39,39 +38,9 @@ public class KudosService { UserInfoRepository userInfoRepository; SponsorRepository sponsorRepository; TalentRepository talentRepository; + ProofSkillRepository proofSkillRepository; 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"); -// } -// sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); -// kudosRepository.save(Kudos.builder() -// .amount(obtainedAmount) -// .proof(talentProof) -// .sponsor(sponsor) -// .build()); -// } - @Transactional(readOnly = true) public KudosAmount getKudosForSponsor(long sponsorId, Authentication authentication) { String login = authentication.getName(); @@ -88,42 +57,88 @@ public KudosAmount getKudosForSponsor(long sponsorId, Authentication authenticat return new KudosAmount(sponsor.getAmountKudos()); } -// @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.getTalent().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.getProofSkills() -// .stream().flatMap(proofSkills -> proofSkills.getKudoses() -// .stream().map(kudos -> kudos.getAmount())) -// .reduce(0L, (prev, next) -> prev + next); -// -// 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(); -// } -// } -} \ No newline at end of file + @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.getTalent().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.getProofSkills() + .stream().flatMap(proofSkills -> proofSkills.getKudoses() + .stream().map(Kudos::getAmount)) + .reduce(0L, (prev, next) -> prev + next); + + if (talent.getId().equals(talentProof.getTalent().getId())) { + Map> skillsMap = new HashMap<>(); + talentProof.getProofSkills().forEach(proofSkill -> { // I dnk wtf is this piece of shit, but it works. + String skill = proofSkill.getSkill().getSkill(); + Map kudosFromSponsor = talentProof.getProofSkills().stream() + .filter(proofSkills -> proofSkills.getSkill().getSkill().equals(skill)) + .flatMap(proofSkills -> proofSkills.getKudoses().stream()) + .collect(Collectors.toMap( + Kudos::getAmount, + proof -> proof.getSponsor() != null + ? sponsorMapper.toDto(proof.getSponsor()) + : SponsorDTO.builder().build(), + (prev, next) -> next, + HashMap::new)); + skillsMap.put(skill, kudosFromSponsor); + }); + return KudosAmountWithSponsor.builder() + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(skillsMap) + .build(); + } else { + return KudosAmountWithSponsor.builder() + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(null).build(); + } + } + + + public void addKudosToProof(long proofId, SetAmountKudos amountOfKudoses, 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 (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) + throw new ResponseStatusException(FORBIDDEN, "Proof that was kudosed does not have the PUBLISHED status"); + long obtainedAmount = amountOfKudoses.amount(); + + if (sponsor.getAmountKudos() < obtainedAmount) { + throw new ResponseStatusException(FORBIDDEN, "The sponsor cannot give more kudos than he has"); + } + if (obtainedAmount % talentProof.getProofSkills().size() != 0) { + throw new ResponseStatusException(BAD_REQUEST, + "Sponsor cannot add amount of kudos that multiple of amount of skills"); + } + sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); + + Long addKudoses = obtainedAmount / talentProof.getProofSkills().size(); + + talentProof.getProofSkills().forEach(proofSkill -> { + Kudos kudos = Kudos.builder() + .sponsor(sponsor) + .skill(proofSkill) + .amount(addKudoses) + .build(); + proofSkill.getKudoses().add(kudosRepository.save(kudos)); + }); + + } +} diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 6bd5814..60dd6cf 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -2,4 +2,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 #logging.level.web=DEBUG -#logging.level.sql=DEBUG \ No newline at end of file +#logging.level.sql=DEBUG +spring.jpa.show-sql=true \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql index 800c6b7..f69e630 100644 --- a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql @@ -7,4 +7,19 @@ values (2, 1); insert into proof_skill (skill_id, proof_id) values (2, 2); insert into proof_skill (skill_id, proof_id) -values (3, 3) \ No newline at end of file +values (3, 3); + +insert into talent_skill(talent_id, skill_id) +values (1, 1); +insert into talent_skill(talent_id, skill_id) +values (1, 2); +insert into talent_skill(talent_id, skill_id) +values (1, 3); +insert into talent_skill(talent_id, skill_id) +values (2, 1); +insert into talent_skill(talent_id, skill_id) +values (2, 2); +insert into talent_skill(talent_id, skill_id) +values (2, 6); +insert into talent_skill(talent_id, skill_id) +values (3, 1); \ No newline at end of file From eba1b78d07e20236e36c9ce240086934282303ff Mon Sep 17 00:00:00 2001 From: Ren Date: Fri, 19 May 2023 21:58:33 +0300 Subject: [PATCH 47/59] Refactor SQL queries to use new table names and columns To improve the organization of the database, SQL queries were refactored to use new table names and columns. The corresponding code was modified to insert data into the updated tables. The commit message describes the changes made to the SQL statements and the affected tables without going into specifics. --- .../db/changelog/changeset/V5/data-V5.sql | 3641 +++++++++-------- .../changelog/changeset/V5/dataSkill-V5.sql | 8 +- 2 files changed, 2033 insertions(+), 1616 deletions(-) diff --git a/src/main/resources/db/changelog/changeset/V5/data-V5.sql b/src/main/resources/db/changelog/changeset/V5/data-V5.sql index ff60b1d..b897501 100644 --- a/src/main/resources/db/changelog/changeset/V5/data-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/data-V5.sql @@ -1,1650 +1,2067 @@ --liquibase formatted sql --changeset Ren:0 -- Authority -insert into authority (id, authority) +insert into authorities (id, authority) values (1, 'TALENT'); -insert into authority (id, authority) +insert into authorities (id, authority) values (2, 'SPONSOR'); -- Skill -insert into skill (id, skill) +insert into skills (id, skill) values (1, 'Java Core'); -insert into skill (id, skill) +insert into skills (id, skill) values (2, 'Spring Core'); -insert into skill (id, skill) +insert into skills (id, skill) values (3, 'Spring boot'); -insert into skill (id, skill) +insert into skills (id, skill) values (4, 'H2 Database'); -insert into skill (id, skill) +insert into skills (id, skill) values (5, 'Spring Security'); -insert into skill (id, skill) +insert into skills (id, skill) values (6, 'REST API'); -insert into skill (id, skill) +insert into skills (id, skill) values (7, 'Git'); -insert into skill (id, skill) +insert into skills (id, skill) values (8, 'Docker'); -insert into skill (id, skill) +insert into skills (id, skill) values (9, 'Jira'); -insert into skill (id, skill) +insert into skills (id, skill) values (10, 'JavaScript Core'); -insert into skill (id, skill) +insert into skills (id, skill) values (11, 'React'); -insert into skill (id, skill) +insert into skills (id, skill) values (12, 'Node.js'); -insert into skill (id, skill) +insert into skills (id, skill) values (13, 'Angular'); -- Talent -- Serhii Soloviov -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_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 talents (first_name, last_name, specialization, image) +values ( + 'Serhii', + 'Soloviov', + 'Java-Developer', + 'https://i.pinimg.com/564x/e1/08/49/e10849923a8b2e85a7adf494ebd063e6.jpg' + ); +insert into descriptions (talent_id, bio, addition_info) +values ( + ( + select id + from talents + 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 links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'first_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'second_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'third_contact' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 users_info (talent_id, login, password) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'SerhiiSoloviov@gmail.com', '$2a$10$EzYxG1DEUek/veK.HzP7B.ynSKE42VbLb4pvFd/v4OwGPNol6buEC' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 1 + ) + ); -- Mykhailo Ordyntsev -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_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 talents (first_name, last_name, specialization, image) +values ( + 'Mykhailo', + 'Ordyntsev', + 'Java-Developer', + 'https://i.pinimg.com/564x/c2/41/31/c24131fe00218467721ba5bacdf0a256.jpg' + ); +insert into descriptions (talent_id, bio, addition_info) +values ( + ( + select id + from talents + 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 links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'MykhailoOrdyntsev_first_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'MykhailoOrdyntsev_second_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'MykhailoOrdyntsev_third_contact' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 users_info (talent_id, login, password) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'MykhailoOrdyntsev@gmail.com', '$2a$10$XD60M86n1MDf3AMIixgnnOQq9JVYnnX/umlNFcre0GoC2XgSN/Cfq' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 1 + ) + ); -- Denis Boyko -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_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 talents (first_name, last_name, specialization, image) +values ( + 'Denis', + 'Boyko', + 'Java-Developer', + 'https://i.pinimg.com/564x/2a/0c/08/2a0c08c421e253ca895c3fdc8c9e08d9.jpg' + ); +insert into descriptions (talent_id, bio, addition_info) +values ( + ( + select id + from talents + 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 links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'DenisBoyko_first_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'DenisBoyko_second_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'DenisBoyko_third_contact' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 users_info (talent_id, login, password) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'DenisBoyko@gmail.com', '$2a$10$tLm27FGH8Sabz57eNkTwm.bSnhmJHINcqt7dNfZI0NfOwD2o/Drse' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 1 + ) + ); -- Ihor Schurenko -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_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 talents (first_name, last_name, specialization, image) +values ( + 'Ihor', + 'Schurenko', + 'Java-Developer', + 'https://i.pinimg.com/564x/e1/11/2f/e1112f0b7b63644dc3e313084936dedb.jpg' + ); +insert into descriptions (talent_id, bio, addition_info) +values ( + ( + select id + from talents + 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 links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'IhorShchurenko_first_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'IhorShchurenko_second_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'IhorShchurenko_third_contact' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 users_info (talent_id, login, password) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'IhorShchurenko@gmail.com', '$2a$10$X.d4hR.yRf3cK0Go20aTTukOI9u/Zu2cj5WU0iTcDihyhJ5vUHXkq' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 1 + ) + ); -- Dmytro Uzun -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_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 talents (first_name, last_name, specialization, image) +values ( + 'Dmytro', + 'Uzun', + 'Dev-Ops', + 'https://i.pinimg.com/564x/1c/af/87/1caf8771ef3edf351f6f2bf6f1c0a276.jpg' + ); +insert into descriptions (talent_id, bio, addition_info) +values ( + ( + select id + from talents + 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 links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'DmytroUzun_first_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'DmytroUzun_second_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'DmytroUzun_third_contact' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 users_info (talent_id, login, password) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'DmytroUzun@gmail.com', '$2a$10$J2Yuh10BWHy8XYk.T5rd2uOwk/h5EYG1eVXTAOkTkTdQcc5Qzd9.y' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 1 + ) + ); -- Viktor Voloshko -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_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 talents (first_name, last_name, specialization, image) +values ( + 'Viktor', + 'Voloshko', + 'Dev-Ops', + 'https://i.pinimg.com/564x/a9/51/ab/a951ab682413b89617235e65564c1e5e.jpg' + ); +insert into descriptions (talent_id, bio, addition_info) +values ( + ( + select id + from talents + 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 links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'ViktorVoloshko_first_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'ViktorVoloshko_second_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'ViktorVoloshko_third_contact' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 users_info (talent_id, login, password) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'ViktorVoloshko@gmail.com', '$2a$10$eZX3hBvllxkmH.juZzN72uvFYtphkrxsj14K5BnHHKy4coRV9FMvq' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 1 + ) + ); -- Olha Moiseienko -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_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 talents (first_name, last_name, specialization, image) +values ( + 'Olha', + 'Moiseienko', + 'QA', + 'https://i.pinimg.com/564x/6d/9d/43/6d9d437baf4db114c047d927307beb84.jpg' + ); +insert into descriptions (talent_id, bio, addition_info) +values ( + ( + select id + from talents + 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 links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'OlhaMoiseienko_first_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'OlhaMoiseienko_second_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'OlhaMoiseienko_third_contact' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 users_info (talent_id, login, password) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'OlhaMoiseienko@gmail.com', '$2a$10$lvvX7DZOwCS/Q7zSo.k.oeayTcKHh8rO1yBBkgIbU4VAC7abPfIa2' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 1 + ) + ); -- Maxim Kiyashko -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_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 talents (first_name, last_name, specialization, image) +values ( + 'Maxim', + 'Kiyashko', + 'QA', + 'https://i.pinimg.com/564x/80/2d/58/802d58b0302985f9486893d499d3634d.jpg' + ); +insert into descriptions (talent_id, bio, addition_info) +values ( + ( + select id + from talents + 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 links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'MaximKiyashko_first_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'MaximKiyashko_second_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'MaximKiyashko_third_contact' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 users_info (talent_id, login, password) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'MaximKiyashko@gmail.com', '$2a$10$y.g9qHYUOPEkIL8xDc2h1.EdVAG5DYh6OKxf9CRb6s16oHHbr8Bny' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 1 + ) + ); -- Nikolaiev Oleksii -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_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 talents (first_name, last_name, specialization, image) +values ( + 'Nikolaiev', + 'Oleksii', + 'QA', + 'https://i.pinimg.com/564x/54/d1/0d/54d10dfce64afefabc9fbbce5de82c87.jpg' + ); +insert into descriptions (talent_id, bio, addition_info) +values ( + ( + select id + from talents + 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 links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'NikolaievOleksii_first_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'NikolaievOleksii_second_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'NikolaievOleksii_third_contact' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 users_info (talent_id, login, password) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'NikolaievOleksiio@gmail.com', '$2a$10$nDObO3nDlhWev29qCnzNuOszdg/.ANaMlTirDVWVyLMapYmtSSqza' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 1 + ) + ); -- Artem Lytvynenko -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_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 talents (first_name, last_name, specialization, image) +values ( + 'Artem', + 'Lytvynenko', + 'QA', + 'https://i.pinimg.com/564x/87/63/55/87635509c5fa7ee496ec351fa7e67eaa.jpg' + ); +insert into descriptions (talent_id, bio, addition_info) +values ( + ( + select id + from talents + 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 links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'ArtemLytvynenko_first_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'ArtemLytvynenko_second_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'ArtemLytvynenko_third_contact' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 users_info (talent_id, login, password) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'ArtemLytvynenko@gmail.com', '$2a$10$.M2fHh9NXbkbnrVHeT.lYeInA8K2khuMUL08iG4NuXs18KIeFBmwG' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 1 + ) + ); -- Daniil Yevtukhov -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_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 talents (first_name, last_name, specialization, image) +values ( + 'Daniil', + 'Yevtukhov', + 'Java-Script-Developer', + 'https://i.pinimg.com/564x/fe/b1/37/feb137d88a3d1c8fb28796db6cbc576f.jpg' + ); +insert into descriptions (talent_id, bio, addition_info) +values ( + ( + select id + from talents + 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 links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'DaniilYevtukhov_first_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'DaniilYevtukhov_second_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'DaniilYevtukhov_third_contact' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 users_info (talent_id, login, password) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'DaniilYevtukhov@gmail.com', '$2a$10$cDxp6U/YcObKMwZNgtEB5eZFLWXuwFU0lIUSPIkfPdvq9l8JUqGea' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 1 + ) + ); -- Ruslan Morozov -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_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 talents (first_name, last_name, specialization, image) +values ( + 'Ruslan', + 'Morozov', + 'Java-Script-Developer', + 'https://i.pinimg.com/736x/36/ae/0e/36ae0ea4aad656f7c3d3175bc33b8399.jpg' + ); +insert into descriptions (talent_id, bio, addition_info) +values ( + ( + select id + from talents + 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 links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'RuslanMorozov_first_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'RuslanMorozov_second_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'RuslanMorozov_third_contact' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 users_info (talent_id, login, password) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'RuslanMorozov@gmail.com', '$2a$10$Hfzp4b6r825g1ZqGzxmal..VNKvo7F4v4YFpBZZ036hmO.7UIWlaK' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 1 + ) + ); -- Ihor Kopieichykov -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_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 talents (first_name, last_name, specialization, image) +values ( + 'Ihor', + 'Kopieichykov', + 'Java-Script-Developer', + 'https://i.pinimg.com/564x/0d/f0/83/0df083121bac75f64e3d93c7c5682d04.jpg' + ); +insert into descriptions (talent_id, bio, addition_info) +values ( + ( + select id + from talents + 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 links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into links (talent_id, link) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'IhorKopieichykov_first_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'IhorKopieichykov_second_contact' + ); +insert into contacts (talent_id, contact) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'IhorKopieichykov_third_contact' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into attached_files (talent_id, attached_file) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + ); +insert into proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 proofs (talent_id, link, text, status, created) +values ( + ( + select id + from talents + 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 users_info (talent_id, login, password) +values ( + ( + select id + from talents + order by id desc + limit 1 + ), 'IhorKopieichykov@gmail.com', '$2a$10$D4KM50WemOahkFv1fkrPX.MvVESsE0TYWlkh5TypTE/q4nlv8ooyS' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 1 + ) + ); -- Sponsor -- Maksym Khudoliy -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 sponsors (amount_kudos, first_name, last_name, image) +values ( + 888, + 'Maksym', + 'Khudoliy', + 'https://i.pinimg.com/564x/e1/08/49/e10849923a8b2e85a7adf494ebd063e6.jpg' + ); +insert into users_info (sponsor_id, login, password) +values ( + ( + select id + from sponsors + order by id desc + limit 1 + ), 'MaksymKhudoliy@gmail.com', '$2a$10$pDrAuawhi3ADZpVDDr7C6eAcaQwDr5oQ9GdZUUZHSsqyM/vVkpruy' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 2 + ) + ); -- Oleksandr Butrym -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 sponsors (amount_kudos, first_name, last_name, image) +values ( + 888, + 'Oleksandr', + 'Butrym', + 'https://i.pinimg.com/564x/c2/41/31/c24131fe00218467721ba5bacdf0a256.jpg' + ); +insert into users_info (sponsor_id, login, password) +values ( + ( + select id + from sponsors + order by id desc + limit 1 + ), 'OleksandrButrym@gmail.com', '$2a$10$R0o8os0t86qyBvg0bO/a6ukuy9VesLapxIkZFLjNupWjvr5Hdjyge' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 2 + ) + ); -- Olha Shutylieva -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 sponsors (amount_kudos, first_name, last_name, image) +values ( + 888, + 'Olha', + 'Shutylieva', + 'https://i.pinimg.com/564x/2a/0c/08/2a0c08c421e253ca895c3fdc8c9e08d9.jpg' + ); +insert into users_info (sponsor_id, login, password) +values ( + ( + select id + from sponsors + order by id desc + limit 1 + ), 'OlhaShutylieva@gmail.com', '$2a$10$UzwVTVR7E2BW.5hA4XWgy.g0XcM.UbIMBoY1cDnYNPQDhCXEa7eGm' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 2 + ) + ); -- Vladyslav Khrychov -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 sponsors (amount_kudos, first_name, last_name, image) +values ( + 888, + 'Vladyslav', + 'Khrychov', + 'https://i.pinimg.com/564x/e1/11/2f/e1112f0b7b63644dc3e313084936dedb.jpg' + ); +insert into users_info (sponsor_id, login, password) +values ( + ( + select id + from sponsors + order by id desc + limit 1 + ), 'VladyslavKhrychov@gmail.com', '$2a$10$o2va23ZPVVSptyCaSBO/oubpML4xEPZo9Ie0ASt154zNVSKdFrN02' + ); +insert into users_authorities (user_id, authority_id) +values ( + ( + select id + from users_info + order by id desc + limit 1 + ), ( + select id + from authorities + where id = 2 + ) + ); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql index 85f124b..25d9ed0 100644 --- a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql @@ -1,10 +1,10 @@ --liquibase formatted sql --changeset dennis:5 -insert into proof_skill (id, skill_id, proof_id) +insert into proofs_skills (id, skill_id, proof_id) values (1, 1, 1); -insert into proof_skill (id, skill_id, proof_id) +insert into proofs_skills (id, skill_id, proof_id) values (2, 2, 1); -insert into proof_skill (id, skill_id, proof_id) +insert into proofs_skills (id, skill_id, proof_id) values (3, 2, 2); -insert into proof_skill (id, skill_id, proof_id) +insert into proofs_skills (id, skill_id, proof_id) values (4, 3, 3) \ No newline at end of file From 6b033757de56accda73f12aa41622d514c7a74f8 Mon Sep 17 00:00:00 2001 From: Ren Date: Fri, 19 May 2023 22:00:25 +0300 Subject: [PATCH 48/59] Refactor database column constraints and entity attributes Changed constraints in Kudos and Sponsor entity tables, along with attributes and relationships. Also updated SkillMapper to reflect SkillDTO changes. --- .../provedcode/kudos/model/entity/Kudos.java | 21 +++++++++++--- .../sponsor/model/entity/Sponsor.java | 28 +++++++++++++------ .../provedcode/talent/mapper/SkillMapper.java | 5 ++-- 3 files changed, 39 insertions(+), 15 deletions(-) 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 45e118d..f4d1df1 100644 --- a/src/main/java/com/provedcode/kudos/model/entity/Kudos.java +++ b/src/main/java/com/provedcode/kudos/model/entity/Kudos.java @@ -2,9 +2,21 @@ import com.provedcode.sponsor.model.entity.Sponsor; import com.provedcode.talent.model.entity.ProofSkill; -import com.provedcode.talent.model.entity.TalentProof; -import jakarta.persistence.*; -import lombok.*; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.validation.constraints.Positive; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; @Getter @Setter @@ -16,9 +28,10 @@ public class Kudos { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", nullable = false) + @Column(name = "id", nullable = false, updatable = false, insertable = false) private Long id; @Column(name = "amount") + @Positive private Long amount; @ManyToOne @JoinColumn(name = "sponsor_id") diff --git a/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java b/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java index 662de41..e698366 100644 --- a/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java +++ b/src/main/java/com/provedcode/sponsor/model/entity/Sponsor.java @@ -1,25 +1,37 @@ 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; +import org.hibernate.validator.constraints.URL; + +import com.provedcode.kudos.model.entity.Kudos; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import jakarta.validation.constraints.NotEmpty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + @Builder @AllArgsConstructor @NoArgsConstructor @Getter @Setter @Entity -@Table(name = "sponsor") +@Table(name = "sponsors") public class Sponsor { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", nullable = false) + @Column(name = "id", nullable = false, insertable = false, updatable = false) private Long id; @Column(name = "amount_kudos") private Long amountKudos; diff --git a/src/main/java/com/provedcode/talent/mapper/SkillMapper.java b/src/main/java/com/provedcode/talent/mapper/SkillMapper.java index 319185e..c2eabf4 100644 --- a/src/main/java/com/provedcode/talent/mapper/SkillMapper.java +++ b/src/main/java/com/provedcode/talent/mapper/SkillMapper.java @@ -1,13 +1,12 @@ package com.provedcode.talent.mapper; import com.provedcode.talent.model.dto.SkillDTO; -import com.provedcode.talent.model.entity.Skills; +import com.provedcode.talent.model.entity.Skill; import org.mapstruct.Mapper; import org.mapstruct.MappingConstants; import org.mapstruct.ReportingPolicy; @Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING) public interface SkillMapper { - SkillDTO skillToSkillDTO(Skills skills); - + SkillDTO skillToSkillDTO(Skill skills); } From faab83d518d96f33b02451bf090784f4d90c5fb5 Mon Sep 17 00:00:00 2001 From: Ren Date: Fri, 19 May 2023 22:00:41 +0300 Subject: [PATCH 49/59] Refactor code by changing table names and some class names to follow naming convention. --- .../talent/model/entity/ProofSkill.java | 36 +++++++++++-------- .../model/entity/{Skills.java => Skill.java} | 8 +++-- 2 files changed, 26 insertions(+), 18 deletions(-) rename src/main/java/com/provedcode/talent/model/entity/{Skills.java => Skill.java} (86%) diff --git a/src/main/java/com/provedcode/talent/model/entity/ProofSkill.java b/src/main/java/com/provedcode/talent/model/entity/ProofSkill.java index a61bbc7..3739cbe 100644 --- a/src/main/java/com/provedcode/talent/model/entity/ProofSkill.java +++ b/src/main/java/com/provedcode/talent/model/entity/ProofSkill.java @@ -1,18 +1,27 @@ package com.provedcode.talent.model.entity; -import jakarta.persistence.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import org.hibernate.Hibernate; + +import com.provedcode.kudos.model.entity.Kudos; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.hibernate.Hibernate; - -import com.provedcode.kudos.model.entity.Kudos; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; @Builder @Entity @@ -20,23 +29,20 @@ @Setter @AllArgsConstructor @NoArgsConstructor -@Table(name = "proof_skill") +@Table(name = "proofs_skills") public class ProofSkill { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(nullable = false, insertable = false, updatable = false) private Long id; - @ManyToOne @JoinColumn(name = "proof_id") private TalentProof talentProof; - @ManyToOne @JoinColumn(name = "skill_id") - private Skills skill; - - @OneToMany(mappedBy = "skill", orphanRemoval = true) - private List kudoses = new ArrayList<>(); + private Skill skill; + @OneToMany(mappedBy = "skill") + private List kudos = new ArrayList<>(); @Override public boolean equals(Object o) { diff --git a/src/main/java/com/provedcode/talent/model/entity/Skills.java b/src/main/java/com/provedcode/talent/model/entity/Skill.java similarity index 86% rename from src/main/java/com/provedcode/talent/model/entity/Skills.java rename to src/main/java/com/provedcode/talent/model/entity/Skill.java index 2bc15bd..01fe8d3 100644 --- a/src/main/java/com/provedcode/talent/model/entity/Skills.java +++ b/src/main/java/com/provedcode/talent/model/entity/Skill.java @@ -19,8 +19,8 @@ @Getter @Setter @Entity -@Table(name = "skill") -public class Skills { +@Table(name = "skills") +public class Skill { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) @@ -29,6 +29,8 @@ public class Skills { private String skill; @ManyToMany(mappedBy = "skills") private Set talents = new LinkedHashSet<>(); + @ManyToMany(mappedBy = "skill") + private Set proofSkills = new LinkedHashSet<>(); @Override public boolean equals(Object o) { @@ -36,7 +38,7 @@ public boolean equals(Object o) { return true; if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false; - Skills skills = (Skills) o; + Skill skills = (Skill) o; return getId() != null && Objects.equals(getId(), skills.getId()); } From 6237c6bbca7069560c8584f19387d266ff5c33ea Mon Sep 17 00:00:00 2001 From: Ren Date: Fri, 19 May 2023 22:00:50 +0300 Subject: [PATCH 50/59] Restructure table names for talents' skill sets, attached files, contact information Changed table names for talents' skill sets, attached files, and contact information for clarity and consistency. --- .../talent/model/entity/Talent.java | 8 +++---- .../model/entity/TalentAttachedFile.java | 22 ++++++++++++++----- .../talent/model/entity/TalentContact.java | 19 ++++++++++++---- 3 files changed, 35 insertions(+), 14 deletions(-) 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 cbb2f54..bed3a74 100644 --- a/src/main/java/com/provedcode/talent/model/entity/Talent.java +++ b/src/main/java/com/provedcode/talent/model/entity/Talent.java @@ -34,7 +34,7 @@ @Getter @Setter @Entity -@Table(name = "talent") +@Table(name = "talents") public class Talent { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -66,8 +66,6 @@ public class Talent { @OneToMany(mappedBy = "talent", cascade = CascadeType.ALL, orphanRemoval = true) private List talentProofs = new ArrayList<>(); @ManyToMany - @JoinTable(name = "talent_skill", - joinColumns = @JoinColumn(name = "talent_id"), - inverseJoinColumns = @JoinColumn(name = "skill_id")) - private Set skills = new LinkedHashSet<>(); + @JoinTable(name = "talents_skills", joinColumns = @JoinColumn(name = "talent_id"), inverseJoinColumns = @JoinColumn(name = "skill_id")) + private Set skills = new LinkedHashSet<>(); } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/model/entity/TalentAttachedFile.java b/src/main/java/com/provedcode/talent/model/entity/TalentAttachedFile.java index b35fdb5..3b0d1d5 100644 --- a/src/main/java/com/provedcode/talent/model/entity/TalentAttachedFile.java +++ b/src/main/java/com/provedcode/talent/model/entity/TalentAttachedFile.java @@ -1,20 +1,32 @@ package com.provedcode.talent.model.entity; -import jakarta.persistence.*; -import jakarta.validation.constraints.NotNull; -import lombok.*; import org.hibernate.validator.constraints.URL; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; @NoArgsConstructor @AllArgsConstructor @Builder @Getter @Setter @Entity -@Table(name = "talent_attached_file") +@Table(name = "attached_files") public class TalentAttachedFile { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", nullable = false) + @Column(name = "id", nullable = false, insertable = false, updatable = false) private Long id; @NotNull @ManyToOne diff --git a/src/main/java/com/provedcode/talent/model/entity/TalentContact.java b/src/main/java/com/provedcode/talent/model/entity/TalentContact.java index 48a390b..d052694 100644 --- a/src/main/java/com/provedcode/talent/model/entity/TalentContact.java +++ b/src/main/java/com/provedcode/talent/model/entity/TalentContact.java @@ -1,8 +1,19 @@ package com.provedcode.talent.model.entity; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import jakarta.validation.constraints.NotNull; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; @NoArgsConstructor @AllArgsConstructor @@ -10,11 +21,11 @@ @Getter @Setter @Entity -@Table(name = "talent_contact") +@Table(name = "contacts") public class TalentContact { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", nullable = false) + @Column(name = "id", nullable = false, insertable = false, updatable = false) private Long id; @NotNull @ManyToOne From 8e1bed7c89e2c25898912862738c7064f36d191f Mon Sep 17 00:00:00 2001 From: Ren Date: Fri, 19 May 2023 22:01:11 +0300 Subject: [PATCH 51/59] Refactor entity names and table names for consistency This commit refactors entity and table names for coherence between TalentLink, TalentProof, and TalentDescription entities. --- .../model/entity/TalentDescription.java | 21 +++++++++++++---- .../talent/model/entity/TalentLink.java | 23 +++++++++++++++---- .../talent/model/entity/TalentProof.java | 4 ++-- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/provedcode/talent/model/entity/TalentDescription.java b/src/main/java/com/provedcode/talent/model/entity/TalentDescription.java index 21629d3..a1d9eb9 100644 --- a/src/main/java/com/provedcode/talent/model/entity/TalentDescription.java +++ b/src/main/java/com/provedcode/talent/model/entity/TalentDescription.java @@ -1,8 +1,19 @@ package com.provedcode.talent.model.entity; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; import jakarta.validation.constraints.NotNull; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; import lombok.experimental.Accessors; @Builder @@ -12,17 +23,17 @@ @Getter @Setter @Entity -@Table(name = "talent_description") +@Table(name = "descriptions") public class TalentDescription { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(nullable = false) + @Column(nullable = false, insertable = false, updatable = false) private Long id; @NotNull @OneToOne(orphanRemoval = true) @JoinColumn(name = "talent_id", updatable = false) private Talent talent; - @Column(name = "BIO") + @Column(name = "bio") private String bio; @Column(name = "addition_info") private String additionalInfo; diff --git a/src/main/java/com/provedcode/talent/model/entity/TalentLink.java b/src/main/java/com/provedcode/talent/model/entity/TalentLink.java index bcb4fac..6a343c1 100644 --- a/src/main/java/com/provedcode/talent/model/entity/TalentLink.java +++ b/src/main/java/com/provedcode/talent/model/entity/TalentLink.java @@ -1,20 +1,33 @@ package com.provedcode.talent.model.entity; -import jakarta.persistence.*; -import jakarta.validation.constraints.NotNull; -import lombok.*; import org.hibernate.validator.constraints.URL; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + @NoArgsConstructor @AllArgsConstructor @Builder @Getter @Setter @Entity -@Table(name = "talent_link") +@Table(name = "links") public class TalentLink { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(nullable = false) + @Column(nullable = false, insertable = false, updatable = false) private Long id; @NotNull @ManyToOne diff --git a/src/main/java/com/provedcode/talent/model/entity/TalentProof.java b/src/main/java/com/provedcode/talent/model/entity/TalentProof.java index 4f4f178..68aead0 100644 --- a/src/main/java/com/provedcode/talent/model/entity/TalentProof.java +++ b/src/main/java/com/provedcode/talent/model/entity/TalentProof.java @@ -41,11 +41,11 @@ @Getter @Setter @Entity -@Table(name = "talent_proofs") +@Table(name = "proofs") public class TalentProof { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", nullable = false) + @Column(name = "id", nullable = false, insertable = false, updatable = false) private Long id; @NotNull @ManyToOne From a08be8601ff4975a37018983afd360640ee959e5 Mon Sep 17 00:00:00 2001 From: Ren Date: Fri, 19 May 2023 22:01:29 +0300 Subject: [PATCH 52/59] refactor: Rename Skills entity to Skill and update references in services and repositories The Skills entity has been renamed to Skill. All references to Skills have been updated in ProofSkillsService, TalentProofService, and SkillsRepository. This refactor allows for more intuitive and consistent code. --- .../java/com/provedcode/talent/repo/SkillsRepository.java | 6 +++--- .../com/provedcode/talent/service/ProofSkillsService.java | 2 +- .../com/provedcode/talent/service/TalentProofService.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/provedcode/talent/repo/SkillsRepository.java b/src/main/java/com/provedcode/talent/repo/SkillsRepository.java index 384d489..08b0fc8 100644 --- a/src/main/java/com/provedcode/talent/repo/SkillsRepository.java +++ b/src/main/java/com/provedcode/talent/repo/SkillsRepository.java @@ -1,12 +1,12 @@ package com.provedcode.talent.repo; -import com.provedcode.talent.model.entity.Skills; +import com.provedcode.talent.model.entity.Skill; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import java.util.List; -public interface SkillsRepository extends JpaRepository { +public interface SkillsRepository extends JpaRepository { @Query("select s from Skills s where upper(s.skill) like upper(concat('%', ?1, '%'))") - List findBySkillContainsIgnoreCase(String skill); + List findBySkillContainsIgnoreCase(String skill); } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/service/ProofSkillsService.java b/src/main/java/com/provedcode/talent/service/ProofSkillsService.java index a851c7d..4d09696 100644 --- a/src/main/java/com/provedcode/talent/service/ProofSkillsService.java +++ b/src/main/java/com/provedcode/talent/service/ProofSkillsService.java @@ -5,7 +5,7 @@ import com.provedcode.talent.model.dto.ProofSkillsDTO; import com.provedcode.talent.model.dto.SkillDTO; import com.provedcode.talent.model.dto.SkillsOnProofDTO; -import com.provedcode.talent.model.entity.Skills; +import com.provedcode.talent.model.entity.Skill; import com.provedcode.talent.model.entity.Talent; import com.provedcode.talent.model.entity.TalentProof; import com.provedcode.talent.repo.SkillsRepository; diff --git a/src/main/java/com/provedcode/talent/service/TalentProofService.java b/src/main/java/com/provedcode/talent/service/TalentProofService.java index 4c58c93..ae17ac0 100644 --- a/src/main/java/com/provedcode/talent/service/TalentProofService.java +++ b/src/main/java/com/provedcode/talent/service/TalentProofService.java @@ -5,7 +5,7 @@ import com.provedcode.talent.model.dto.FullProofDTO; import com.provedcode.talent.model.dto.ProofDTO; import com.provedcode.talent.model.dto.StatusDTO; -import com.provedcode.talent.model.entity.Skills; +import com.provedcode.talent.model.entity.Skill; import com.provedcode.talent.model.entity.Talent; import com.provedcode.talent.model.entity.TalentProof; import com.provedcode.talent.model.request.AddProof; From d0c76221eb023995d51b8a0f9d4edd376cc2d235 Mon Sep 17 00:00:00 2001 From: Ren Date: Fri, 19 May 2023 22:01:38 +0300 Subject: [PATCH 53/59] Refactor TalentService, Authority, and UserInfo entities - Use Skill instead of Skills to represent a unique skill - Use "authorities" instead of "authority" table name for UserInfo entity - Use "users_info" and "users_authorities" instead of "user_info" and "user_authorities" respectively for UserInfo entity This commit refactors TalentService, Authority, and UserInfo models to use Skill instead of Skills and updates table names for UserInfo entity to use plural form for consistency and clarity. --- .../talent/service/TalentService.java | 10 +++--- .../user/model/entity/Authority.java | 22 +++++++++---- .../user/model/entity/UserInfo.java | 32 +++++++++++++------ 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/provedcode/talent/service/TalentService.java b/src/main/java/com/provedcode/talent/service/TalentService.java index 50f63ac..9d08612 100644 --- a/src/main/java/com/provedcode/talent/service/TalentService.java +++ b/src/main/java/com/provedcode/talent/service/TalentService.java @@ -162,18 +162,18 @@ public void addSkillOnTalent(long id, SkillIdDTO skillIdDTO, Authentication auth validateTalentForCompliance.userVerification(talent, userInfo, id); Talent talentObject = talent.get(); - Set skillsFromRepo = skillIdDTO.id().stream() + Set skillsFromRepo = skillIdDTO.id().stream() .map(element -> skillsRepository.findById(element) .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "Skill with id = %d not found".formatted(element)))) .collect(Collectors.toSet()); - Set skillsFromProofs = talentObject.getTalentProofs().stream() + Set skillsFromProofs = talentObject.getTalentProofs().stream() .flatMap(talentProof -> talentProof.getProofSkills() .stream().map(skill -> skill.getSkill())).collect(Collectors.toSet()); - for (Skills skill : talentObject.getSkills()) { - for (Skills skillForAdd : skillsFromRepo) { + for (Skill skill : talentObject.getSkills()) { + for (Skill skillForAdd : skillsFromRepo) { if (skill.equals(skillForAdd)) { throw new ResponseStatusException(BAD_REQUEST, "Skill with id = %d found in talent's skills".formatted(skill.getId())); @@ -195,7 +195,7 @@ public void addSkillOnTalent(long id, SkillIdDTO skillIdDTO, Authentication auth public void deleteSkillFromTalent(long talentId, long skillId, Authentication authentication) { Optional talent = talentRepository.findById(talentId); Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); - Skills skill = skillsRepository.findById(skillId) + Skill skill = skillsRepository.findById(skillId) .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "Skill with id = %d not found".formatted(skillId))); validateTalentForCompliance.userVerification(talent, userInfo, talentId); diff --git a/src/main/java/com/provedcode/user/model/entity/Authority.java b/src/main/java/com/provedcode/user/model/entity/Authority.java index 03b7bac..7473afd 100644 --- a/src/main/java/com/provedcode/user/model/entity/Authority.java +++ b/src/main/java/com/provedcode/user/model/entity/Authority.java @@ -1,23 +1,33 @@ package com.provedcode.user.model.entity; +import java.util.LinkedHashSet; +import java.util.Set; + import com.provedcode.user.model.Role; -import jakarta.persistence.*; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.Table; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; -import java.util.LinkedHashSet; -import java.util.Set; - @Getter @Setter @Entity -@Table(name = "authority") +@Table(name = "authorities") public class Authority { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", nullable = false) + @Column(name = "id", nullable = false, insertable = false, updatable = false) private Long id; @Enumerated(EnumType.STRING) @NotEmpty 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 852d0b8..19dc0da 100644 --- a/src/main/java/com/provedcode/user/model/entity/UserInfo.java +++ b/src/main/java/com/provedcode/user/model/entity/UserInfo.java @@ -1,14 +1,30 @@ package com.provedcode.user.model.entity; +import java.util.LinkedHashSet; +import java.util.Set; + import com.provedcode.sponsor.model.entity.Sponsor; import com.provedcode.talent.model.entity.Talent; -import jakarta.persistence.*; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; -import lombok.*; - -import java.util.LinkedHashSet; -import java.util.Set; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; @Builder @AllArgsConstructor @@ -16,7 +32,7 @@ @Getter @Setter @Entity -@Table(name = "user_info") +@Table(name = "users_info") public class UserInfo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -37,8 +53,6 @@ public class UserInfo { @Column(name = "password") private String password; @ManyToMany(fetch = FetchType.EAGER) - @JoinTable(name = "user_authorities", - joinColumns = @JoinColumn(name = "user_id"), - inverseJoinColumns = @JoinColumn(name = "authority_id")) + @JoinTable(name = "users_authorities", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "authority_id")) private Set authorities = new LinkedHashSet<>(); } \ No newline at end of file From 1d43c33cdc9436b5ff17bf98771f1263125a4692 Mon Sep 17 00:00:00 2001 From: Ren Date: Sat, 20 May 2023 11:51:02 +0300 Subject: [PATCH 54/59] Update project version to 0.5.0-SNAPSHOT in pom.xml file --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 54591a1..85cb069 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.provedcode demo - 0.1.1-SNAPSHOT + 0.5.0-SNAPSHOT ProvedCode Demo project for Spring Boot From 329f0866cc50f06706f6aa5715ddaba4e213e45f Mon Sep 17 00:00:00 2001 From: Ren Date: Sat, 20 May 2023 12:27:28 +0300 Subject: [PATCH 55/59] Refactor data retrieval and management in KudosService This commit has removed unused imports and introduced cleaner code for retrieving kudos from a sponsor. Skill's kudos retrieval was optimized by replacing a fetching architecture using flatMap() for the stream with collecting stream results into a hash table. Finally, the `KudosService` class has been refactored to accommodate these changes. In SkillsRepository, a minor fix has been made to ensure that the 'Skill' table is queried correctly. In 'dataSkill-V5.sql', the IDs in the insert statements have been removed, and the queries have been changed accordingly to make the statements more readable. Annotations have been added for easier reading. --- .../kudos/service/KudosService.java | 31 ++++++++++--------- .../talent/repo/SkillsRepository.java | 2 +- .../changelog/changeset/V5/dataSkill-V5.sql | 16 +++++----- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/provedcode/kudos/service/KudosService.java b/src/main/java/com/provedcode/kudos/service/KudosService.java index e880c54..051b126 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -1,5 +1,18 @@ package com.provedcode.kudos.service; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.FORBIDDEN; +import static org.springframework.http.HttpStatus.NOT_FOUND; + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.server.ResponseStatusException; + import com.provedcode.kudos.model.entity.Kudos; import com.provedcode.kudos.model.request.SetAmountKudos; import com.provedcode.kudos.model.response.KudosAmount; @@ -17,17 +30,8 @@ import com.provedcode.talent.repo.TalentRepository; import com.provedcode.user.model.entity.UserInfo; import com.provedcode.user.repo.UserInfoRepository; -import lombok.AllArgsConstructor; -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.HashMap; -import java.util.Map; -import java.util.stream.Collectors; -import static org.springframework.http.HttpStatus.*; +import lombok.AllArgsConstructor; @Service @AllArgsConstructor @@ -71,7 +75,7 @@ public KudosAmountWithSponsor getProofKudos(long proofId, Authentication authent "Proof with id = %s not found".formatted(proofId))); Long countOfAllKudos = talentProof.getProofSkills() - .stream().flatMap(proofSkills -> proofSkills.getKudoses() + .stream().flatMap(proofSkills -> proofSkills.getKudos() .stream().map(Kudos::getAmount)) .reduce(0L, (prev, next) -> prev + next); @@ -81,7 +85,7 @@ public KudosAmountWithSponsor getProofKudos(long proofId, Authentication authent String skill = proofSkill.getSkill().getSkill(); Map kudosFromSponsor = talentProof.getProofSkills().stream() .filter(proofSkills -> proofSkills.getSkill().getSkill().equals(skill)) - .flatMap(proofSkills -> proofSkills.getKudoses().stream()) + .flatMap(proofSkills -> proofSkills.getKudos().stream()) .collect(Collectors.toMap( Kudos::getAmount, proof -> proof.getSponsor() != null @@ -137,8 +141,7 @@ public void addKudosToProof(long proofId, SetAmountKudos amountOfKudoses, Authen .skill(proofSkill) .amount(addKudoses) .build(); - proofSkill.getKudoses().add(kudosRepository.save(kudos)); + proofSkill.getKudos().add(kudosRepository.save(kudos)); }); - } } diff --git a/src/main/java/com/provedcode/talent/repo/SkillsRepository.java b/src/main/java/com/provedcode/talent/repo/SkillsRepository.java index 08b0fc8..a879f10 100644 --- a/src/main/java/com/provedcode/talent/repo/SkillsRepository.java +++ b/src/main/java/com/provedcode/talent/repo/SkillsRepository.java @@ -7,6 +7,6 @@ import java.util.List; public interface SkillsRepository extends JpaRepository { - @Query("select s from Skills s where upper(s.skill) like upper(concat('%', ?1, '%'))") + @Query("select s from Skill s where upper(s.skill) like upper(concat('%', ?1, '%'))") List findBySkillContainsIgnoreCase(String skill); } \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql index 8a82c74..8de1cc7 100644 --- a/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/dataSkill-V5.sql @@ -1,13 +1,13 @@ --liquibase formatted sql --changeset dennis:5 -insert into proofs_skills (id, skill_id, proof_id) -values (1, 1, 1); -insert into proofs_skills (id, skill_id, proof_id) -values (2, 2, 1); -insert into proofs_skills (id, skill_id, proof_id) -values (3, 2, 2); -insert into proofs_skills (id, skill_id, proof_id) -values (4, 3, 3) +insert into proofs_skills (skill_id, proof_id) +values (1, 1); +insert into proofs_skills (skill_id, proof_id) +values (2, 1); +insert into proofs_skills (skill_id, proof_id) +values (2, 2); +insert into proofs_skills (skill_id, proof_id) +values (3, 3); insert into talents_skills(talent_id, skill_id) values (1, 1); From 1ae5e6b926784395b68912498ce85c499e8fb173 Mon Sep 17 00:00:00 2001 From: Denis973 <46610112+Denis973@users.noreply.github.com> Date: Sun, 21 May 2023 12:34:18 +0300 Subject: [PATCH 56/59] S5 us3 (#146) * preparation for US3 * getAllKudosOnTalent * not yet getSkillWithLargestNumberOfKudos * finish getProofWithLargestNumberOfKudos * finish getSkillWithLargestNumberOfKudos * refactor addKudosToProof: you can give kudos even if you gave not a multiple of the amount --- .../kudos/service/KudosService.java | 14 ++-- .../talent/controller/TalentController.java | 7 ++ .../controller/TalentProofController.java | 1 - .../talent/model/dto/StatisticsDTO.java | 13 ++++ .../talent/service/TalentService.java | 77 ++++++++++++++++++- 5 files changed, 100 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/provedcode/talent/model/dto/StatisticsDTO.java diff --git a/src/main/java/com/provedcode/kudos/service/KudosService.java b/src/main/java/com/provedcode/kudos/service/KudosService.java index 051b126..595396e 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -89,10 +89,10 @@ public KudosAmountWithSponsor getProofKudos(long proofId, Authentication authent .collect(Collectors.toMap( Kudos::getAmount, proof -> proof.getSponsor() != null - ? sponsorMapper.toDto(proof.getSponsor()) - : SponsorDTO.builder().build(), - (prev, next) -> next, - HashMap::new)); + ? sponsorMapper.toDto(proof.getSponsor()) + : SponsorDTO.builder().build(), + (prev, next) -> next, + HashMap::new)); skillsMap.put(skill, kudosFromSponsor); }); return KudosAmountWithSponsor.builder() @@ -127,9 +127,9 @@ public void addKudosToProof(long proofId, SetAmountKudos amountOfKudoses, Authen if (sponsor.getAmountKudos() < obtainedAmount) { throw new ResponseStatusException(FORBIDDEN, "The sponsor cannot give more kudos than he has"); } - if (obtainedAmount % talentProof.getProofSkills().size() != 0) { - throw new ResponseStatusException(BAD_REQUEST, - "Sponsor cannot add amount of kudos that multiple of amount of skills"); + Long modula = obtainedAmount % talentProof.getProofSkills().size(); + if (modula != 0) { + obtainedAmount -= modula; } sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); diff --git a/src/main/java/com/provedcode/talent/controller/TalentController.java b/src/main/java/com/provedcode/talent/controller/TalentController.java index ecff1f5..3c0b319 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentController.java @@ -4,6 +4,7 @@ import com.provedcode.talent.model.dto.FullTalentDTO; import com.provedcode.talent.model.dto.ShortTalentDTO; import com.provedcode.talent.model.dto.SkillIdDTO; +import com.provedcode.talent.model.dto.StatisticsDTO; import com.provedcode.talent.model.request.EditTalent; import com.provedcode.talent.service.TalentService; import com.provedcode.user.model.dto.SessionInfoDTO; @@ -90,4 +91,10 @@ Page getFilteredBySkillsTalents(@RequestParam(value = "page", de return talentService.getFilteredBySkillsTalentsPage(page, size, filterBy).map(talentMapper::talentToShortTalentDTO); } + @PreAuthorize("hasRole('TALENT')") + @GetMapping("v5/talents/{talent-id}/statistics") + StatisticsDTO getStatisticsForTalent(@PathVariable("talent-id") long talentId, + Authentication authentication) { + return talentService.getStatisticsForTalent(talentId, authentication); + } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/controller/TalentProofController.java b/src/main/java/com/provedcode/talent/controller/TalentProofController.java index ff89e09..775edf6 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentProofController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentProofController.java @@ -3,7 +3,6 @@ import com.provedcode.talent.mapper.TalentProofMapper; import com.provedcode.talent.model.dto.FullProofDTO; import com.provedcode.talent.model.dto.ProofDTO; -import com.provedcode.talent.model.dto.StatusDTO; import com.provedcode.talent.model.request.AddProof; import com.provedcode.talent.service.TalentProofService; import com.provedcode.util.annotations.doc.controller.proof.*; diff --git a/src/main/java/com/provedcode/talent/model/dto/StatisticsDTO.java b/src/main/java/com/provedcode/talent/model/dto/StatisticsDTO.java new file mode 100644 index 0000000..1914887 --- /dev/null +++ b/src/main/java/com/provedcode/talent/model/dto/StatisticsDTO.java @@ -0,0 +1,13 @@ +package com.provedcode.talent.model.dto; + +import lombok.Builder; + +import java.util.Map; + +@Builder +public record StatisticsDTO( + Long allKudosOnTalent, + Map skillWithLargestNumberOfKudos, + Map proofWithLargestNumberOfKudos +) { +} diff --git a/src/main/java/com/provedcode/talent/service/TalentService.java b/src/main/java/com/provedcode/talent/service/TalentService.java index 775b78a..d89b82d 100644 --- a/src/main/java/com/provedcode/talent/service/TalentService.java +++ b/src/main/java/com/provedcode/talent/service/TalentService.java @@ -1,7 +1,12 @@ package com.provedcode.talent.service; import com.provedcode.config.PageProperties; +import com.provedcode.kudos.model.entity.Kudos; +import com.provedcode.talent.mapper.TalentProofMapper; +import com.provedcode.talent.model.dto.ProofDTO; +import com.provedcode.talent.model.dto.SkillDTO; import com.provedcode.talent.model.dto.SkillIdDTO; +import com.provedcode.talent.model.dto.StatisticsDTO; import com.provedcode.talent.model.entity.*; import com.provedcode.talent.model.request.EditTalent; import com.provedcode.talent.repo.SkillsRepository; @@ -24,10 +29,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.server.ResponseStatusException; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import static org.springframework.http.HttpStatus.*; @@ -44,6 +46,7 @@ public class TalentService { PageProperties pageProperties; ValidateTalentForCompliance validateTalentForCompliance; SkillsRepository skillsRepository; + TalentProofMapper talentProofMapper; @Transactional(readOnly = true) public Page getTalentsPage(Integer page, Integer size) { @@ -214,4 +217,70 @@ public Page getFilteredBySkillsTalentsPage(@PositiveOrZero Integer page, talentRepository.findBySkills_SkillsInIgnoreCase(PageRequest.of(page, size), Arrays.stream(filterBy).map(String::toUpperCase).toList()) : talentRepository.findAll(PageRequest.of(page, size)); } + + public StatisticsDTO getStatisticsForTalent(long talentId, Authentication authentication) { + Optional talent = talentRepository.findById(talentId); + Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); + validateTalentForCompliance.userVerification(talent, userInfo, talentId); + Talent talentObject = talent.get(); + return StatisticsDTO.builder() + .allKudosOnTalent(getAllKudosOnTalent(talentObject)) + .skillWithLargestNumberOfKudos(getSkillWithLargestNumberOfKudos(talentObject)) + .proofWithLargestNumberOfKudos(getProofWithLargestNumberOfKudos(talentObject)) + .build(); + } + + public Long getAllKudosOnTalent(Talent talent) { + return talent.getTalentProofs() + .stream() + .flatMap(x -> x.getProofSkills().stream()) + .flatMap(y -> y.getKudos().stream()) + .mapToLong(q -> q.getAmount()) + .sum(); + } + + public Map getSkillWithLargestNumberOfKudos(Talent talent) { + Map numberKudosOnSkill = new HashMap<>(); + for (TalentProof talentProof : talent.getTalentProofs()) { + for (ProofSkill proofSkill : talentProof.getProofSkills()) { + for (Kudos kudos : proofSkill.getKudos()) { + if (numberKudosOnSkill.containsKey(proofSkill.getSkill().getSkill())) { + Long amountKudosOnSkill = numberKudosOnSkill.get(proofSkill.getSkill().getSkill()); + numberKudosOnSkill.remove(proofSkill.getSkill().getSkill()); + numberKudosOnSkill.put(proofSkill.getSkill().getSkill(), amountKudosOnSkill + kudos.getAmount()); + } else { + numberKudosOnSkill.put(proofSkill.getSkill().getSkill(), kudos.getAmount()); + } + } + } + } + Long max = Collections.max(numberKudosOnSkill.values()); + Map result = new HashMap<>(); + for (Map.Entry entry : numberKudosOnSkill.entrySet()) { + if (entry.getValue().equals(max)) { + result.put(entry.getKey(), entry.getValue()); + } + } + + return result; + } + + public Map getProofWithLargestNumberOfKudos(Talent talent) { + Map result = new HashMap<>(); + Long maxForResult = 0L; + for (TalentProof talentProof : talent.getTalentProofs()) { + Long amountKudosOnSkills = 0L; + for (ProofSkill proofSkill : talentProof.getProofSkills()) { + for (Kudos kudos : proofSkill.getKudos()) { + amountKudosOnSkills += kudos.getAmount(); + } + } + if (amountKudosOnSkills > maxForResult) { + maxForResult = amountKudosOnSkills; + result.clear(); + result.put(talentProofMapper.toProofDTO(talentProof), amountKudosOnSkills); + } + } + return result; + } } \ No newline at end of file From bd843e8e84c37ec183070d1af954d9c7b490d76b Mon Sep 17 00:00:00 2001 From: Ren <75202059+LordRenDS@users.noreply.github.com> Date: Tue, 23 May 2023 13:54:21 +0300 Subject: [PATCH 57/59] S5US1T3-4 (#147) * feat: Add endpoints for adding and getting kudos to skills This commit adds two new endpoints for adding kudos to a skill and getting the amount of kudos for a skill under a given proof. These endpoints require sponsor authentication and take a valid SetAmountKudos object. * Add access permission to PROOF API endpoint and modify H2 URL - Permit access to PROOF API endpoint by updating SecurityConfig.java. - Change H2 URL format in application-dev.properties. * Add KudosRepository and KudosService changes - Added a new interface method to KudosRepository that returns Kudos list by ProofSkill - Added getKudosForSponsor and getProofKudos methods to KudosService that returns kudos amount for sponsor and kudos amount with sponsor respectively * add @Transactional(readOnly = true) to getSkillKudos * change the logic: * skill-id is an id from the skills table, not proofs_skills * Refactor wrong datasource configuration properties for H2 database * Update skill column size to 50 chars in talents_skills table The skill column in the talents_skills table has been increased from 30 chars to 50 chars to accommodate longer skill names. This update ensures compatibility with future use cases that may require longer skill names. --- .../com/provedcode/config/SecurityConfig.java | 1 + .../kudos/controller/KudosController.java | 33 ++- .../kudos/repository/KudosRepository.java | 11 +- .../kudos/service/KudosService.java | 254 +++++++++++------- src/main/resources/application-dev.properties | 6 +- .../changeset/V5/talent-schema-V5.sql | 2 +- 6 files changed, 187 insertions(+), 120 deletions(-) diff --git a/src/main/java/com/provedcode/config/SecurityConfig.java b/src/main/java/com/provedcode/config/SecurityConfig.java index dff7a62..4459d42 100644 --- a/src/main/java/com/provedcode/config/SecurityConfig.java +++ b/src/main/java/com/provedcode/config/SecurityConfig.java @@ -54,6 +54,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .requestMatchers(antMatcher("/api/*/sponsors/**")).permitAll() .requestMatchers(antMatcher("/api/*/login")).permitAll() .requestMatchers(antMatcher("/api/*/skills")).permitAll() + .requestMatchers(antMatcher("/api/*/proofs/**")).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/kudos/controller/KudosController.java b/src/main/java/com/provedcode/kudos/controller/KudosController.java index 878474b..f065d39 100644 --- a/src/main/java/com/provedcode/kudos/controller/KudosController.java +++ b/src/main/java/com/provedcode/kudos/controller/KudosController.java @@ -1,5 +1,15 @@ package com.provedcode.kudos.controller; +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.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + import com.provedcode.kudos.model.request.SetAmountKudos; import com.provedcode.kudos.model.response.KudosAmount; import com.provedcode.kudos.model.response.KudosAmountWithSponsor; @@ -7,14 +17,9 @@ 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 @@ -41,8 +46,20 @@ KudosAmountWithSponsor getProofKudos(@PathVariable("proof-id") long proofId, Aut @PreAuthorize("hasRole('SPONSOR')") @PostMapping("/proofs/{proof-id}/kudos") void addKudosToProof(@PathVariable("proof-id") long proofId, - @RequestBody @Valid SetAmountKudos amount, - Authentication authentication) { + @RequestBody @Valid SetAmountKudos amount, + Authentication authentication) { kudosService.addKudosToProof(proofId, amount, authentication); } + + @PreAuthorize("hasRole('SPONSOR')") + @PostMapping("/proofs/{proof-id}/skills/{skill-id}/kudos") + void addKudosToSkill(@PathVariable("proof-id") long proofId, @PathVariable("skill-id") long skillId, + Authentication authentication, @RequestBody @Valid SetAmountKudos amount) { + kudosService.addKudosToSkill(proofId, skillId, amount, authentication); + } + + @GetMapping("/proofs/{proof-id}/skills/{skill-id}/kudos") + KudosAmount getKudosForSkill(@PathVariable("proof-id") long proofId, @PathVariable("skill-id") long skillId) { + return kudosService.getSkillKudos(proofId, skillId); + } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/kudos/repository/KudosRepository.java b/src/main/java/com/provedcode/kudos/repository/KudosRepository.java index 8f489c9..0408d75 100644 --- a/src/main/java/com/provedcode/kudos/repository/KudosRepository.java +++ b/src/main/java/com/provedcode/kudos/repository/KudosRepository.java @@ -1,10 +1,13 @@ package com.provedcode.kudos.repository; -import com.provedcode.kudos.model.entity.Kudos; +import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; +import com.provedcode.kudos.model.entity.Kudos; +import com.provedcode.talent.model.entity.ProofSkill; + + public interface KudosRepository extends JpaRepository { -// long countByProofId(Long id); -// -// boolean existsBySponsorIdAndProofId(Long sponsorId, Long proofId); + List findBySkill(ProofSkill skill); } \ 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 595396e..39ae8b5 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -1,10 +1,10 @@ package com.provedcode.kudos.service; -import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.FORBIDDEN; import static org.springframework.http.HttpStatus.NOT_FOUND; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -23,6 +23,7 @@ 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.ProofSkill; import com.provedcode.talent.model.entity.Talent; import com.provedcode.talent.model.entity.TalentProof; import com.provedcode.talent.repo.ProofSkillRepository; @@ -37,111 +38,156 @@ @AllArgsConstructor @Transactional public class KudosService { - KudosRepository kudosRepository; - TalentProofRepository talentProofRepository; - UserInfoRepository userInfoRepository; - SponsorRepository sponsorRepository; - TalentRepository talentRepository; - ProofSkillRepository proofSkillRepository; - SponsorMapper sponsorMapper; - - @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 kudosRepository; + TalentProofRepository talentProofRepository; + UserInfoRepository userInfoRepository; + SponsorRepository sponsorRepository; + TalentRepository talentRepository; + ProofSkillRepository proofSkillRepository; + SponsorMapper sponsorMapper; + + @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"); + } + Sponsor sponsor = sponsorRepository.findById(sponsorId).orElseThrow( + () -> new ResponseStatusException(NOT_FOUND, + String.format("Sponsor with id = %d not found", sponsorId))); + return new KudosAmount(sponsor.getAmountKudos()); } - Sponsor sponsor = sponsorRepository.findById(sponsorId).orElseThrow( - () -> new ResponseStatusException(NOT_FOUND, - String.format("Sponsor with id = %d not found", sponsorId))); - return new KudosAmount(sponsor.getAmountKudos()); - } - - @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.getTalent().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.getProofSkills() - .stream().flatMap(proofSkills -> proofSkills.getKudos() - .stream().map(Kudos::getAmount)) - .reduce(0L, (prev, next) -> prev + next); - - if (talent.getId().equals(talentProof.getTalent().getId())) { - Map> skillsMap = new HashMap<>(); - talentProof.getProofSkills().forEach(proofSkill -> { // I dnk wtf is this piece of shit, but it works. - String skill = proofSkill.getSkill().getSkill(); - Map kudosFromSponsor = talentProof.getProofSkills().stream() - .filter(proofSkills -> proofSkills.getSkill().getSkill().equals(skill)) - .flatMap(proofSkills -> proofSkills.getKudos().stream()) - .collect(Collectors.toMap( - Kudos::getAmount, - proof -> proof.getSponsor() != null - ? sponsorMapper.toDto(proof.getSponsor()) - : SponsorDTO.builder().build(), - (prev, next) -> next, - HashMap::new)); - skillsMap.put(skill, kudosFromSponsor); - }); - return KudosAmountWithSponsor.builder() - .allKudosOnProof(countOfAllKudos) - .kudosFromSponsor(skillsMap) - .build(); - } else { - return KudosAmountWithSponsor.builder() - .allKudosOnProof(countOfAllKudos) - .kudosFromSponsor(null).build(); + + @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.getTalent().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.getProofSkills() + .stream().flatMap(proofSkills -> proofSkills.getKudos() + .stream().map(Kudos::getAmount)) + .reduce(0L, (prev, next) -> prev + next); + + if (talent.getId().equals(talentProof.getTalent().getId())) { + Map> skillsMap = new HashMap<>(); + talentProof.getProofSkills().forEach(proofSkill -> { // I dnk wtf is this piece of shit, but it + // works. + String skill = proofSkill.getSkill().getSkill(); + Map kudosFromSponsor = talentProof.getProofSkills().stream() + .filter(proofSkills -> proofSkills.getSkill().getSkill().equals(skill)) + .flatMap(proofSkills -> proofSkills.getKudos().stream()) + .collect(Collectors.toMap( + Kudos::getAmount, + proof -> proof.getSponsor() != null + ? sponsorMapper.toDto( + proof.getSponsor()) + : SponsorDTO.builder().build(), + (prev, next) -> next, + HashMap::new)); + skillsMap.put(skill, kudosFromSponsor); + }); + return KudosAmountWithSponsor.builder() + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(skillsMap) + .build(); + } else { + return KudosAmountWithSponsor.builder() + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(null).build(); + } } - } - - - public void addKudosToProof(long proofId, SetAmountKudos amountOfKudoses, 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 (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) - throw new ResponseStatusException(FORBIDDEN, "Proof that was kudosed does not have the PUBLISHED status"); - long obtainedAmount = amountOfKudoses.amount(); - - if (sponsor.getAmountKudos() < obtainedAmount) { - throw new ResponseStatusException(FORBIDDEN, "The sponsor cannot give more kudos than he has"); + + public void addKudosToProof(long proofId, SetAmountKudos amountOfKudoses, 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 (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) + throw new ResponseStatusException(FORBIDDEN, + "Proof that was kudosed does not have the PUBLISHED status"); + long obtainedAmount = amountOfKudoses.amount(); + + if (sponsor.getAmountKudos() < obtainedAmount) { + throw new ResponseStatusException(FORBIDDEN, "The sponsor cannot give more kudos than he has"); + } + Long modula = obtainedAmount % talentProof.getProofSkills().size(); + if (modula != 0) { + obtainedAmount -= modula; + } + sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); + + Long addKudoses = obtainedAmount / talentProof.getProofSkills().size(); + + talentProof.getProofSkills().forEach(proofSkill -> { + Kudos kudos = Kudos.builder() + .sponsor(sponsor) + .skill(proofSkill) + .amount(addKudoses) + .build(); + proofSkill.getKudos().add(kudosRepository.save(kudos)); + }); } - Long modula = obtainedAmount % talentProof.getProofSkills().size(); - if (modula != 0) { - obtainedAmount -= modula; + + public void addKudosToSkill(long proofId, long skillId, SetAmountKudos amountOfKudos, + 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 (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) + throw new ResponseStatusException(FORBIDDEN, + "Skill on proof that was kudosed does not have the PUBLISHED status"); + long obtainedAmount = amountOfKudos.amount(); + if (sponsor.getAmountKudos() < obtainedAmount) { + throw new ResponseStatusException(FORBIDDEN, "The sponsor cannot give more kudos than he has"); + } + sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); + ProofSkill proofSkill = talentProof.getProofSkills().stream() + .filter(s -> s.getSkill().getId().equals(skillId)) + .findFirst().orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Skill with id = %d not found".formatted(skillId))); + kudosRepository.save(Kudos.builder().amount(obtainedAmount).sponsor(sponsor).skill(proofSkill).build()); + } + + @Transactional(readOnly = true) + public KudosAmount getSkillKudos(long proofId, long skillId) { + TalentProof talentProof = talentProofRepository.findById(proofId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Proof with id = %d not found".formatted(proofId))); + if (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) + throw new ResponseStatusException(FORBIDDEN, + "The skill from the proof that was referred to does not have a PUBLISHED status"); + ProofSkill proofSkill = talentProof.getProofSkills().stream() + .filter(s -> s.getSkill().getId().equals(skillId)) + .findFirst().orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Skill with id = %d not found".formatted(skillId))); + List kudos = kudosRepository.findBySkill(proofSkill); + long amountOfKudos = kudos.stream().map(Kudos::getAmount).reduce(0L, Long::sum); + return new KudosAmount(amountOfKudos); } - sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); - - Long addKudoses = obtainedAmount / talentProof.getProofSkills().size(); - - talentProof.getProofSkills().forEach(proofSkill -> { - Kudos kudos = Kudos.builder() - .sponsor(sponsor) - .skill(proofSkill) - .amount(addKudoses) - .build(); - proofSkill.getKudos().add(kudosRepository.save(kudos)); - }); - } } diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 60dd6cf..21ea24c 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -1,6 +1,6 @@ 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 -#logging.level.web=DEBUG -#logging.level.sql=DEBUG -spring.jpa.show-sql=true \ No newline at end of file +# logging.level.web=DEBUG +# logging.level.sql=DEBUG +# spring.jpa.show-sql=true diff --git a/src/main/resources/db/changelog/changeset/V5/talent-schema-V5.sql b/src/main/resources/db/changelog/changeset/V5/talent-schema-V5.sql index 5871498..2eca374 100644 --- a/src/main/resources/db/changelog/changeset/V5/talent-schema-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/talent-schema-V5.sql @@ -47,7 +47,7 @@ CREATE TABLE proofs ( ); CREATE TABLE skills ( id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - skill VARCHAR(30), + skill VARCHAR(50), PRIMARY KEY (id) ); CREATE TABLE talents_skills ( From 53113b6fc6a30bcc0ce93ad9ce8cd9abf8ce4f86 Mon Sep 17 00:00:00 2001 From: Mykhailo Ordyntsev <102993813+Maslyna@users.noreply.github.com> Date: Wed, 24 May 2023 12:27:58 +0200 Subject: [PATCH 58/59] S5-email (#149) * refactor userInfo: add uuid and isLocked, add DeletedUser * add deleted-user-schema.sql and refactor user-info-schema-V5.sql * refactor register in AuthenticationServiceImpl * refactor application.properties * add EmailDefaultProps * add GlobalControllerAdvice * add EmailConfig * add EmailService and dependency * add ServerInfoConfig * refactor deleteTalentById, add email * refactor deleteSponsor, add email account recovery * add DeleteUsersScheduler * update properties * AWS minore update * update * sponsor service update * Requested update: sponsor can see amount of kudos on user account User restore account now available! * MERGE UPDATE * MERGE UPDATE --------- Co-authored-by: Denis Boyko --- pom.xml | 4 + .../aws/controller/AWSS3BucketController.java | 7 +- .../provedcode/aws/service/FileService.java | 2 +- .../com/provedcode/aws/service/S3Service.java | 8 +- .../com/provedcode/config/EmailConfig.java | 15 + .../provedcode/config/EmailDefaultProps.java | 19 ++ .../com/provedcode/config/SecurityConfig.java | 2 + .../provedcode/config/ServerInfoConfig.java | 29 ++ .../handlers/GlobalControllerAdvice.java | 33 ++ .../kudos/controller/KudosController.java | 2 +- .../kudos/service/KudosService.java | 321 ++++++++++-------- .../sponsor/controller/SponsorController.java | 16 +- .../sponsor/service/SponsorService.java | 53 ++- .../talent/controller/TalentController.java | 7 + .../talent/service/TalentService.java | 39 ++- .../controller/AuthenticationController.java | 6 + .../user/model/entity/DeletedUser.java | 25 ++ .../user/model/entity/UserInfo.java | 3 + .../user/repo/DeletedUserRepository.java | 15 + .../user/service/AuthenticationService.java | 4 + .../impl/AuthenticationServiceImpl.java | 15 +- .../user/service/impl/EmailService.java | 25 ++ .../user/util/UsersSchedulerService.java | 64 ++++ src/main/resources/application.properties | 12 +- .../db/changelog/changeset/V5/data-V5.sql | 28 +- .../changeset/V5/deleted-user-schema.sql | 14 + .../db/changelog/changeset/V5/skills-data.sql | 223 ++++++++++++ .../changeset/V5/user-info-schema-V5.sql | 1 + .../db/changelog/db.changelog-master.yaml | 5 + 29 files changed, 802 insertions(+), 195 deletions(-) create mode 100644 src/main/java/com/provedcode/config/EmailConfig.java create mode 100644 src/main/java/com/provedcode/config/EmailDefaultProps.java create mode 100644 src/main/java/com/provedcode/config/ServerInfoConfig.java create mode 100644 src/main/java/com/provedcode/handlers/GlobalControllerAdvice.java create mode 100644 src/main/java/com/provedcode/user/model/entity/DeletedUser.java create mode 100644 src/main/java/com/provedcode/user/repo/DeletedUserRepository.java create mode 100644 src/main/java/com/provedcode/user/service/impl/EmailService.java create mode 100644 src/main/java/com/provedcode/user/util/UsersSchedulerService.java create mode 100644 src/main/resources/db/changelog/changeset/V5/deleted-user-schema.sql create mode 100644 src/main/resources/db/changelog/changeset/V5/skills-data.sql diff --git a/pom.xml b/pom.xml index 85cb069..409f5d0 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,10 @@ 17 + + org.springframework.boot + spring-boot-starter-mail + org.springdoc diff --git a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java index 926e991..54bd25f 100644 --- a/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java +++ b/src/main/java/com/provedcode/aws/controller/AWSS3BucketController.java @@ -21,10 +21,11 @@ public class AWSS3BucketController { @PostSetNewUserImageApiDoc @PreAuthorize("hasRole('TALENT')") - @PostMapping("/image/upload") + @PostMapping("/talents/{talent-id}/image/upload") public void setNewUserImage(@RequestParam("file") MultipartFile file, - Authentication authentication) { - fileService.setNewUserImage(file, authentication); + @PathVariable("talent-id") Long talentId, + Authentication authentication) { + fileService.setNewUserImage(file, talentId, authentication); } @GetAllAWSBucketFilesDevApiDoc diff --git a/src/main/java/com/provedcode/aws/service/FileService.java b/src/main/java/com/provedcode/aws/service/FileService.java index 1c1d9e6..bb771c2 100644 --- a/src/main/java/com/provedcode/aws/service/FileService.java +++ b/src/main/java/com/provedcode/aws/service/FileService.java @@ -16,7 +16,7 @@ public interface FileService { List listAllFiles(); - void setNewUserImage(MultipartFile file, Authentication authentication); + void setNewUserImage(MultipartFile file, Long talentId, 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 a7a4dc9..5c753ef 100644 --- a/src/main/java/com/provedcode/aws/service/S3Service.java +++ b/src/main/java/com/provedcode/aws/service/S3Service.java @@ -6,6 +6,7 @@ import com.amazonaws.services.s3.model.*; import com.amazonaws.util.IOUtils; import com.provedcode.config.AWSProperties; +import com.provedcode.talent.model.entity.Talent; import com.provedcode.talent.repo.TalentRepository; import com.provedcode.user.model.entity.UserInfo; import com.provedcode.user.repo.UserInfoRepository; @@ -75,7 +76,7 @@ public List listAllFiles() { } @Override - public void setNewUserImage(MultipartFile file, Authentication authentication) { + public void setNewUserImage(MultipartFile file, Long talentId, Authentication authentication) { if (file.isEmpty()) { throw new ResponseStatusException(BAD_REQUEST, "file must be not empty, actual file-size: %s".formatted(file.getSize())); } @@ -84,6 +85,11 @@ public void setNewUserImage(MultipartFile file, Authentication authentication) { } UserInfo user = userInfoRepository.findByLogin(authentication.getName()) .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "user with login = {%s} not found".formatted(authentication.getName()))); + Talent talent = talentRepository.findById(talentId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "talent with id = {%s} not found".formatted(talentId))); + if (!user.getTalent().equals(talent)) { + throw new ResponseStatusException(FORBIDDEN, "You cannot change another talent"); + } try { String fileType = getFileType(file); diff --git a/src/main/java/com/provedcode/config/EmailConfig.java b/src/main/java/com/provedcode/config/EmailConfig.java new file mode 100644 index 0000000..d1a0073 --- /dev/null +++ b/src/main/java/com/provedcode/config/EmailConfig.java @@ -0,0 +1,15 @@ +package com.provedcode.config; + +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +@Configuration +@AllArgsConstructor +public class EmailConfig { + private Environment env; + + public String getDefaultEmail() { + return env.getProperty("EMAIL_USER"); + } +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/config/EmailDefaultProps.java b/src/main/java/com/provedcode/config/EmailDefaultProps.java new file mode 100644 index 0000000..f6adf63 --- /dev/null +++ b/src/main/java/com/provedcode/config/EmailDefaultProps.java @@ -0,0 +1,19 @@ +package com.provedcode.config; + +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +@Validated +@ConfigurationProperties(prefix = "default-email") +@Slf4j +public record EmailDefaultProps( + String userDeleted, + String userDeletedSubject +) { + @PostConstruct + void logging() { + log.info("email-default-props = {}", this); + } +} diff --git a/src/main/java/com/provedcode/config/SecurityConfig.java b/src/main/java/com/provedcode/config/SecurityConfig.java index 4459d42..8bfb464 100644 --- a/src/main/java/com/provedcode/config/SecurityConfig.java +++ b/src/main/java/com/provedcode/config/SecurityConfig.java @@ -9,6 +9,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; @@ -59,6 +60,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .requestMatchers(antMatcher("/v3/api-docs/**")).permitAll() // for openAPI .requestMatchers(antMatcher("/swagger-ui/**")).permitAll() // for openAPI .requestMatchers(antMatcher("/swagger-ui.html")).permitAll() // for openAPI + .requestMatchers(antMatcher(HttpMethod.GET, "/api/v5/activate")).permitAll()// for email account recovery .anyRequest().authenticated() ); diff --git a/src/main/java/com/provedcode/config/ServerInfoConfig.java b/src/main/java/com/provedcode/config/ServerInfoConfig.java new file mode 100644 index 0000000..ba483f4 --- /dev/null +++ b/src/main/java/com/provedcode/config/ServerInfoConfig.java @@ -0,0 +1,29 @@ +package com.provedcode.config; + +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +@AllArgsConstructor +@Configuration +public class ServerInfoConfig { + private Environment env; + + public String getServerPort() { + return env.getProperty("server.port"); + } + public String getIpAddress() { + InetAddress ip = null; + try { + return ip.getLocalHost().getHostAddress(); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + } + public String getFullServerAddress() { + return getIpAddress() + ":" + getServerPort(); + } +} diff --git a/src/main/java/com/provedcode/handlers/GlobalControllerAdvice.java b/src/main/java/com/provedcode/handlers/GlobalControllerAdvice.java new file mode 100644 index 0000000..1d59e1d --- /dev/null +++ b/src/main/java/com/provedcode/handlers/GlobalControllerAdvice.java @@ -0,0 +1,33 @@ +package com.provedcode.handlers; + +import com.provedcode.user.model.entity.UserInfo; +import com.provedcode.user.repo.UserInfoRepository; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.server.ResponseStatusException; + +import static org.springframework.http.HttpStatus.FORBIDDEN; +import static org.springframework.http.HttpStatus.NOT_FOUND; + +@ControllerAdvice +@AllArgsConstructor +@Slf4j +public class GlobalControllerAdvice { + UserInfoRepository userInfoRepository; + + @ModelAttribute + public void handleAuthentication(Authentication authentication) { + if (authentication != null) { + String login = authentication.getName(); + UserInfo user = userInfoRepository.findByLogin(login) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "User with login {%s} not found".formatted(login))); + if (Boolean.TRUE.equals(user.getIsLocked())) { + throw new ResponseStatusException(FORBIDDEN, "your account is blocked"); + } + } + } +} diff --git a/src/main/java/com/provedcode/kudos/controller/KudosController.java b/src/main/java/com/provedcode/kudos/controller/KudosController.java index f065d39..78fa3e1 100644 --- a/src/main/java/com/provedcode/kudos/controller/KudosController.java +++ b/src/main/java/com/provedcode/kudos/controller/KudosController.java @@ -36,7 +36,7 @@ KudosAmount getKudosForSponsor(@PathVariable("sponsor-id") long sponsorId, Authe } @GetAmountOfKudosApiDoc - @PreAuthorize("hasRole('TALENT')") + @PreAuthorize("hasAnyRole('TALENT', 'SPONSOR')") @GetMapping("/proofs/{proof-id}/kudos") KudosAmountWithSponsor getProofKudos(@PathVariable("proof-id") long proofId, Authentication authentication) { return kudosService.getProofKudos(proofId, authentication); diff --git a/src/main/java/com/provedcode/kudos/service/KudosService.java b/src/main/java/com/provedcode/kudos/service/KudosService.java index 39ae8b5..793441a 100644 --- a/src/main/java/com/provedcode/kudos/service/KudosService.java +++ b/src/main/java/com/provedcode/kudos/service/KudosService.java @@ -38,156 +38,185 @@ @AllArgsConstructor @Transactional public class KudosService { - KudosRepository kudosRepository; - TalentProofRepository talentProofRepository; - UserInfoRepository userInfoRepository; - SponsorRepository sponsorRepository; - TalentRepository talentRepository; - ProofSkillRepository proofSkillRepository; - SponsorMapper sponsorMapper; - - @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"); - } - Sponsor sponsor = sponsorRepository.findById(sponsorId).orElseThrow( - () -> new ResponseStatusException(NOT_FOUND, - String.format("Sponsor with id = %d not found", sponsorId))); - return new KudosAmount(sponsor.getAmountKudos()); + KudosRepository kudosRepository; + TalentProofRepository talentProofRepository; + UserInfoRepository userInfoRepository; + SponsorRepository sponsorRepository; + TalentRepository talentRepository; + ProofSkillRepository proofSkillRepository; + SponsorMapper sponsorMapper; + + @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"); } - - @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.getTalent().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.getProofSkills() - .stream().flatMap(proofSkills -> proofSkills.getKudos() - .stream().map(Kudos::getAmount)) - .reduce(0L, (prev, next) -> prev + next); - - if (talent.getId().equals(talentProof.getTalent().getId())) { - Map> skillsMap = new HashMap<>(); - talentProof.getProofSkills().forEach(proofSkill -> { // I dnk wtf is this piece of shit, but it - // works. - String skill = proofSkill.getSkill().getSkill(); - Map kudosFromSponsor = talentProof.getProofSkills().stream() - .filter(proofSkills -> proofSkills.getSkill().getSkill().equals(skill)) - .flatMap(proofSkills -> proofSkills.getKudos().stream()) - .collect(Collectors.toMap( - Kudos::getAmount, - proof -> proof.getSponsor() != null - ? sponsorMapper.toDto( - proof.getSponsor()) - : SponsorDTO.builder().build(), - (prev, next) -> next, - HashMap::new)); - skillsMap.put(skill, kudosFromSponsor); - }); - return KudosAmountWithSponsor.builder() - .allKudosOnProof(countOfAllKudos) - .kudosFromSponsor(skillsMap) - .build(); - } else { - return KudosAmountWithSponsor.builder() - .allKudosOnProof(countOfAllKudos) - .kudosFromSponsor(null).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()); + } + + @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))); + TalentProof talentProof = talentProofRepository.findById(proofId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Proof with id = %s not found".formatted(proofId))); + + Long countOfAllKudos = talentProof.getProofSkills() + .stream().flatMap(proofSkills -> proofSkills.getKudos() + .stream().map(Kudos::getAmount)) + .reduce(0L, Long::sum); + Map> skillsMap = new HashMap<>(); + + if (userInfo.getSponsor() != null && userInfo.getTalent() == null) { + Sponsor sponsor = sponsorRepository.findById(userInfo.getSponsor().getId()) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "User with login = %s not found".formatted( + login))); + talentProof.getProofSkills().forEach(proofSkill -> { + String skill = proofSkill.getSkill().getSkill(); + Map kudosFromSponsor = talentProof.getProofSkills().stream() + .map(proofSkills -> { + proofSkills.setKudos(proofSkills.getKudos().stream() + .filter(kudos -> sponsor.equals(kudos.getSponsor())).toList()); + return proofSkills; + }) + .filter(proofSkills -> proofSkills.getSkill().getSkill().equals(skill)) + .flatMap(proofSkills -> proofSkills.getKudos().stream()) + .collect(Collectors.toMap( + Kudos::getAmount, + proof -> proof.getSponsor() != null + ? sponsorMapper.toDto(proof.getSponsor()) + : SponsorDTO.builder().build(), + (prev, next) -> next, + HashMap::new)); + skillsMap.put(skill, kudosFromSponsor); + }); + + return KudosAmountWithSponsor.builder() + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(skillsMap) + .build(); } - public void addKudosToProof(long proofId, SetAmountKudos amountOfKudoses, 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 (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) - throw new ResponseStatusException(FORBIDDEN, - "Proof that was kudosed does not have the PUBLISHED status"); - long obtainedAmount = amountOfKudoses.amount(); - - if (sponsor.getAmountKudos() < obtainedAmount) { - throw new ResponseStatusException(FORBIDDEN, "The sponsor cannot give more kudos than he has"); - } - Long modula = obtainedAmount % talentProof.getProofSkills().size(); - if (modula != 0) { - obtainedAmount -= modula; - } - sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); - - Long addKudoses = obtainedAmount / talentProof.getProofSkills().size(); - - talentProof.getProofSkills().forEach(proofSkill -> { - Kudos kudos = Kudos.builder() - .sponsor(sponsor) - .skill(proofSkill) - .amount(addKudoses) - .build(); - proofSkill.getKudos().add(kudosRepository.save(kudos)); - }); + Talent talent = talentRepository.findById(userInfo.getTalent().getId()) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Talent with login = %s not found".formatted(login))); + if (talent.getId().equals(talentProof.getTalent().getId())) { + talentProof.getProofSkills().forEach(proofSkill -> { // I dnk wtf is this piece of shit, but it works. + String skill = proofSkill.getSkill().getSkill(); + Map kudosFromSponsor = talentProof.getProofSkills().stream() + .filter(proofSkills -> proofSkills.getSkill().getSkill().equals(skill)) + .flatMap(proofSkills -> proofSkills.getKudos().stream()) + .collect(Collectors.toMap( + Kudos::getAmount, + proof -> proof.getSponsor() != null + ? sponsorMapper.toDto(proof.getSponsor()) + : SponsorDTO.builder().build(), + (prev, next) -> next, + HashMap::new)); + skillsMap.put(skill, kudosFromSponsor); + }); + return KudosAmountWithSponsor.builder() + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(skillsMap) + .build(); + } else { + return KudosAmountWithSponsor.builder() + .allKudosOnProof(countOfAllKudos) + .kudosFromSponsor(null).build(); } - - public void addKudosToSkill(long proofId, long skillId, SetAmountKudos amountOfKudos, - 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 (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) - throw new ResponseStatusException(FORBIDDEN, - "Skill on proof that was kudosed does not have the PUBLISHED status"); - long obtainedAmount = amountOfKudos.amount(); - if (sponsor.getAmountKudos() < obtainedAmount) { - throw new ResponseStatusException(FORBIDDEN, "The sponsor cannot give more kudos than he has"); - } - sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); - ProofSkill proofSkill = talentProof.getProofSkills().stream() - .filter(s -> s.getSkill().getId().equals(skillId)) - .findFirst().orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Skill with id = %d not found".formatted(skillId))); - kudosRepository.save(Kudos.builder().amount(obtainedAmount).sponsor(sponsor).skill(proofSkill).build()); + } + + public void addKudosToProof(long proofId, SetAmountKudos amountOfKudoses, 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 (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) + throw new ResponseStatusException(FORBIDDEN, + "Proof that was kudosed does not have the PUBLISHED status"); + long obtainedAmount = amountOfKudoses.amount(); + + if (sponsor.getAmountKudos() < obtainedAmount) { + throw new ResponseStatusException(FORBIDDEN, "The sponsor cannot give more kudos than he has"); } - - @Transactional(readOnly = true) - public KudosAmount getSkillKudos(long proofId, long skillId) { - TalentProof talentProof = talentProofRepository.findById(proofId) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Proof with id = %d not found".formatted(proofId))); - if (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) - throw new ResponseStatusException(FORBIDDEN, - "The skill from the proof that was referred to does not have a PUBLISHED status"); - ProofSkill proofSkill = talentProof.getProofSkills().stream() - .filter(s -> s.getSkill().getId().equals(skillId)) - .findFirst().orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "Skill with id = %d not found".formatted(skillId))); - List kudos = kudosRepository.findBySkill(proofSkill); - long amountOfKudos = kudos.stream().map(Kudos::getAmount).reduce(0L, Long::sum); - return new KudosAmount(amountOfKudos); + Long modula = obtainedAmount % talentProof.getProofSkills().size(); + if (modula != 0) { + obtainedAmount -= modula; + } + sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); + + Long addKudoses = obtainedAmount / talentProof.getProofSkills().size(); + + talentProof.getProofSkills().forEach(proofSkill -> { + Kudos kudos = Kudos.builder() + .sponsor(sponsor) + .skill(proofSkill) + .amount(addKudoses) + .build(); + proofSkill.getKudos().add(kudosRepository.save(kudos)); + }); + } + + public void addKudosToSkill(long proofId, long skillId, SetAmountKudos amountOfKudos, + 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 (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) + throw new ResponseStatusException(FORBIDDEN, + "Skill on proof that was kudosed does not have the PUBLISHED status"); + long obtainedAmount = amountOfKudos.amount(); + if (sponsor.getAmountKudos() < obtainedAmount) { + throw new ResponseStatusException(FORBIDDEN, "The sponsor cannot give more kudos than he has"); } + sponsor.setAmountKudos(sponsor.getAmountKudos() - obtainedAmount); + ProofSkill proofSkill = talentProof.getProofSkills().stream() + .filter(s -> s.getSkill().getId().equals(skillId)) + .findFirst().orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Skill with id = %d not found".formatted(skillId))); + kudosRepository.save(Kudos.builder().amount(obtainedAmount).sponsor(sponsor).skill(proofSkill).build()); + } + + @Transactional(readOnly = true) + public KudosAmount getSkillKudos(long proofId, long skillId) { + TalentProof talentProof = talentProofRepository.findById(proofId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Proof with id = %d not found".formatted(proofId))); + if (!talentProof.getStatus().equals(ProofStatus.PUBLISHED)) + throw new ResponseStatusException(FORBIDDEN, + "The skill from the proof that was referred to does not have a PUBLISHED status"); + ProofSkill proofSkill = talentProof.getProofSkills().stream() + .filter(s -> s.getSkill().getId().equals(skillId)) + .findFirst().orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "Skill with id = %d not found".formatted(skillId))); + List kudos = kudosRepository.findBySkill(proofSkill); + long amountOfKudos = kudos.stream().map(Kudos::getAmount).reduce(0L, Long::sum); + return new KudosAmount(amountOfKudos); + } } diff --git a/src/main/java/com/provedcode/sponsor/controller/SponsorController.java b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java index 39c5bad..09aa4d0 100644 --- a/src/main/java/com/provedcode/sponsor/controller/SponsorController.java +++ b/src/main/java/com/provedcode/sponsor/controller/SponsorController.java @@ -23,13 +23,13 @@ @RestController @AllArgsConstructor @Validated -@RequestMapping("/api/v3") +@RequestMapping("/api") public class SponsorController { SponsorService sponsorService; SponsorMapper sponsorMapper; @GetAllSponsorsApiDoc - @GetMapping("/sponsors") + @GetMapping("/v3/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); @@ -37,14 +37,14 @@ Page getSponsors(@RequestParam(value = "page", defaultValue = "0") @ @GetSponsorApiDoc @PreAuthorize("hasRole('SPONSOR')") - @GetMapping("/sponsors/{id}") + @GetMapping("/v3/sponsors/{id}") SponsorDTO getSponsor(@PathVariable("id") long id, Authentication authentication) { return sponsorMapper.toDto(sponsorService.getSponsorById(id, authentication)); } @PatchEditSponsorApiDoc @PreAuthorize("hasRole('SPONSOR')") - @PatchMapping("/sponsors/{id}") + @PatchMapping("/v3/sponsors/{id}") SponsorDTO editSponsor(@PathVariable("id") long id, @RequestBody EditSponsor editSponsor, Authentication authentication) { @@ -53,8 +53,14 @@ SponsorDTO editSponsor(@PathVariable("id") long id, @DeleteSponsorApiDoc @PreAuthorize("hasRole('SPONSOR')") - @DeleteMapping("/sponsors/{id}") + @DeleteMapping("/v3/sponsors/{id}") void deleteSponsor(@PathVariable("id") long id, Authentication authentication) { sponsorService.deleteSponsor(id, authentication); } + + @PreAuthorize("hasRole('SPONSOR')") + @DeleteMapping("/v5/sponsors/{sponsor-id}") + void deactivateSponsor(@PathVariable("sponsor-id") long sponsorId, Authentication authentication) { + sponsorService.deactivateSponsor(sponsorId, authentication); + } } \ 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 index 8beaba7..40bff99 100644 --- a/src/main/java/com/provedcode/sponsor/service/SponsorService.java +++ b/src/main/java/com/provedcode/sponsor/service/SponsorService.java @@ -1,13 +1,20 @@ package com.provedcode.sponsor.service; +import com.provedcode.config.EmailDefaultProps; import com.provedcode.config.PageProperties; +import com.provedcode.config.ServerInfoConfig; 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.DeletedUser; import com.provedcode.user.model.entity.UserInfo; +import com.provedcode.user.repo.DeletedUserRepository; import com.provedcode.user.repo.UserInfoRepository; +import com.provedcode.user.service.impl.EmailService; +import com.provedcode.user.util.UsersSchedulerService; +import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -16,11 +23,13 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.server.ResponseStatusException; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.List; import java.util.Optional; +import java.util.UUID; -import static org.springframework.http.HttpStatus.BAD_REQUEST; -import static org.springframework.http.HttpStatus.FORBIDDEN; +import static org.springframework.http.HttpStatus.*; @Service @AllArgsConstructor @@ -30,6 +39,10 @@ public class SponsorService { SponsorRepository sponsorRepository; UserInfoRepository userInfoRepository; ValidateSponsorForCompliance validateSponsorForCompliance; + DeletedUserRepository deletedUserRepository; + ServerInfoConfig serverInfoConfig; + EmailService emailService; + EmailDefaultProps emailDefaultProps; @Transactional(readOnly = true) public Page getAllSponsors(Integer page, Integer size) { @@ -76,17 +89,49 @@ public void deleteSponsor(long id, Authentication authentication) { validateSponsorForCompliance.userVerification(sponsor, user, id); Sponsor deletableSponsor = sponsor.get(); + deleteSponsorByUser(user.get(), deletableSponsor); + } + + private void deleteSponsorByUser(UserInfo user, @NotNull Sponsor deletableSponsor) { List kudosList = deletableSponsor.getKudoses().stream().map(i -> { i.setSponsor(null); return i; }).toList(); deletableSponsor.setKudoses(kudosList); - userInfoRepository.delete(user.get()); + userInfoRepository.delete(user); } private void checkEditSponsorNull(EditSponsor editSponsor) { if (editSponsor.firstName() == null && editSponsor.lastName() == null && editSponsor.image() == null && - editSponsor.countOfKudos() == null) + editSponsor.countOfKudos() == null) throw new ResponseStatusException(FORBIDDEN, "you did not provide information to make changes"); } + + public void deactivateSponsor(long sponsorId, Authentication authentication) { + UserInfo user = userInfoRepository.findByLogin(authentication.getName()) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "user with login = %s not found".formatted(authentication.getName()))); + Sponsor sponsor = sponsorRepository.findById(sponsorId) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, + "sponsor with id = %s not found".formatted(sponsorId))); + if (!sponsor.equals(user.getSponsor())) { + throw new ResponseStatusException(FORBIDDEN, "you cannot update/delete another sponsor"); + } + user.setIsLocked(true); + + DeletedUser deletedUser = DeletedUser.builder() + .deletedUser(user) + .timeToDelete(Instant.now().plus(3, ChronoUnit.DAYS)) + .uuidForActivate(UUID.randomUUID().toString()) + .build(); + + String userActivateAccountLink = serverInfoConfig.getFullServerAddress() + + "/api/v5/activate?uuid=" + deletedUser.getUuidForActivate(); + + deletedUserRepository.save(deletedUser); + + emailService.sendEmail(user.getLogin(), + emailDefaultProps.userDeletedSubject(), + emailDefaultProps.userDeleted().formatted(userActivateAccountLink)); + } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/controller/TalentController.java b/src/main/java/com/provedcode/talent/controller/TalentController.java index 3c0b319..157cc17 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentController.java @@ -97,4 +97,11 @@ StatisticsDTO getStatisticsForTalent(@PathVariable("talent-id") long talentId, Authentication authentication) { return talentService.getStatisticsForTalent(talentId, authentication); } + + @PreAuthorize("hasRole('TALENT')") + @DeleteMapping("v5/talents/{talent-id}") + void deactivateTalentById(@PathVariable("talent-id") long talentId, + Authentication authentication) { + talentService.deactivateTalentById(talentId, authentication); + } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/talent/service/TalentService.java b/src/main/java/com/provedcode/talent/service/TalentService.java index d89b82d..e0e8e54 100644 --- a/src/main/java/com/provedcode/talent/service/TalentService.java +++ b/src/main/java/com/provedcode/talent/service/TalentService.java @@ -1,10 +1,11 @@ package com.provedcode.talent.service; +import com.provedcode.config.EmailDefaultProps; import com.provedcode.config.PageProperties; +import com.provedcode.config.ServerInfoConfig; import com.provedcode.kudos.model.entity.Kudos; import com.provedcode.talent.mapper.TalentProofMapper; import com.provedcode.talent.model.dto.ProofDTO; -import com.provedcode.talent.model.dto.SkillDTO; import com.provedcode.talent.model.dto.SkillIdDTO; import com.provedcode.talent.model.dto.StatisticsDTO; import com.provedcode.talent.model.entity.*; @@ -14,9 +15,12 @@ import com.provedcode.talent.repo.TalentRepository; import com.provedcode.talent.utill.ValidateTalentForCompliance; import com.provedcode.user.model.dto.SessionInfoDTO; +import com.provedcode.user.model.entity.DeletedUser; import com.provedcode.user.model.entity.UserInfo; import com.provedcode.user.repo.AuthorityRepository; +import com.provedcode.user.repo.DeletedUserRepository; import com.provedcode.user.repo.UserInfoRepository; +import com.provedcode.user.service.impl.EmailService; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.PositiveOrZero; @@ -29,6 +33,8 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.server.ResponseStatusException; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; @@ -47,6 +53,10 @@ public class TalentService { ValidateTalentForCompliance validateTalentForCompliance; SkillsRepository skillsRepository; TalentProofMapper talentProofMapper; + DeletedUserRepository deletedUserRepository; + ServerInfoConfig serverInfoConfig; + EmailService emailService; + EmailDefaultProps emailDefaultProps; @Transactional(readOnly = true) public Page getTalentsPage(Integer page, Integer size) { @@ -143,15 +153,34 @@ public SessionInfoDTO deleteTalentById(long id, Authentication authentication) { validateTalentForCompliance.userVerification(talent, userInfo, id); UserInfo user = userInfo.get(); - Talent entity = talent.get(); - - user.getAuthorities().clear(); userInfoRepository.delete(user); - talentRepository.delete(entity); return new SessionInfoDTO("deleted", "null"); } + public void deactivateTalentById(long id, Authentication authentication) { + Optional talent = talentRepository.findById(id); + Optional userInfo = userInfoRepository.findByLogin(authentication.getName()); + + validateTalentForCompliance.userVerification(talent, userInfo, id); + + UserInfo user = userInfo.get(); + user.setIsLocked(true); + DeletedUser deletedUser = DeletedUser.builder() + .deletedUser(user) + .timeToDelete(Instant.now().plus(3, ChronoUnit.DAYS)) + .uuidForActivate(UUID.randomUUID().toString()) + .build(); + deletedUserRepository.save(deletedUser); + userInfoRepository.save(user); + + String userActivateAccountLink = serverInfoConfig.getFullServerAddress() + "/api/v5/activate?uuid=" + deletedUser.getUuidForActivate(); + + emailService.sendEmail(user.getLogin(), + emailDefaultProps.userDeletedSubject(), + emailDefaultProps.userDeleted().formatted(userActivateAccountLink)); + } + private void checkEditTalentNull(EditTalent editTalent) { if (editTalent.firstName() == null && editTalent.lastName() == null && editTalent.image() == null && editTalent.specialization() == null && editTalent.additionalInfo() == null && editTalent.bio() == null && diff --git a/src/main/java/com/provedcode/user/controller/AuthenticationController.java b/src/main/java/com/provedcode/user/controller/AuthenticationController.java index b30ee13..e25f35b 100644 --- a/src/main/java/com/provedcode/user/controller/AuthenticationController.java +++ b/src/main/java/com/provedcode/user/controller/AuthenticationController.java @@ -1,5 +1,6 @@ package com.provedcode.user.controller; +import com.provedcode.talent.service.TalentService; import com.provedcode.user.model.dto.SponsorRegistrationDTO; import com.provedcode.user.model.dto.TalentRegistrationDTO; import com.provedcode.user.model.dto.UserInfoDTO; @@ -40,4 +41,9 @@ UserInfoDTO register(@RequestBody @Valid TalentRegistrationDTO user) { UserInfoDTO register(@RequestBody @Valid SponsorRegistrationDTO user) { return authenticationService.register(user); } + + @GetMapping("/v5/activate") + void activateAccount(@RequestParam("uuid") String uuid) { + authenticationService.activateAccount(uuid); + } } \ No newline at end of file diff --git a/src/main/java/com/provedcode/user/model/entity/DeletedUser.java b/src/main/java/com/provedcode/user/model/entity/DeletedUser.java new file mode 100644 index 0000000..105f920 --- /dev/null +++ b/src/main/java/com/provedcode/user/model/entity/DeletedUser.java @@ -0,0 +1,25 @@ +package com.provedcode.user.model.entity; + +import jakarta.persistence.*; +import lombok.*; +import lombok.extern.slf4j.Slf4j; + +import java.time.Instant; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +@Slf4j +@Builder +@Entity +public class DeletedUser { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private Instant timeToDelete; + @OneToOne + @JoinColumn(name = "user_id", referencedColumnName = "id") + private UserInfo deletedUser; + private String uuidForActivate; +} \ 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 19dc0da..7250e83 100644 --- a/src/main/java/com/provedcode/user/model/entity/UserInfo.java +++ b/src/main/java/com/provedcode/user/model/entity/UserInfo.java @@ -55,4 +55,7 @@ public class UserInfo { @ManyToMany(fetch = FetchType.EAGER) @JoinTable(name = "users_authorities", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "authority_id")) private Set authorities = new LinkedHashSet<>(); + + @Column(columnDefinition = "FALSE") + private Boolean isLocked; } \ No newline at end of file diff --git a/src/main/java/com/provedcode/user/repo/DeletedUserRepository.java b/src/main/java/com/provedcode/user/repo/DeletedUserRepository.java new file mode 100644 index 0000000..de3478a --- /dev/null +++ b/src/main/java/com/provedcode/user/repo/DeletedUserRepository.java @@ -0,0 +1,15 @@ +package com.provedcode.user.repo; + +import com.provedcode.user.model.entity.DeletedUser; +import com.provedcode.user.model.entity.UserInfo; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.Optional; + +public interface DeletedUserRepository extends JpaRepository { + @Query("select d from DeletedUser d where d.uuidForActivate = ?1") + Optional findByUUID(String uuidForActivate); + Optional findByUuidForActivate(String uuidForActivate); + +} \ No newline at end of file diff --git a/src/main/java/com/provedcode/user/service/AuthenticationService.java b/src/main/java/com/provedcode/user/service/AuthenticationService.java index 57b7bcd..277af5d 100644 --- a/src/main/java/com/provedcode/user/service/AuthenticationService.java +++ b/src/main/java/com/provedcode/user/service/AuthenticationService.java @@ -9,6 +9,10 @@ public interface AuthenticationService { UserInfoDTO login(String name, Collection authorities); + UserInfoDTO register(TalentRegistrationDTO user); + UserInfoDTO register(SponsorRegistrationDTO user); + + void activateAccount(String uuid); } 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 dbcce3e..2adc01f 100644 --- a/src/main/java/com/provedcode/user/service/impl/AuthenticationServiceImpl.java +++ b/src/main/java/com/provedcode/user/service/impl/AuthenticationServiceImpl.java @@ -9,13 +9,14 @@ 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.DeletedUser; import com.provedcode.user.model.entity.UserInfo; import com.provedcode.user.repo.AuthorityRepository; +import com.provedcode.user.repo.DeletedUserRepository; import com.provedcode.user.repo.UserInfoRepository; import com.provedcode.user.service.AuthenticationService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.catalina.User; import org.springframework.http.HttpStatus; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.crypto.password.PasswordEncoder; @@ -47,6 +48,7 @@ public class AuthenticationServiceImpl implements AuthenticationService { SponsorRepository sponsorRepository; AuthorityRepository authorityRepository; PasswordEncoder passwordEncoder; + DeletedUserRepository deletedUserRepository; @Transactional(readOnly = true) public UserInfoDTO login(String name, Collection authorities) { @@ -80,6 +82,7 @@ public UserInfoDTO register(TalentRegistrationDTO user) { .login(user.login()) .password(passwordEncoder.encode(user.password())) .authorities(Set.of(authorityRepository.findByAuthority(Role.TALENT).orElseThrow())) + .isLocked(false) .build(); userInfoRepository.save(userInfo); @@ -111,6 +114,7 @@ public UserInfoDTO register(SponsorRegistrationDTO user) { .password(passwordEncoder.encode(user.password())) .authorities( Set.of(authorityRepository.findByAuthority(Role.SPONSOR).orElseThrow())) + .isLocked(false) .build(); userInfoRepository.save(userInfo); @@ -123,6 +127,15 @@ public UserInfoDTO register(SponsorRegistrationDTO user) { return new UserInfoDTO(generateJWTToken(sponsor.getId(), userLogin, userAuthorities).getTokenValue()); } + public void activateAccount(String uuid) { + DeletedUser deletedUser = deletedUserRepository.findByUUID(uuid) + .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); + UserInfo user = deletedUser.getDeletedUser(); + user.setIsLocked(false); + deletedUserRepository.deleteById(deletedUser.getId()); + userInfoRepository.save(user); + } + private Jwt generateJWTToken(Long id, String login, Collection authorities) { log.info("=== POST /login === auth.login = {}", login); log.info("=== POST /login === auth = {}", authorities); diff --git a/src/main/java/com/provedcode/user/service/impl/EmailService.java b/src/main/java/com/provedcode/user/service/impl/EmailService.java new file mode 100644 index 0000000..c497427 --- /dev/null +++ b/src/main/java/com/provedcode/user/service/impl/EmailService.java @@ -0,0 +1,25 @@ +package com.provedcode.user.service.impl; + +import com.provedcode.config.EmailConfig; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Service; + +@Service +@AllArgsConstructor +@Slf4j +public class EmailService { + private JavaMailSender javaMailSender; + private EmailConfig emailConfig; + + public void sendEmail(String to, String subject, String text) { + SimpleMailMessage message = new SimpleMailMessage(); + message.setFrom(emailConfig.getDefaultEmail()); + message.setTo(to); + message.setSubject(subject); + message.setText(text); + javaMailSender.send(message); + } +} diff --git a/src/main/java/com/provedcode/user/util/UsersSchedulerService.java b/src/main/java/com/provedcode/user/util/UsersSchedulerService.java new file mode 100644 index 0000000..63285dd --- /dev/null +++ b/src/main/java/com/provedcode/user/util/UsersSchedulerService.java @@ -0,0 +1,64 @@ +package com.provedcode.user.util; + +import com.provedcode.user.repo.DeletedUserRepository; +import com.provedcode.user.repo.UserInfoRepository; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.Instant; +import java.util.concurrent.TimeUnit; + +@Service +@EnableScheduling +@AllArgsConstructor +@Transactional +@Slf4j +public class UsersSchedulerService { + UserInfoRepository userInfoRepository; + DeletedUserRepository deletedUsersRepository; + + @Scheduled(timeUnit = TimeUnit.HOURS, fixedRate = 1) + void deleteUser() { + deletedUsersRepository.findAll() + .forEach(userToDelete -> { + if (userToDelete.getTimeToDelete().isAfter(Instant.now())) { + log.info("deleting user: id = {}", userToDelete.getDeletedUser().getId()); + deletedUsersRepository.delete(userToDelete); + userInfoRepository.delete(userToDelete.getDeletedUser()); + } + }); + } + +// @Async +// public void scheduleDeletingMethod(String uuid) { +// try { +// TimeUnit.MINUTES.sleep(3); +// log.info("scheduleDeletingMethod = {}", uuid); +// deletedUsersRepository.findByUUID(uuid) +// .ifPresent(deleted -> { +// deletedUsersRepository.delete(deleted); +// deleteUser(deleted.getDeletedUser()); +// }); +// } catch (InterruptedException e) { +// Thread.currentThread().interrupt(); +// } +// } +// +// private void deleteUser(UserInfo user) { +// if (user.getSponsor() != null) { +// List kudosList = user.getSponsor().getKudoses().stream().map(i -> { +// i.setSponsor(null); +// return i; +// }).toList(); +// user.getSponsor().setKudoses(kudosList); +// userInfoRepository.delete(user); +// } +// if (user.getTalent() != null) { +// userInfoRepository.delete(user); +// } +// } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f91aa56..d3d2982 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -38,4 +38,14 @@ page-config.default-page-num=0 page-config.default-page-size=5 page-config.default-sort-by=created ## -spring.liquibase.enabled=true \ No newline at end of file +spring.liquibase.enabled=true +## +spring.mail.host=smtp.gmail.com +spring.mail.port=587 +spring.mail.username=${EMAIL_USER} +spring.mail.password=${EMAIL_PASSWORD} +spring.mail.properties.mail.smtp.auth=true +spring.mail.properties.mail.smtp.starttls.enable=true +# Default email response +default-email.user-deleted=Your account has been suspended, it will be deleted after 24 hours, click on the link to restore it:\n%s\nBest wishes from the test team. +default-email.user-deleted-subject=Your account has been suspended, TestTeam. \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V5/data-V5.sql b/src/main/resources/db/changelog/changeset/V5/data-V5.sql index b897501..2d63889 100644 --- a/src/main/resources/db/changelog/changeset/V5/data-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/data-V5.sql @@ -5,33 +5,7 @@ insert into authorities (id, authority) values (1, 'TALENT'); insert into authorities (id, authority) values (2, 'SPONSOR'); --- Skill -insert into skills (id, skill) -values (1, 'Java Core'); -insert into skills (id, skill) -values (2, 'Spring Core'); -insert into skills (id, skill) -values (3, 'Spring boot'); -insert into skills (id, skill) -values (4, 'H2 Database'); -insert into skills (id, skill) -values (5, 'Spring Security'); -insert into skills (id, skill) -values (6, 'REST API'); -insert into skills (id, skill) -values (7, 'Git'); -insert into skills (id, skill) -values (8, 'Docker'); -insert into skills (id, skill) -values (9, 'Jira'); -insert into skills (id, skill) -values (10, 'JavaScript Core'); -insert into skills (id, skill) -values (11, 'React'); -insert into skills (id, skill) -values (12, 'Node.js'); -insert into skills (id, skill) -values (13, 'Angular'); + -- Talent -- Serhii Soloviov insert into talents (first_name, last_name, specialization, image) diff --git a/src/main/resources/db/changelog/changeset/V5/deleted-user-schema.sql b/src/main/resources/db/changelog/changeset/V5/deleted-user-schema.sql new file mode 100644 index 0000000..7f19179 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V5/deleted-user-schema.sql @@ -0,0 +1,14 @@ +--liquibase formatted sql +--changeset Maslyna:5 + +CREATE TABLE deleted_user +( + id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + time_to_delete TIMESTAMP WITHOUT TIME ZONE, + user_id BIGINT, + uuid_for_activate VARCHAR(255), + CONSTRAINT pk_deleteduser PRIMARY KEY (id) +); + +ALTER TABLE deleted_user + ADD CONSTRAINT FK_DELETEDUSER_ON_USER FOREIGN KEY (user_id) REFERENCES users_info (id); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V5/skills-data.sql b/src/main/resources/db/changelog/changeset/V5/skills-data.sql new file mode 100644 index 0000000..cd7848c --- /dev/null +++ b/src/main/resources/db/changelog/changeset/V5/skills-data.sql @@ -0,0 +1,223 @@ +--liquibase formatted sql +--changeset Maslyna:0 + +-- Skill +insert into skills (id, skill) +values (1, 'Java Core'); +insert into skills (id, skill) +values (2, 'Spring Core'); +insert into skills (id, skill) +values (3, 'Spring boot'); +insert into skills (id, skill) +values (4, 'H2 Database'); +insert into skills (id, skill) +values (5, 'Spring Security'); +insert into skills (id, skill) +values (6, 'REST API'); +insert into skills (id, skill) +values (7, 'Git'); +insert into skills (id, skill) +values (8, 'Docker'); +insert into skills (id, skill) +values (9, 'Jira'); +insert into skills (id, skill) +values (10, 'JavaScript Core'); +insert into skills (id, skill) +values (11, 'React'); +insert into skills (id, skill) +values (12, 'Node.js'); +insert into skills (id, skill) +values (13, 'Angular'); +-- +INSERT INTO skills (id, skill) +VALUES (14, 'Java Development Kit (JDK)'), + (15, 'Servlet API'), + (16, 'JavaServer Pages (JSP)'), + (17, 'JavaServer Faces (JSF)'), + (18, 'Spring Framework'), + (19, 'Hibernate'), + (20, 'Apache Struts'), + (21, 'MySQL'), + (22, 'PostgreSQL'), + (23, 'Oracle'), + (24, 'SQL'), + (25, 'Eclipse'), + (26, 'IntelliJ IDEA'), + (27, 'NetBeans'), + (28, 'Apache Tomcat'), + (29, 'Jetty'), + (30, 'JBoss'), + (31, 'Git'), + (32, 'SVN'), + (33, 'Mercurial'), + (34, 'Algorithms and data structures'), + (35, 'SOAP'), + (36, 'REST'), + (37, 'JSON'), + (38, 'XML'), + (39, 'Multithreading and parallelism'); +INSERT INTO skills (id, skill) +VALUES (40, 'Django'), + (41, 'Flask'), + (42, 'Pyramid'), + (43, 'SQLite'), + (44, 'NoSQL'), + (45, 'MongoDB'), + (46, 'Redis'), + (47, 'BeautifulSoup'), + (48, 'Scrapy'), + (49, 'asyncio'), + (50, 'Twisted'), + (51, 'NumPy'), + (52, 'SciPy'), + (53, 'Pandas'), + (54, 'scikit-learn'), + (55, 'TensorFlow'), + (56, 'PyTorch'), + (57, 'JavaScript'), + (58, 'HTML'), + (59, 'CSS'), + (60, 'DOM'), + (61, 'React'), + (62, 'Angular'), + (63, 'Vue.js'), + (64, 'jQuery'), + (65, 'AJAX'), + (66, 'XSS (Cross-Site Scripting)'), + (67, 'CSRF (Cross-Site Request Forgery)'), + (68, 'Swift'), + (69, 'UIKit'), + (70, 'AppKit'), + (71, 'Core Data'), + (72, 'Core Animation'), + (73, 'Core Location'), + (74, 'Core Graphics'), + (75, 'Storyboards'), + (76, 'Interface Builder'), + (77, 'Auto Layout'), + (78, 'CoreData'), + (79, 'Asynchronous programming'), + (80, 'MVC (Model-View-Controller)'), + (81, 'MVVM (Model-View-ViewModel)'), + (82, 'Clean Architecture'), + (83, 'Kotlin'), + (84, 'Android SDK'), + (85, 'Firebase'), + (86, 'Jenkins'), + (87, 'Docker'), + (88, 'UNIX'), + (89, 'Linux OS'), + (90, 'JPA'), + (91, 'JUnit'), + (92, 'OOP'), + (93, 'PHP'), + (94, 'Microservices'), + (95, 'Azure Service Bus'), + (96, 'Typescript'), + (97, 'WinForms'), + (98, 'Firebase Analytics'), + (99, 'Appsflyer'), + (100, 'Amplitude'); +INSERT INTO skills (id, skill) +VALUES (101, 'Marketing'), + (102, 'Sales'), + (103, 'Content Writing'), + (104, 'Graphic Design'), + (105, 'Video Editing'), + (106, 'Project Management'), + (107, 'Leadership'), + (108, 'Negotiation'), + (109, 'Public Speaking'), + (110, 'Time Management'), + (111, 'Critical Thinking'), + (112, 'Problem Solving'), + (113, 'Customer Service'), + (114, 'Data Analysis'), + (115, 'Financial Planning'), + (116, 'Event Planning'), + (117, 'Foreign Languages'), + (118, 'Photography'), + (119, 'Cooking'), + (120, 'Yoga'), + (121, 'Creative Writing'); +INSERT INTO skills (id, skill) +VALUES (122, 'Leadership Development'), + (123, 'Emotional Intelligence'), + (124, 'Teamwork'), + (125, 'Conflict Resolution'), + (126, 'Decision Making'), + (127, 'Presentation Skills'), + (128, 'Networking'), + (129, 'Research Skills'), + (130, 'Problem-solving'), + (131, 'Analytical Thinking'), + (132, 'Creativity'), + (133, 'Attention to Detail'), + (134, 'Organizational Skills'), + (135, 'Time Management'), + (136, 'Adaptability'), + (137, 'Stress Management'), + (138, 'Interpersonal Skills'), + (139, 'Communication Skills'), + (140, 'Customer Relationship Management'), + (141, 'Sales Techniques'), + (142, 'Market Research'), + (143, 'Digital Marketing'), + (144, 'Social Media Marketing'), + (145, 'Search Engine Optimization'), + (146, 'Content Marketing'), + (147, 'Data Analytics'), + (148, 'Financial Analysis'), + (149, 'Budgeting'), + (150, 'Project Planning'), + (151, 'Quality Assurance'), + (152, 'Risk Management'), + (153, 'Supply Chain Management'), + (154, 'Logistics'), + (155, 'Business Strategy'), + (156, 'Entrepreneurship'), + (157, 'Innovation'), + (158, 'Customer Service'), + (159, 'Hospitality'), + (160, 'Event Management'); +INSERT INTO skills (id, skill) +VALUES (161, 'Teaching'), + (162, 'Tutoring'), + (163, 'Curriculum Development'), + (164, 'Instructional Design'), + (165, 'Classroom Management'), + (166, 'Educational Technology'), + (167, 'Language Teaching'), + (168, 'Music'), + (169, 'Art'), + (170, 'Sports'), + (171, 'Fitness'), + (172, 'Nutrition'), + (173, 'Counseling'), + (174, 'Life Coaching'), + (175, 'Meditation'), + (176, 'Mindfulness'), + (177, 'Research'), + (178, 'Data Entry'), + (179, 'Virtual Assistance'), + (180, 'Project Coordination'), + (181, 'Event Coordination'), + (182, 'Office Management'), + (183, 'Translation'), + (184, 'Transcription'), + (185, 'Proofreading'), + (186, 'Editing'), + (187, 'Copywriting'), + (188, 'Content Creation'), + (189, 'Social Media Management'), + (190, 'Graphic Design'), + (191, 'Video Editing'), + (192, 'Photography'), + (193, 'Web Development'), + (194, 'Mobile App Development'), + (195, 'Game Development'), + (196, 'UI/UX Design'), + (197, 'Product Management'), + (198, 'Agile Methodology'), + (199, 'Scrum'), + (200, 'Lean Manufacturing'); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changeset/V5/user-info-schema-V5.sql b/src/main/resources/db/changelog/changeset/V5/user-info-schema-V5.sql index 97b1109..3028fe7 100644 --- a/src/main/resources/db/changelog/changeset/V5/user-info-schema-V5.sql +++ b/src/main/resources/db/changelog/changeset/V5/user-info-schema-V5.sql @@ -8,6 +8,7 @@ CREATE TABLE users_info ( sponsor_id BIGINT REFERENCES sponsors, login VARCHAR(100) NOT NULL, password VARCHAR(255) NOT NULL, + is_locked BOOLEAN, PRIMARY KEY (id) ); CREATE TABLE authorities ( diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 77eb9b2..49cbdae 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -23,7 +23,12 @@ databaseChangeLog: file: db/changelog/changeset/V5/user-info-schema-V5.sql - include: file: db/changelog/changeset/V5/data-V5.sql + - include: + file: db/changelog/changeset/V5/skills-data.sql - include: file: db/changelog/changeset/V5/dataSkill-V5.sql - include: file: db/changelog/changeset/V5/dataKudos-V5.sql + - include: + file: db/changelog/changeset/V5/deleted-user-schema.sql + From 5f645fd225244108419dd1241e8d17345c8e910f Mon Sep 17 00:00:00 2001 From: Maslyna Date: Wed, 24 May 2023 12:39:27 +0200 Subject: [PATCH 59/59] MERGE UPDATE --- .../talent/controller/TalentController.java | 4 +- .../talent/service/TalentSkillsService.java | 115 ------------------ 2 files changed, 3 insertions(+), 116 deletions(-) delete mode 100644 src/main/java/com/provedcode/talent/service/TalentSkillsService.java diff --git a/src/main/java/com/provedcode/talent/controller/TalentController.java b/src/main/java/com/provedcode/talent/controller/TalentController.java index 7373c7b..cb81997 100644 --- a/src/main/java/com/provedcode/talent/controller/TalentController.java +++ b/src/main/java/com/provedcode/talent/controller/TalentController.java @@ -3,6 +3,8 @@ 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.dto.SkillIdDTO; +import com.provedcode.talent.model.dto.StatisticsDTO; import com.provedcode.talent.model.request.EditTalent; import com.provedcode.talent.service.TalentService; import com.provedcode.user.model.dto.SessionInfoDTO; @@ -43,7 +45,7 @@ Page getTalents(@RequestParam(value = "page", defaultValue = "0" } @GetTalentApiDoc - @PreAuthorize("hasRole('TALENT', 'SPONSOR')") + @PreAuthorize("hasAnyRole('TALENT', 'SPONSOR')") @GetMapping("v2/talents/{id}") FullTalentDTO getTalent(@PathVariable("id") long id, Authentication authentication) { log.info("get-talent auth = {}", authentication); diff --git a/src/main/java/com/provedcode/talent/service/TalentSkillsService.java b/src/main/java/com/provedcode/talent/service/TalentSkillsService.java deleted file mode 100644 index 3926eb6..0000000 --- a/src/main/java/com/provedcode/talent/service/TalentSkillsService.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.provedcode.talent.service; - -import com.provedcode.talent.model.ProofStatus; -import com.provedcode.talent.model.dto.ProofSkillsDTO; -import com.provedcode.talent.model.dto.SkillsOnProofDTO; -import com.provedcode.talent.model.entity.Skills; -import com.provedcode.talent.model.entity.Talent; -import com.provedcode.talent.model.entity.TalentProof; -import com.provedcode.talent.repo.SkillsRepository; -import com.provedcode.talent.repo.TalentProofRepository; -import com.provedcode.talent.repo.TalentRepository; -import com.provedcode.user.model.entity.UserInfo; -import com.provedcode.user.repo.UserInfoRepository; -import lombok.AllArgsConstructor; -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.HashSet; -import java.util.Set; -import java.util.function.BiConsumer; - -import static org.springframework.http.HttpStatus.*; - -@Transactional -@Service -@AllArgsConstructor -public class TalentSkillsService { - SkillsRepository skillsRepository; - TalentRepository talentRepository; - UserInfoRepository userInfoRepository; - TalentProofRepository talentProofRepository; - - static BiConsumer isValidUserEditTalent = (talentId, userInfo) -> { - if (!userInfo.getTalent().getId().equals(talentId)) { - throw new ResponseStatusException(CONFLICT, "you can`t change another talent"); - } - }; - - public void addSkillsOnProof(long talentId, long proofId, ProofSkillsDTO skills, Authentication authentication) { - if (!talentRepository.existsById(talentId)) { - throw new ResponseStatusException(NOT_FOUND, "talent with id = %s not found".formatted(talentId)); - } - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); - TalentProof talentProof = talentProofRepository.findById(proofId) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "proof with id = %s not found".formatted(proofId))); - if (!talentProof.getStatus().equals(ProofStatus.DRAFT)) { - throw new ResponseStatusException(CONFLICT, "proof status must be DRAFT"); - } - - isValidUserEditTalent.accept(talentId, userInfo); - skills.skills().forEach(skillId -> { - if (!skillsRepository.existsById(skillId)) - throw new ResponseStatusException(NOT_FOUND, "no such skill with id = " + skillId); - }); - - Set skillsSet = new HashSet<>(skillsRepository.findAllById(skills.skills())); - talentProof.getSkills().forEach(skill -> { - if (skillsSet.contains(skill)) - throw new ResponseStatusException(CONFLICT, - "skill with id = %s already on skill".formatted(skill.getId())); - }); - - talentProof.getSkills().addAll(skillsSet); - talentProofRepository.save(talentProof); - } - - @Transactional(readOnly = true) - public SkillsOnProofDTO getAllSkillsOnProof(long proofId, Authentication authentication) { - TalentProof talentProof = talentProofRepository.findById(proofId) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "proof with id = %s not found".formatted(proofId))); - if (talentProof.getStatus().equals(ProofStatus.PUBLISHED)) { - return SkillsOnProofDTO.builder().skills(talentProof.getSkills()).build(); - } else if (authentication != null) { - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); - if (userInfo.getTalent().getId().equals(talentProof.getTalent().getId())) { - return SkillsOnProofDTO.builder().skills(talentProof.getSkills()).build(); - } else { - throw new ResponseStatusException(FORBIDDEN, "you can't see proofs in DRAFT and HIDDEN status"); - } - } else { - throw new ResponseStatusException(FORBIDDEN, "you can't see proofs in DRAFT and HIDDEN status"); - } - } - - public void deleteSkillOnProof(long talentId, long proofId, long skillId, Authentication authentication) { - Talent talent = talentRepository.findById(talentId) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "talent with id = %s not found".formatted(talentId))); - UserInfo userInfo = userInfoRepository.findByLogin(authentication.getName()) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND)); - TalentProof talentProof = talentProofRepository.findById(proofId) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, "proof with id = %s not found".formatted(proofId))); - if (!talentProof.getStatus().equals(ProofStatus.DRAFT)) { - throw new ResponseStatusException(CONFLICT, "proof status must be DRAFT"); - } - if (!talent.getId().equals(talentProof.getTalent().getId())) { - throw new ResponseStatusException(BAD_REQUEST, - "talentId with id = %s and proofId with id = %s do not match".formatted(talentId, proofId)); - } - isValidUserEditTalent.accept(talentId, userInfo); - Skills skills = skillsRepository.findById(skillId) - .orElseThrow(() -> new ResponseStatusException(NOT_FOUND, - "skill with id = %s not found".formatted(skillId))); - if (!talentProof.getSkills().contains(skills)) { - throw new ResponseStatusException(NOT_FOUND, - "you dont have skill with id = %s on proof with id = %s".formatted(skillId, proofId)); - } - talentProof.getSkills().remove(skills); - } -}