diff --git a/README.md b/README.md index de1bb5bb..2888772a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## Project Documents -For other information, you can check [Wiki](https://github.com/gelecekbilimde/gelecekbilimde-backend/wiki) +For other information, you can check [Wiki](https://gelecekbilimde.atlassian.net/wiki/spaces/GBS/overview) Page. --- @@ -57,3 +57,16 @@ The following command can be used to remove Docker Containers. > directory. > is required. +--- + +# Project Infrastructure + +## 🏛️ HexaLayered Architecture + +![](/documents/architecture/gb-architecture.png?raw=true) + +> **Reference: [HexaLayered Architecture](https://github.com/agitrubard/hexalayered-architecture)** + +## 📦 Package Architecture + +![](/documents/architecture/package-architecture-example.png?raw=true) diff --git a/documents/architecture/gb-architecture.drawio b/documents/architecture/gb-architecture.drawio new file mode 100644 index 00000000..8fe381b7 --- /dev/null +++ b/documents/architecture/gb-architecture.drawio @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documents/architecture/gb-architecture.png b/documents/architecture/gb-architecture.png new file mode 100644 index 00000000..2d5f440e Binary files /dev/null and b/documents/architecture/gb-architecture.png differ diff --git a/documents/architecture/package-architecture-example.drawio b/documents/architecture/package-architecture-example.drawio new file mode 100644 index 00000000..c0391e06 --- /dev/null +++ b/documents/architecture/package-architecture-example.drawio @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/documents/architecture/package-architecture-example.png b/documents/architecture/package-architecture-example.png new file mode 100644 index 00000000..1e399168 Binary files /dev/null and b/documents/architecture/package-architecture-example.png differ diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/config/SecurityConfiguration.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/config/SecurityConfiguration.java index 3fde2970..71dca840 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/config/SecurityConfiguration.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/config/SecurityConfiguration.java @@ -43,15 +43,20 @@ public SecurityFilterChain filterChain(HttpSecurity httpSecurity, httpSecurity.cors(customizer -> customizer.configurationSource(corsConfigurationSource())) .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(customizer -> customizer - .requestMatchers(HttpMethod.GET, "/public/**").permitAll() - .requestMatchers("/api/v1/version", "/api/v1/auth/**", "/api/v1/category/**") + .requestMatchers(HttpMethod.GET, "/public/**") .permitAll() - .requestMatchers(HttpMethod.GET, "/api/v1/users/*/followers", "/api/v1/users/*/followings") + .requestMatchers("/api/v1/auth/**") + .permitAll() + .requestMatchers("/api/v1/categories/summary") + .permitAll() + .requestMatchers(HttpMethod.GET, "/api/v1/user/*/followers", "/api/v1/user/*/followings") .permitAll() .anyRequest() - .authenticated()) + .authenticated() + ) .sessionManagement(customizer -> customizer - .sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + ) .addFilterBefore(bearerTokenAuthenticationFilter, BearerTokenAuthenticationFilter.class); return httpSecurity.build(); @@ -71,4 +76,5 @@ CorsConfigurationSource corsConfigurationSource() { public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } + } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/AlreadyRegisteredException.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/AlreadyRegisteredException.java deleted file mode 100644 index 7aeb0370..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/AlreadyRegisteredException.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.gelecekbilimde.scienceplatform.auth.exception; - -import java.io.Serial; - -public class AlreadyRegisteredException extends RuntimeException { - - @Serial - private static final long serialVersionUID = -8120776112921535480L; - - public AlreadyRegisteredException(String email) { - super("This user is already registered" + email); - } -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/KeyPairConversionException.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/KeyPairConversionException.java index 183d436c..edd1de56 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/KeyPairConversionException.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/KeyPairConversionException.java @@ -4,10 +4,10 @@ import java.io.Serial; -public class KeyPairConversionException extends AbstractServerException { +public final class KeyPairConversionException extends AbstractServerException { @Serial - private static final long serialVersionUID = -714864829639781798L; + private static final long serialVersionUID = 304959574320527271L; public KeyPairConversionException(Throwable cause) { super("error occurred while converting key pair", cause); diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/KeyPairGenerationException.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/KeyPairGenerationException.java index 6cac596f..88befbd7 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/KeyPairGenerationException.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/KeyPairGenerationException.java @@ -4,10 +4,10 @@ import java.io.Serial; -public class KeyPairGenerationException extends AbstractServerException { +public final class KeyPairGenerationException extends AbstractServerException { @Serial - private static final long serialVersionUID = 7666167175325870801L; + private static final long serialVersionUID = 6533777004102054133L; public KeyPairGenerationException(Throwable cause) { super("error occurred while generating key pair", cause); diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationAlreadyConcludedException.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationAlreadyConcludedException.java index 2f8244ab..a52267a2 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationAlreadyConcludedException.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationAlreadyConcludedException.java @@ -4,10 +4,10 @@ import java.io.Serial; -public class RoleApplicationAlreadyConcludedException extends AbstractConflictException { +public final class RoleApplicationAlreadyConcludedException extends AbstractConflictException { @Serial - private static final long serialVersionUID = -7807528937254572325L; + private static final long serialVersionUID = 6963403850981238210L; public RoleApplicationAlreadyConcludedException(String id) { super("role application already concluded id: " + id); diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationAlreadyExistException.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationAlreadyExistException.java index a6fd9a3c..e28ae7e4 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationAlreadyExistException.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationAlreadyExistException.java @@ -4,10 +4,10 @@ import java.io.Serial; -public class RoleApplicationAlreadyExistException extends AbstractConflictException { +public final class RoleApplicationAlreadyExistException extends AbstractConflictException { @Serial - private static final long serialVersionUID = 3834570698226426742L; + private static final long serialVersionUID = 8186687324812319190L; public RoleApplicationAlreadyExistException() { super("user already has a role application in review"); diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationNotFoundByIdException.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationNotFoundByIdException.java index 7a9c9df8..3a44b479 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationNotFoundByIdException.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationNotFoundByIdException.java @@ -4,10 +4,10 @@ import java.io.Serial; -public class RoleApplicationNotFoundByIdException extends AbstractNotFoundException { +public final class RoleApplicationNotFoundByIdException extends AbstractNotFoundException { @Serial - private static final long serialVersionUID = -7420720906649254998L; + private static final long serialVersionUID = -1036422987236610575L; public RoleApplicationNotFoundByIdException(String id) { super("role application does not found! id: " + id); diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationNotFoundByUserIdAndStatusException.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationNotFoundByUserIdAndStatusException.java index 4f73aac0..1831a477 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationNotFoundByUserIdAndStatusException.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleApplicationNotFoundByUserIdAndStatusException.java @@ -5,10 +5,10 @@ import java.io.Serial; -public class RoleApplicationNotFoundByUserIdAndStatusException extends AbstractNotFoundException { +public final class RoleApplicationNotFoundByUserIdAndStatusException extends AbstractNotFoundException { @Serial - private static final long serialVersionUID = 4738260982768669235L; + private static final long serialVersionUID = -8360751775119161646L; public RoleApplicationNotFoundByUserIdAndStatusException(String userId, RoleApplicationStatus status) { super("role application not found! userId: " + userId + ", status: " + status); diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleNotFoundByNameException.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleNotFoundByNameException.java index d340e190..e9a8c2d0 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleNotFoundByNameException.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/RoleNotFoundByNameException.java @@ -2,10 +2,10 @@ import java.io.Serial; -public class RoleNotFoundByNameException extends RuntimeException { +public final class RoleNotFoundByNameException extends RuntimeException { @Serial - private static final long serialVersionUID = -927147689852209182L; + private static final long serialVersionUID = -4700198439829934412L; public RoleNotFoundByNameException(String name) { super("role not found with name: " + name); diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserAlreadyRegisteredException.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserAlreadyRegisteredException.java new file mode 100644 index 00000000..0b06e66f --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserAlreadyRegisteredException.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.auth.exception; + +import org.gelecekbilimde.scienceplatform.common.exception.AbstractConflictException; + +import java.io.Serial; + +public final class UserAlreadyRegisteredException extends AbstractConflictException { + + @Serial + private static final long serialVersionUID = -5670350199459862153L; + + public UserAlreadyRegisteredException(String email) { + super("user already registered by " + email); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserNotVerifiedException.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserNotVerifiedException.java index 5704e161..306237c9 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserNotVerifiedException.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserNotVerifiedException.java @@ -4,10 +4,10 @@ import java.io.Serial; -public class UserNotVerifiedException extends AbstractAuthException { +public final class UserNotVerifiedException extends AbstractAuthException { @Serial - private static final long serialVersionUID = 263502105581485335L; + private static final long serialVersionUID = -8766975383392137276L; public UserNotVerifiedException(String email) { super("user not verified yet! email: " + email); diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserPasswordNotValidException.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserPasswordNotValidException.java index 0f69b1f1..4f8d351b 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserPasswordNotValidException.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserPasswordNotValidException.java @@ -4,7 +4,7 @@ import java.io.Serial; -public class UserPasswordNotValidException extends AbstractAuthException { +public final class UserPasswordNotValidException extends AbstractAuthException { @Serial private static final long serialVersionUID = 359664997679732461L; diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserVerificationAlreadyCompletedException.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserVerificationAlreadyCompletedException.java index d1e03e0a..5a3c1b33 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserVerificationAlreadyCompletedException.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserVerificationAlreadyCompletedException.java @@ -2,12 +2,13 @@ import java.io.Serial; -public class UserVerificationAlreadyCompletedException extends RuntimeException { +public final class UserVerificationAlreadyCompletedException extends RuntimeException { @Serial - private static final long serialVersionUID = 3624833133483334337L; + private static final long serialVersionUID = 5017223706763359158L; public UserVerificationAlreadyCompletedException() { super("User verification is already completed!"); } + } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserVerificationIsNotFoundException.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserVerificationIsNotFoundException.java index 43a2a2b9..fd013ca3 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserVerificationIsNotFoundException.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/exception/UserVerificationIsNotFoundException.java @@ -2,13 +2,13 @@ import java.io.Serial; -public class UserVerificationIsNotFoundException extends RuntimeException { +public final class UserVerificationIsNotFoundException extends RuntimeException { + @Serial - private static final long serialVersionUID = 7045861607490841147L; + private static final long serialVersionUID = 3026197679369190902L; public UserVerificationIsNotFoundException(String id) { super("User Verification ID does not found! verificationId: " + id); } - } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/Identity.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/Identity.java index 418dcc39..f05fde9a 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/Identity.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/Identity.java @@ -1,5 +1,6 @@ package org.gelecekbilimde.scienceplatform.auth.model; +import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleName; import org.gelecekbilimde.scienceplatform.auth.model.enums.TokenClaims; import org.gelecekbilimde.scienceplatform.auth.util.BeanScope; import org.springframework.context.annotation.Scope; @@ -15,7 +16,14 @@ public class Identity { public String getUserId() { - return this.getJwt().getClaim("userId"); + return this.getJwt().getClaim(TokenClaims.USER_ID.getValue()); + } + + public boolean isAdmin() { + final RoleName roleName = RoleName.valueOf( + this.getJwt().getClaim(TokenClaims.USER_ROLE.getValue()) + ); + return RoleName.ADMIN == roleName; } public boolean hasPermission(String requiredPermission) { diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/settings/model/Settings.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/InvalidToken.java similarity index 50% rename from src/main/java/org/gelecekbilimde/scienceplatform/settings/model/Settings.java rename to src/main/java/org/gelecekbilimde/scienceplatform/auth/model/InvalidToken.java index fd266589..44bfd474 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/settings/model/Settings.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/InvalidToken.java @@ -1,4 +1,4 @@ -package org.gelecekbilimde.scienceplatform.settings.model; +package org.gelecekbilimde.scienceplatform.auth.model; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -10,13 +10,9 @@ @Setter @SuperBuilder @EqualsAndHashCode(callSuper = true) -public class Settings extends BaseDomainModel { +public class InvalidToken extends BaseDomainModel { - private Long settingsId; - private String groupName; - private String name; - private String definition; - private Long userId; - private boolean hidden; + private Long id; + private String tokenId; } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/Role.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/Role.java index 0a552592..c9a957c0 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/Role.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/Role.java @@ -17,4 +17,11 @@ public class Role { private RoleStatus status; private List permissions; + + public List getPermissionNames() { + return permissions.stream() + .map(PermissionEntity::getName) + .toList(); + } + } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleApplication.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleApplication.java index 56f3029d..9cbe77c5 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleApplication.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleApplication.java @@ -1,5 +1,6 @@ package org.gelecekbilimde.scienceplatform.auth.model; +import lombok.Builder; import lombok.Getter; import lombok.Setter; import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleApplicationStatus; @@ -7,6 +8,7 @@ @Getter @Setter +@Builder public class RoleApplication { private String id; @@ -14,4 +16,22 @@ public class RoleApplication { private Role role; private RoleApplicationStatus status; + + public boolean isConcluded() { + return this.status == RoleApplicationStatus.APPROVED || this.status == RoleApplicationStatus.REJECTED; + } + + + public void cancel() { + this.status = RoleApplicationStatus.CANCELLED; + } + + public void approve() { + this.status = RoleApplicationStatus.APPROVED; + } + + public void reject() { + this.status = RoleApplicationStatus.REJECTED; + } + } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleApplicationAbstractFilter.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleApplicationAbstractFilter.java new file mode 100644 index 00000000..32726423 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleApplicationAbstractFilter.java @@ -0,0 +1,39 @@ +package org.gelecekbilimde.scienceplatform.auth.model; + +import lombok.Getter; +import lombok.Setter; +import org.gelecekbilimde.scienceplatform.auth.model.entity.RoleApplicationEntity; +import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleApplicationStatus; +import org.gelecekbilimde.scienceplatform.common.model.BaseFilter; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.util.CollectionUtils; + +import java.util.Set; + +@Getter +@Setter +public class RoleApplicationAbstractFilter implements BaseFilter { + + protected Set statuses; + + + @Override + public Specification toSpecification() { + + Specification specification = Specification.where(null); + + if (!CollectionUtils.isEmpty(this.statuses)) { + + Specification statusSpecification = this.statuses.stream() + .map(status -> (Specification) (root, query, criteriaBuilder) -> + criteriaBuilder.equal(root.get("status"), status)) + .reduce(Specification::or) + .orElse(null); + + specification = specification.and(statusSpecification); + } + + return specification; + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleApplicationFilter.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleApplicationFilter.java index 42b614d9..41b56992 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleApplicationFilter.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleApplicationFilter.java @@ -2,38 +2,8 @@ import lombok.Getter; import lombok.Setter; -import org.gelecekbilimde.scienceplatform.auth.model.entity.RoleApplicationEntity; -import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleApplicationStatus; -import org.gelecekbilimde.scienceplatform.common.model.BaseFilter; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.util.CollectionUtils; - -import java.util.Set; @Getter @Setter -public class RoleApplicationFilter implements BaseFilter { - - private Set statuses; - - - @Override - public Specification toSpecification() { - - Specification specification = Specification.where(null); - - if (!CollectionUtils.isEmpty(this.statuses)) { - - Specification statusSpecification = this.statuses.stream() - .map(status -> (Specification) (root, query, criteriaBuilder) -> - criteriaBuilder.equal(root.get("status"), status)) - .reduce(Specification::or) - .orElse(null); - - specification = specification.and(statusSpecification); - } - - return specification; - } - +public class RoleApplicationFilter extends RoleApplicationAbstractFilter { } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleSelfApplicationFilter.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleSelfApplicationFilter.java index 9b671790..87e829d3 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleSelfApplicationFilter.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/RoleSelfApplicationFilter.java @@ -4,19 +4,14 @@ import lombok.Getter; import lombok.Setter; import org.gelecekbilimde.scienceplatform.auth.model.entity.RoleApplicationEntity; -import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleApplicationStatus; -import org.gelecekbilimde.scienceplatform.common.model.BaseFilter; import org.springframework.data.jpa.domain.Specification; import org.springframework.util.CollectionUtils; -import java.util.Set; - @Getter @Setter @Builder -public class RoleSelfApplicationFilter implements BaseFilter { +public class RoleSelfApplicationFilter extends RoleApplicationAbstractFilter { - private Set statuses; private User user; @Getter diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/entity/AuthorRequestEntity.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/entity/AuthorRequestEntity.java deleted file mode 100644 index 9869f889..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/entity/AuthorRequestEntity.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.gelecekbilimde.scienceplatform.auth.model.entity; - -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.experimental.SuperBuilder; -import org.gelecekbilimde.scienceplatform.auth.model.enums.Role; -import org.gelecekbilimde.scienceplatform.user.model.entity.UserEntity; - -@Data -@SuperBuilder -@NoArgsConstructor -@AllArgsConstructor -@Entity -@Table(name = "gb_author_request") -public class AuthorRequestEntity { - - @Id - @Column(name = "ID") - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne - private UserEntity user; - - private Role requestRoleName; - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/entity/RoleApplicationEntity.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/entity/RoleApplicationEntity.java index 806e329b..914fc2e9 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/entity/RoleApplicationEntity.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/entity/RoleApplicationEntity.java @@ -45,22 +45,4 @@ public class RoleApplicationEntity extends BaseEntity { @Column(name = "status") private RoleApplicationStatus status; - - public boolean isConcluded() { - return this.status == RoleApplicationStatus.APPROVED || this.status == RoleApplicationStatus.REJECTED; - } - - - public void cancel() { - this.status = RoleApplicationStatus.CANCELLED; - } - - public void approve() { - this.status = RoleApplicationStatus.APPROVED; - } - - public void reject() { - this.status = RoleApplicationStatus.REJECTED; - } - } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/entity/RoleEntity.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/entity/RoleEntity.java index 180720fa..4ef9a3f3 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/entity/RoleEntity.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/entity/RoleEntity.java @@ -16,6 +16,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleName; import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleStatus; import org.gelecekbilimde.scienceplatform.common.model.entity.BaseEntity; @@ -35,8 +36,9 @@ public class RoleEntity extends BaseEntity { @GeneratedValue(strategy = GenerationType.UUID) private String id; + @Enumerated(EnumType.STRING) @Column(name = "name") - private String name; + private RoleName name; @Column(name = "description") private String description; @@ -53,11 +55,4 @@ public class RoleEntity extends BaseEntity { ) private List permissions; - - public List getPermissionNames() { - return permissions.stream() - .map(PermissionEntity::getName) - .toList(); - } - } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/enums/Role.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/enums/Role.java deleted file mode 100644 index 5ae9dac5..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/enums/Role.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.gelecekbilimde.scienceplatform.auth.model.enums; - -public enum Role { - GUEST, - USER, - AUTHOR, - MODERATOR, - ADMIN -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/mapper/InvalidTokenToEntityMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/mapper/InvalidTokenToEntityMapper.java new file mode 100644 index 00000000..e6d15461 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/mapper/InvalidTokenToEntityMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.auth.model.mapper; + +import org.gelecekbilimde.scienceplatform.auth.model.InvalidToken; +import org.gelecekbilimde.scienceplatform.auth.model.entity.InvalidTokenEntity; +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface InvalidTokenToEntityMapper extends BaseMapper { + + static InvalidTokenToEntityMapper initialize() { + return Mappers.getMapper(InvalidTokenToEntityMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/mapper/RoleApplicationToEntityMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/mapper/RoleApplicationToEntityMapper.java new file mode 100644 index 00000000..3be6a13c --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/mapper/RoleApplicationToEntityMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.auth.model.mapper; + +import org.gelecekbilimde.scienceplatform.auth.model.RoleApplication; +import org.gelecekbilimde.scienceplatform.auth.model.entity.RoleApplicationEntity; +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface RoleApplicationToEntityMapper extends BaseMapper { + + static RoleApplicationToEntityMapper initialize() { + return Mappers.getMapper(RoleApplicationToEntityMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/mapper/RoleEntityToDomainMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/mapper/RoleEntityToDomainMapper.java new file mode 100644 index 00000000..41c3c4c2 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/mapper/RoleEntityToDomainMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.auth.model.mapper; + +import org.gelecekbilimde.scienceplatform.auth.model.Role; +import org.gelecekbilimde.scienceplatform.auth.model.entity.RoleEntity; +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface RoleEntityToDomainMapper extends BaseMapper { + + static RoleEntityToDomainMapper initialize() { + return Mappers.getMapper(RoleEntityToDomainMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/InvalidTokenReadPort.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/InvalidTokenReadPort.java new file mode 100644 index 00000000..e42b271d --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/InvalidTokenReadPort.java @@ -0,0 +1,7 @@ +package org.gelecekbilimde.scienceplatform.auth.port; + +public interface InvalidTokenReadPort { + + boolean existsByTokenId(String tokenId); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/InvalidTokenSavePort.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/InvalidTokenSavePort.java new file mode 100644 index 00000000..075f7971 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/InvalidTokenSavePort.java @@ -0,0 +1,11 @@ +package org.gelecekbilimde.scienceplatform.auth.port; + +import org.gelecekbilimde.scienceplatform.auth.model.InvalidToken; + +import java.util.List; + +public interface InvalidTokenSavePort { + + void saveAll(List invalidTokens); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/RoleApplicationReadPort.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/RoleApplicationReadPort.java new file mode 100644 index 00000000..1036e57f --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/RoleApplicationReadPort.java @@ -0,0 +1,21 @@ +package org.gelecekbilimde.scienceplatform.auth.port; + +import org.gelecekbilimde.scienceplatform.auth.model.RoleApplication; +import org.gelecekbilimde.scienceplatform.auth.model.RoleApplicationAbstractFilter; +import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleApplicationStatus; +import org.gelecekbilimde.scienceplatform.common.model.BasePage; +import org.gelecekbilimde.scienceplatform.common.model.BasePageable; + +import java.util.Optional; + +public interface RoleApplicationReadPort { + + BasePage findAll(BasePageable basePageable, RoleApplicationAbstractFilter filter); + + Optional findById(String id); + + Optional findByUserIdAndStatus(String userId, RoleApplicationStatus status); + + boolean existsByUserIdAndStatus(String userId, RoleApplicationStatus status); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/RoleApplicationSavePort.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/RoleApplicationSavePort.java new file mode 100644 index 00000000..e161d977 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/RoleApplicationSavePort.java @@ -0,0 +1,9 @@ +package org.gelecekbilimde.scienceplatform.auth.port; + +import org.gelecekbilimde.scienceplatform.auth.model.RoleApplication; + +public interface RoleApplicationSavePort { + + RoleApplication save(RoleApplication roleApplication); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/RoleReadPort.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/RoleReadPort.java new file mode 100644 index 00000000..5aa3976d --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/RoleReadPort.java @@ -0,0 +1,12 @@ +package org.gelecekbilimde.scienceplatform.auth.port; + +import org.gelecekbilimde.scienceplatform.auth.model.Role; +import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleName; + +import java.util.Optional; + +public interface RoleReadPort { + + Optional findByName(RoleName name); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/adapter/InvalidTokenAdapter.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/adapter/InvalidTokenAdapter.java new file mode 100644 index 00000000..ade7b24f --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/adapter/InvalidTokenAdapter.java @@ -0,0 +1,36 @@ +package org.gelecekbilimde.scienceplatform.auth.port.adapter; + +import lombok.RequiredArgsConstructor; +import org.gelecekbilimde.scienceplatform.auth.model.InvalidToken; +import org.gelecekbilimde.scienceplatform.auth.model.entity.InvalidTokenEntity; +import org.gelecekbilimde.scienceplatform.auth.model.mapper.InvalidTokenToEntityMapper; +import org.gelecekbilimde.scienceplatform.auth.port.InvalidTokenReadPort; +import org.gelecekbilimde.scienceplatform.auth.port.InvalidTokenSavePort; +import org.gelecekbilimde.scienceplatform.auth.repository.InvalidTokenRepository; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +@RequiredArgsConstructor +class InvalidTokenAdapter implements InvalidTokenReadPort, InvalidTokenSavePort { + + private final InvalidTokenRepository invalidTokenRepository; + + + private final InvalidTokenToEntityMapper invalidTokenToEntityMapper = InvalidTokenToEntityMapper.initialize(); + + + @Override + public boolean existsByTokenId(final String tokenId) { + return invalidTokenRepository.existsByTokenId(tokenId); + } + + + @Override + public void saveAll(final List invalidTokens) { + final List invalidTokenEntities = invalidTokenToEntityMapper.map(invalidTokens); + invalidTokenRepository.saveAll(invalidTokenEntities); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/adapter/RoleAdapter.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/adapter/RoleAdapter.java new file mode 100644 index 00000000..be21626e --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/adapter/RoleAdapter.java @@ -0,0 +1,29 @@ +package org.gelecekbilimde.scienceplatform.auth.port.adapter; + +import lombok.RequiredArgsConstructor; +import org.gelecekbilimde.scienceplatform.auth.model.Role; +import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleName; +import org.gelecekbilimde.scienceplatform.auth.model.mapper.RoleEntityToDomainMapper; +import org.gelecekbilimde.scienceplatform.auth.port.RoleReadPort; +import org.gelecekbilimde.scienceplatform.auth.repository.RoleRepository; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +@Component +@RequiredArgsConstructor +class RoleAdapter implements RoleReadPort { + + private final RoleRepository roleRepository; + + + private final RoleEntityToDomainMapper roleEntityToDomainMapper = RoleEntityToDomainMapper.initialize(); + + + @Override + public Optional findByName(RoleName name) { + return roleRepository.findByName(name) + .map(roleEntityToDomainMapper::map); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/adapter/RoleApplicationAdapter.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/adapter/RoleApplicationAdapter.java new file mode 100644 index 00000000..8e01abe7 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/port/adapter/RoleApplicationAdapter.java @@ -0,0 +1,90 @@ +package org.gelecekbilimde.scienceplatform.auth.port.adapter; + +import lombok.RequiredArgsConstructor; +import org.gelecekbilimde.scienceplatform.auth.model.RoleApplication; +import org.gelecekbilimde.scienceplatform.auth.model.RoleApplicationAbstractFilter; +import org.gelecekbilimde.scienceplatform.auth.model.entity.RoleApplicationEntity; +import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleApplicationStatus; +import org.gelecekbilimde.scienceplatform.auth.model.mapper.RoleApplicationEntityToDomainMapper; +import org.gelecekbilimde.scienceplatform.auth.model.mapper.RoleApplicationToEntityMapper; +import org.gelecekbilimde.scienceplatform.auth.port.RoleApplicationReadPort; +import org.gelecekbilimde.scienceplatform.auth.port.RoleApplicationSavePort; +import org.gelecekbilimde.scienceplatform.auth.repository.RoleApplicationRepository; +import org.gelecekbilimde.scienceplatform.common.model.BasePage; +import org.gelecekbilimde.scienceplatform.common.model.BasePageable; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Optional; + +@Component +@RequiredArgsConstructor +class RoleApplicationAdapter implements RoleApplicationReadPort, RoleApplicationSavePort { + + private final RoleApplicationRepository roleApplicationRepository; + + + private final RoleApplicationEntityToDomainMapper roleApplicationEntityToDomainMapper = RoleApplicationEntityToDomainMapper.initialize(); + private final RoleApplicationToEntityMapper roleApplicationToEntityMapper = RoleApplicationToEntityMapper.initialize(); + + + @Override + public BasePage findAll(final BasePageable basePageable, + final RoleApplicationAbstractFilter filter) { + + final Pageable pageable = basePageable.toPageable(); + + final Specification specification = Optional + .ofNullable(filter) + .map(RoleApplicationAbstractFilter::toSpecification) + .orElse(Specification.allOf()); + + final Page roleApplicationEntitiesPage = roleApplicationRepository + .findAll(specification, pageable); + + final List roleApplications = roleApplicationEntityToDomainMapper + .map(roleApplicationEntitiesPage.getContent()); + + return BasePage.of( + filter, + roleApplicationEntitiesPage, + roleApplications + ); + } + + + @Override + public Optional findById(final String id) { + return roleApplicationRepository.findById(id) + .map(roleApplicationEntityToDomainMapper::map); + } + + + @Override + public Optional findByUserIdAndStatus(final String userId, + final RoleApplicationStatus status) { + + return roleApplicationRepository.findByUserIdAndStatus(userId, status) + .map(roleApplicationEntityToDomainMapper::map); + } + + + @Override + public boolean existsByUserIdAndStatus(final String userId, + final RoleApplicationStatus status) { + + return roleApplicationRepository.existsByUserIdAndStatus(userId, status); + } + + + @Override + public RoleApplication save(final RoleApplication roleApplication) { + final RoleApplicationEntity roleApplicationEntity = roleApplicationToEntityMapper.map(roleApplication); + final RoleApplicationEntity savedRoleApplicationEntity = roleApplicationRepository.save(roleApplicationEntity); + return roleApplicationEntityToDomainMapper.map(savedRoleApplicationEntity); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/repository/AuthorRequestRepository.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/repository/AuthorRequestRepository.java deleted file mode 100644 index ebb18fcf..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/repository/AuthorRequestRepository.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.gelecekbilimde.scienceplatform.auth.repository; - -import org.gelecekbilimde.scienceplatform.auth.model.entity.AuthorRequestEntity; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface AuthorRequestRepository extends JpaRepository { - - Optional findByUserId(String id); - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/repository/InvalidTokenRepository.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/repository/InvalidTokenRepository.java index f22b7d5c..2dd3db8f 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/repository/InvalidTokenRepository.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/repository/InvalidTokenRepository.java @@ -3,10 +3,8 @@ import org.gelecekbilimde.scienceplatform.auth.model.entity.InvalidTokenEntity; import org.springframework.data.jpa.repository.JpaRepository; -import java.util.Optional; - public interface InvalidTokenRepository extends JpaRepository { - Optional findByTokenId(String tokenId); + boolean existsByTokenId(String tokenId); } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/repository/RoleRepository.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/repository/RoleRepository.java index 6ba28173..add577e8 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/repository/RoleRepository.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/repository/RoleRepository.java @@ -1,12 +1,13 @@ package org.gelecekbilimde.scienceplatform.auth.repository; import org.gelecekbilimde.scienceplatform.auth.model.entity.RoleEntity; +import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleName; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; public interface RoleRepository extends JpaRepository { - Optional findByName(String role); + Optional findByName(RoleName name); } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/AuthenticationServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/AuthenticationServiceImpl.java index 4a6e7c7f..4a854e5b 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/AuthenticationServiceImpl.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/AuthenticationServiceImpl.java @@ -9,15 +9,14 @@ import org.gelecekbilimde.scienceplatform.auth.exception.UserPasswordNotValidException; import org.gelecekbilimde.scienceplatform.auth.model.Identity; import org.gelecekbilimde.scienceplatform.auth.model.Token; -import org.gelecekbilimde.scienceplatform.auth.model.entity.RoleEntity; import org.gelecekbilimde.scienceplatform.auth.model.enums.TokenClaims; import org.gelecekbilimde.scienceplatform.auth.model.request.LoginRequest; import org.gelecekbilimde.scienceplatform.auth.model.request.RefreshRequest; import org.gelecekbilimde.scienceplatform.auth.service.AuthenticationService; import org.gelecekbilimde.scienceplatform.auth.service.InvalidTokenService; import org.gelecekbilimde.scienceplatform.auth.service.TokenService; -import org.gelecekbilimde.scienceplatform.user.model.entity.UserEntity; -import org.gelecekbilimde.scienceplatform.user.repository.UserRepository; +import org.gelecekbilimde.scienceplatform.user.model.User; +import org.gelecekbilimde.scienceplatform.user.port.UserReadPort; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; @@ -27,30 +26,32 @@ @RequiredArgsConstructor class AuthenticationServiceImpl implements AuthenticationService { - private final UserRepository userRepository; + private final UserReadPort userReadPort; private final PasswordEncoder passwordEncoder; private final TokenService tokenService; private final InvalidTokenService invalidTokenService; private final Identity identity; + @Override public Token login(LoginRequest request) { - UserEntity userEntity = userRepository.findByEmail(request.getEmail()) + User user = userReadPort.findByEmail(request.getEmail()) .orElseThrow(() -> new UserNotFoundByEmailException(request.getEmail())); - if (!userEntity.isVerified()) { + if (!user.isVerified()) { throw new UserNotVerifiedException(request.getEmail()); } - if (!passwordEncoder.matches(request.getPassword(), userEntity.getPassword())) { + if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) { throw new UserPasswordNotValidException(); } - final Claims claims = this.getClaimsBuilder(userEntity); + final Claims claims = this.generateClaims(user); return tokenService.generate(claims); } + @Override public Token refresh(RefreshRequest refreshRequest) { @@ -58,28 +59,27 @@ public Token refresh(RefreshRequest refreshRequest) { final Claims payload = tokenService.getPayload(refreshToken); final String email = payload.get(TokenClaims.USER_MAIL.getValue(), String.class); - final UserEntity userEntity = this.userRepository.findByEmail(email) + final User user = userReadPort.findByEmail(email) .orElseThrow(() -> new UserNotFoundByEmailException(email)); - final Claims claims = this.getClaimsBuilder(userEntity); + final Claims claims = this.generateClaims(user); return tokenService.generate(claims, refreshToken); } - private Claims getClaimsBuilder(UserEntity userEntity) { - RoleEntity role = userEntity.getRole(); - + private Claims generateClaims(User user) { final ClaimsBuilder claimsBuilder = Jwts.claims(); - claimsBuilder.add(TokenClaims.USER_ID.getValue(), userEntity.getId()); - claimsBuilder.add(TokenClaims.USER_FIRST_NAME.getValue(), userEntity.getFirstName()); - claimsBuilder.add(TokenClaims.USER_LAST_NAME.getValue(), userEntity.getLastName()); - claimsBuilder.add(TokenClaims.USER_STATUS.getValue(), userEntity.getStatus()); - claimsBuilder.add(TokenClaims.USER_MAIL.getValue(), userEntity.getEmail()); - claimsBuilder.add(TokenClaims.USER_ROLE.getValue(), role.getName()); - claimsBuilder.add(TokenClaims.USER_PERMISSIONS.getValue(), role.getPermissionNames()); + claimsBuilder.add(TokenClaims.USER_ID.getValue(), user.getId()); + claimsBuilder.add(TokenClaims.USER_FIRST_NAME.getValue(), user.getFirstName()); + claimsBuilder.add(TokenClaims.USER_LAST_NAME.getValue(), user.getLastName()); + claimsBuilder.add(TokenClaims.USER_STATUS.getValue(), user.getStatus()); + claimsBuilder.add(TokenClaims.USER_MAIL.getValue(), user.getEmail()); + claimsBuilder.add(TokenClaims.USER_ROLE.getValue(), user.getRole().getName()); + claimsBuilder.add(TokenClaims.USER_PERMISSIONS.getValue(), user.getRole().getPermissionNames()); return claimsBuilder.build(); } + @Override public void logout(String refreshToken) { @@ -89,4 +89,5 @@ public void logout(String refreshToken) { final List invalidTokenIds = List.of(refreshTokenId, tokenId); invalidTokenService.saveAll(invalidTokenIds); } + } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/InvalidTokenServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/InvalidTokenServiceImpl.java index 04197bbc..de7fa7d3 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/InvalidTokenServiceImpl.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/InvalidTokenServiceImpl.java @@ -2,8 +2,9 @@ import lombok.RequiredArgsConstructor; import org.gelecekbilimde.scienceplatform.auth.exception.TokenNotValidException; -import org.gelecekbilimde.scienceplatform.auth.model.entity.InvalidTokenEntity; -import org.gelecekbilimde.scienceplatform.auth.repository.InvalidTokenRepository; +import org.gelecekbilimde.scienceplatform.auth.model.InvalidToken; +import org.gelecekbilimde.scienceplatform.auth.port.InvalidTokenReadPort; +import org.gelecekbilimde.scienceplatform.auth.port.InvalidTokenSavePort; import org.gelecekbilimde.scienceplatform.auth.service.InvalidTokenService; import org.springframework.stereotype.Service; @@ -14,20 +15,25 @@ @RequiredArgsConstructor class InvalidTokenServiceImpl implements InvalidTokenService { - private final InvalidTokenRepository invalidTokenRepository; + private final InvalidTokenReadPort invalidTokenReadPort; + private final InvalidTokenSavePort invalidTokenSavePort; public void checkForInvalidityOfToken(final String tokenId) { - final boolean isTokenInvalid = invalidTokenRepository.findByTokenId(tokenId).isPresent(); + + final boolean isTokenInvalid = invalidTokenReadPort.existsByTokenId(tokenId); + if (isTokenInvalid) { throw new TokenNotValidException(); } } public void saveAll(List invalidTokenIds) { - List invalidTokenEntities = invalidTokenIds.stream() - .map(invalidTokenId -> InvalidTokenEntity.builder().tokenId(invalidTokenId).build()) - .collect(Collectors.toUnmodifiableList()); - invalidTokenRepository.saveAll(invalidTokenEntities); + + final List invalidTokens = invalidTokenIds.stream() + .map(invalidTokenId -> InvalidToken.builder().tokenId(invalidTokenId).build()) + .collect(Collectors.toList()); + + invalidTokenSavePort.saveAll(invalidTokens); } } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/RegistrationServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/RegistrationServiceImpl.java index 7549dc68..89663df3 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/RegistrationServiceImpl.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/RegistrationServiceImpl.java @@ -1,52 +1,54 @@ package org.gelecekbilimde.scienceplatform.auth.service.impl; import lombok.RequiredArgsConstructor; -import org.gelecekbilimde.scienceplatform.auth.exception.AlreadyRegisteredException; import org.gelecekbilimde.scienceplatform.auth.exception.RoleNotFoundByNameException; +import org.gelecekbilimde.scienceplatform.auth.exception.UserAlreadyRegisteredException; import org.gelecekbilimde.scienceplatform.auth.exception.UserNotFoundByIdException; import org.gelecekbilimde.scienceplatform.auth.exception.UserVerificationAlreadyCompletedException; import org.gelecekbilimde.scienceplatform.auth.exception.UserVerificationIsNotFoundException; -import org.gelecekbilimde.scienceplatform.auth.model.entity.RoleEntity; +import org.gelecekbilimde.scienceplatform.auth.model.Role; import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleName; import org.gelecekbilimde.scienceplatform.auth.model.request.RegisterRequest; import org.gelecekbilimde.scienceplatform.auth.model.request.VerifyRequest; -import org.gelecekbilimde.scienceplatform.auth.repository.RoleRepository; +import org.gelecekbilimde.scienceplatform.auth.port.RoleReadPort; import org.gelecekbilimde.scienceplatform.auth.service.RegistrationService; -import org.gelecekbilimde.scienceplatform.user.model.entity.UserEntity; -import org.gelecekbilimde.scienceplatform.user.model.entity.UserVerificationEntity; +import org.gelecekbilimde.scienceplatform.user.model.User; +import org.gelecekbilimde.scienceplatform.user.model.UserVerification; import org.gelecekbilimde.scienceplatform.user.model.enums.UserStatus; import org.gelecekbilimde.scienceplatform.user.model.enums.UserVerificationStatus; -import org.gelecekbilimde.scienceplatform.user.repository.UserRepository; -import org.gelecekbilimde.scienceplatform.user.repository.UserVerificationRepository; +import org.gelecekbilimde.scienceplatform.user.port.UserReadPort; +import org.gelecekbilimde.scienceplatform.user.port.UserSavePort; +import org.gelecekbilimde.scienceplatform.user.port.UserVerificationReadPort; +import org.gelecekbilimde.scienceplatform.user.port.UserVerificationSavePort; import org.gelecekbilimde.scienceplatform.user.service.UserEmailService; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.concurrent.CompletableFuture; - @Service @RequiredArgsConstructor class RegistrationServiceImpl implements RegistrationService { - private final UserRepository userRepository; + private final UserReadPort userReadPort; + private final UserSavePort userSavePort; + private final RoleReadPort roleReadPort; private final PasswordEncoder passwordEncoder; - private final RoleRepository roleRepository; private final UserEmailService userEmailService; - private final UserVerificationRepository userVerificationRepository; + private final UserVerificationReadPort userVerificationReadPort; + private final UserVerificationSavePort userVerificationSavePort; @Override @Transactional public void register(RegisterRequest request) { - if (userRepository.existsByEmail(request.getEmail())) { - throw new AlreadyRegisteredException(request.getEmail()); + if (userReadPort.existsByEmail(request.getEmail())) { + throw new UserAlreadyRegisteredException(request.getEmail()); } - RoleEntity role = roleRepository.findByName(RoleName.USER.name()) + Role role = roleReadPort.findByName(RoleName.USER) .orElseThrow(() -> new RoleNotFoundByNameException(RoleName.USER.name())); - UserEntity user = UserEntity.builder() + User user = User.builder() .firstName(request.getFirstname()) .lastName(request.getLastname()) .email(request.getEmail()) @@ -59,40 +61,40 @@ public void register(RegisterRequest request) { .password(passwordEncoder.encode(request.getPassword())) .build(); - UserEntity savedUser = userRepository.save(user); + User savedUser = userSavePort.save(user); - UserVerificationEntity userVerificationEntity = UserVerificationEntity.builder() - .userId(savedUser.getId()) + UserVerification userVerification = UserVerification.builder() + .user(savedUser) .status(UserVerificationStatus.WAITING) .build(); - userVerificationRepository.save(userVerificationEntity); + userVerificationSavePort.save(userVerification); - CompletableFuture.runAsync(() -> userEmailService.sendVerifyMessage(savedUser.getEmail(), userVerificationEntity.getId())); + userEmailService.sendVerification(savedUser.getEmail(), userVerification.getId()); } @Override @Transactional public void verify(VerifyRequest verifyRequest) { - UserVerificationEntity userVerificationEntity = userVerificationRepository + UserVerification userVerification = userVerificationReadPort .findById(verifyRequest.getVerificationId()) .orElseThrow(() -> new UserVerificationIsNotFoundException(verifyRequest.getVerificationId())); - if (userVerificationEntity.isCompleted()) { + if (userVerification.isCompleted()) { throw new UserVerificationAlreadyCompletedException(); } - userVerificationEntity.complete(); - userVerificationRepository.save(userVerificationEntity); + userVerification.complete(); + userVerificationSavePort.save(userVerification); - UserEntity userEntity = userRepository.findById(userVerificationEntity.getUserId()) - .orElseThrow(() -> new UserNotFoundByIdException(userVerificationEntity.getUserId())); + User user = userReadPort.findById(userVerification.getUser().getId()) + .orElseThrow(() -> new UserNotFoundByIdException(userVerification.getUser().getId())); - userEntity.verify(); - userRepository.save(userEntity); + user.verify(); + userSavePort.save(user); - CompletableFuture.runAsync(() -> userEmailService.sendWelcomeMessage(userEntity.getEmail())); + userEmailService.sendWelcome(user.getEmail()); } } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/RoleApplicationServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/RoleApplicationServiceImpl.java index df2ffb77..312b3194 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/RoleApplicationServiceImpl.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/RoleApplicationServiceImpl.java @@ -4,84 +4,56 @@ import org.gelecekbilimde.scienceplatform.auth.exception.RoleApplicationAlreadyConcludedException; import org.gelecekbilimde.scienceplatform.auth.exception.RoleApplicationNotFoundByIdException; import org.gelecekbilimde.scienceplatform.auth.model.RoleApplication; -import org.gelecekbilimde.scienceplatform.auth.model.RoleApplicationFilter; -import org.gelecekbilimde.scienceplatform.auth.model.entity.RoleApplicationEntity; -import org.gelecekbilimde.scienceplatform.auth.model.mapper.RoleApplicationEntityToDomainMapper; import org.gelecekbilimde.scienceplatform.auth.model.request.RoleApplicationListRequest; -import org.gelecekbilimde.scienceplatform.auth.repository.RoleApplicationRepository; +import org.gelecekbilimde.scienceplatform.auth.port.RoleApplicationReadPort; +import org.gelecekbilimde.scienceplatform.auth.port.RoleApplicationSavePort; import org.gelecekbilimde.scienceplatform.auth.service.RoleApplicationService; import org.gelecekbilimde.scienceplatform.common.model.BasePage; -import org.gelecekbilimde.scienceplatform.user.model.entity.UserEntity; -import org.gelecekbilimde.scienceplatform.user.repository.UserRepository; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; +import org.gelecekbilimde.scienceplatform.user.model.User; +import org.gelecekbilimde.scienceplatform.user.port.UserSavePort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; -import java.util.Optional; - @Service @RequiredArgsConstructor class RoleApplicationServiceImpl implements RoleApplicationService { - private final UserRepository userRepository; - private final RoleApplicationRepository roleApplicationRepository; - - - private final RoleApplicationEntityToDomainMapper roleApplicationEntityToDomainMapper = RoleApplicationEntityToDomainMapper.initialize(); + private final RoleApplicationReadPort roleApplicationReadPort; + private final RoleApplicationSavePort roleApplicationSavePort; + private final UserSavePort userSavePort; @Override public BasePage findAll(final RoleApplicationListRequest listRequest) { - - final Pageable pageable = listRequest.getPageable().toPageable(); - - final RoleApplicationFilter filter = listRequest.getFilter(); - - final Specification specification = Optional - .ofNullable(filter) - .map(RoleApplicationFilter::toSpecification) - .orElse(Specification.allOf()); - - final Page roleApplicationEntitiesPage = roleApplicationRepository - .findAll(specification, pageable); - - final List roleApplications = roleApplicationEntityToDomainMapper - .map(roleApplicationEntitiesPage.getContent()); - - return BasePage.of( - filter, - roleApplicationEntitiesPage, - roleApplications - ); + return roleApplicationReadPort + .findAll(listRequest.getPageable(), listRequest.getFilter()); } + @Override @Transactional public void approve(final String id) { - RoleApplicationEntity application = roleApplicationRepository.findById(id) + RoleApplication application = roleApplicationReadPort.findById(id) .orElseThrow(() -> new RoleApplicationNotFoundByIdException(id)); if (application.isConcluded()) { throw new RoleApplicationAlreadyConcludedException(id); } - UserEntity user = application.getUser(); + User user = application.getUser(); user.setRole(application.getRole()); - userRepository.save(user); + userSavePort.save(user); application.approve(); - roleApplicationRepository.save(application); + roleApplicationSavePort.save(application); } @Override public void reject(final String id) { - RoleApplicationEntity application = roleApplicationRepository.findById(id) + RoleApplication application = roleApplicationReadPort.findById(id) .orElseThrow(() -> new RoleApplicationNotFoundByIdException(id)); if (application.isConcluded()) { @@ -89,7 +61,7 @@ public void reject(final String id) { } application.reject(); - roleApplicationRepository.save(application); + roleApplicationSavePort.save(application); } } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/RoleSelfApplicationServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/RoleSelfApplicationServiceImpl.java index a782211d..d5f67c16 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/RoleSelfApplicationServiceImpl.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/service/impl/RoleSelfApplicationServiceImpl.java @@ -5,44 +5,35 @@ import org.gelecekbilimde.scienceplatform.auth.exception.RoleApplicationNotFoundByUserIdAndStatusException; import org.gelecekbilimde.scienceplatform.auth.exception.RoleNotFoundByNameException; import org.gelecekbilimde.scienceplatform.auth.model.Identity; +import org.gelecekbilimde.scienceplatform.auth.model.Role; import org.gelecekbilimde.scienceplatform.auth.model.RoleApplication; import org.gelecekbilimde.scienceplatform.auth.model.RoleSelfApplicationFilter; -import org.gelecekbilimde.scienceplatform.auth.model.entity.RoleApplicationEntity; -import org.gelecekbilimde.scienceplatform.auth.model.entity.RoleEntity; import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleApplicationStatus; import org.gelecekbilimde.scienceplatform.auth.model.enums.RoleName; -import org.gelecekbilimde.scienceplatform.auth.model.mapper.RoleApplicationEntityToDomainMapper; import org.gelecekbilimde.scienceplatform.auth.model.request.RoleSelfApplicationListRequest; -import org.gelecekbilimde.scienceplatform.auth.repository.RoleApplicationRepository; -import org.gelecekbilimde.scienceplatform.auth.repository.RoleRepository; +import org.gelecekbilimde.scienceplatform.auth.port.RoleApplicationReadPort; +import org.gelecekbilimde.scienceplatform.auth.port.RoleApplicationSavePort; +import org.gelecekbilimde.scienceplatform.auth.port.RoleReadPort; import org.gelecekbilimde.scienceplatform.auth.service.RoleSelfApplicationService; import org.gelecekbilimde.scienceplatform.common.model.BasePage; -import org.gelecekbilimde.scienceplatform.user.model.entity.UserEntity; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; +import org.gelecekbilimde.scienceplatform.user.model.User; import org.springframework.stereotype.Service; -import java.util.List; import java.util.Optional; @Service @RequiredArgsConstructor class RoleSelfApplicationServiceImpl implements RoleSelfApplicationService { - private final RoleApplicationRepository roleApplicationRepository; - private final RoleRepository roleRepository; + private final RoleApplicationReadPort roleApplicationReadPort; + private final RoleApplicationSavePort roleApplicationSavePort; + private final RoleReadPort roleReadPort; private final Identity identity; - private final RoleApplicationEntityToDomainMapper roleApplicationEntityToDomainMapper = RoleApplicationEntityToDomainMapper.initialize(); - - @Override public BasePage findAll(final RoleSelfApplicationListRequest listRequest) { - final Pageable pageable = listRequest.getPageable().toPageable(); - Optional.ofNullable(listRequest.getFilter()) .ifPresentOrElse( filter -> filter.addUserId(identity.getUserId()), @@ -53,60 +44,45 @@ public BasePage findAll(final RoleSelfApplicationListRequest li } ); - final Specification specification = Optional - .ofNullable(listRequest.getFilter()) - .map(RoleSelfApplicationFilter::toSpecification) - .orElse(Specification.allOf()); - - final Page roleApplicationEntitiesPage = roleApplicationRepository - .findAll(specification, pageable); - - final List roleApplications = roleApplicationEntityToDomainMapper - .map(roleApplicationEntitiesPage.getContent()); - - return BasePage.of( - listRequest.getFilter(), - roleApplicationEntitiesPage, - roleApplications - ); + return roleApplicationReadPort.findAll(listRequest.getPageable(), listRequest.getFilter()); } + @Override public void createAuthorApplication() { this.createApplication(RoleName.AUTHOR); } - @Override public void createModeratorApplication() { this.createApplication(RoleName.MODERATOR); } - private void createApplication(final RoleName roleName) { - boolean existAnyApplicationInReview = roleApplicationRepository + boolean existAnyApplicationInReview = roleApplicationReadPort .existsByUserIdAndStatus(identity.getUserId(), RoleApplicationStatus.IN_REVIEW); if (existAnyApplicationInReview) { throw new RoleApplicationAlreadyExistException(); } - final RoleEntity role = roleRepository.findByName(roleName.name()) + final Role role = roleReadPort.findByName(roleName) .orElseThrow(() -> new RoleNotFoundByNameException(roleName.name())); - final RoleApplicationEntity application = RoleApplicationEntity.builder() - .user(UserEntity.builder().id(identity.getUserId()).build()) + final RoleApplication application = RoleApplication.builder() + .user(User.builder().id(identity.getUserId()).build()) .role(role) .status(RoleApplicationStatus.IN_REVIEW) .build(); - roleApplicationRepository.save(application); + + roleApplicationSavePort.save(application); } @Override public void cancel() { - final RoleApplicationEntity application = roleApplicationRepository + final RoleApplication application = roleApplicationReadPort .findByUserIdAndStatus(identity.getUserId(), RoleApplicationStatus.IN_REVIEW) .orElseThrow(() -> new RoleApplicationNotFoundByUserIdAndStatusException( identity.getUserId(), @@ -115,7 +91,7 @@ public void cancel() { ); application.cancel(); - roleApplicationRepository.save(application); + roleApplicationSavePort.save(application); } } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/util/AuthKeyPairUtil.java b/src/main/java/org/gelecekbilimde/scienceplatform/auth/util/AuthKeyPairUtil.java index c6b1239a..b6fd2a0c 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/auth/util/AuthKeyPairUtil.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/auth/util/AuthKeyPairUtil.java @@ -1,7 +1,6 @@ package org.gelecekbilimde.scienceplatform.auth.util; import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.openssl.PEMParser; @@ -18,7 +17,6 @@ import java.security.PrivateKey; import java.security.PublicKey; -@Slf4j @UtilityClass public class AuthKeyPairUtil { diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/common/mail/model/request/EmailSendRequest.java b/src/main/java/org/gelecekbilimde/scienceplatform/common/mail/model/request/EmailSendRequest.java deleted file mode 100644 index 3a8c96fe..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/common/mail/model/request/EmailSendRequest.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.gelecekbilimde.scienceplatform.common.mail.model.request; - -import lombok.Builder; -import lombok.Getter; - -import java.util.HashMap; -import java.util.Map; - -@Getter -@Builder -public class EmailSendRequest { - private String to; - private String templateFileName; - @Builder.Default - private Map templateVariables = new HashMap<>(); -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/common/mail/service/EmailService.java b/src/main/java/org/gelecekbilimde/scienceplatform/common/mail/service/EmailService.java deleted file mode 100644 index 1ec2d0a3..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/common/mail/service/EmailService.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.gelecekbilimde.scienceplatform.common.mail.service; - -import org.gelecekbilimde.scienceplatform.common.mail.model.request.EmailSendRequest; - -public interface EmailService { - - void send(EmailSendRequest sendRequest); - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/common/mail/service/impl/EmailServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/common/mail/service/impl/EmailServiceImpl.java deleted file mode 100644 index b243cb95..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/common/mail/service/impl/EmailServiceImpl.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.gelecekbilimde.scienceplatform.common.mail.service.impl; - -import jakarta.mail.internet.MimeMessage; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.gelecekbilimde.scienceplatform.common.mail.model.request.EmailSendRequest; -import org.gelecekbilimde.scienceplatform.common.mail.service.EmailService; -import org.springframework.core.io.ClassPathResource; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.MimeMessageHelper; -import org.springframework.stereotype.Service; -import org.springframework.util.FileCopyUtils; - -import java.io.IOException; -import java.util.Map; - -@Slf4j -@Service -@RequiredArgsConstructor -class EmailServiceImpl implements EmailService { - - private final JavaMailSender javaMailSender; - - @Override - public void send(EmailSendRequest sendRequest) { - - try { - MimeMessage mimeMessage = javaMailSender.createMimeMessage(); - MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, "utf-8"); - - mimeMessageHelper.setTo(sendRequest.getTo()); - String emailContent = this.generateEmailContent( - sendRequest.getTemplateFileName(), - sendRequest.getTemplateVariables() - ); - mimeMessageHelper.setSubject(this.getSubject(emailContent)); - mimeMessageHelper.setText(emailContent, true); - - javaMailSender.send(mimeMessage); - } catch (Exception exception) { - log.error("Error while sending email: {}", sendRequest.getTo(), exception); - } - - } - - private String generateEmailContent(String templateName, Map templateVariables) throws IOException { - ClassPathResource htmlTemplate = new ClassPathResource("static/mailtemplate/".concat(templateName)); - byte[] htmlBytes = FileCopyUtils.copyToByteArray(htmlTemplate.getInputStream()); - String emailContent = new String(htmlBytes); - - for (Map.Entry entry : templateVariables.entrySet()) { - emailContent = emailContent.replace("${".concat(entry.getKey()).concat("}"), entry.getValue()); - } - return emailContent; - } - - private String getSubject(String emailContent) { - return emailContent.split("")[1].split("")[0]; - } - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/common/model/BaseSort.java b/src/main/java/org/gelecekbilimde/scienceplatform/common/model/BaseSort.java index 52ea5f50..04e21113 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/common/model/BaseSort.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/common/model/BaseSort.java @@ -3,7 +3,11 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; 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.SuperBuilder; import org.springframework.data.domain.Sort; diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/common/model/enums/MailTemplate.java b/src/main/java/org/gelecekbilimde/scienceplatform/common/model/enums/MailTemplate.java new file mode 100644 index 00000000..59a22611 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/common/model/enums/MailTemplate.java @@ -0,0 +1,15 @@ +package org.gelecekbilimde.scienceplatform.common.model.enums; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum MailTemplate { + + USER_VERIFICATION("user-verification.html"), + USER_WELCOME("user-welcome.html"); + + private final String file; + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/common/model/request/MailSendRequest.java b/src/main/java/org/gelecekbilimde/scienceplatform/common/model/request/MailSendRequest.java new file mode 100644 index 00000000..8bc66300 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/common/model/request/MailSendRequest.java @@ -0,0 +1,20 @@ +package org.gelecekbilimde.scienceplatform.common.model.request; + +import lombok.Builder; +import lombok.Getter; +import org.gelecekbilimde.scienceplatform.common.model.enums.MailTemplate; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Getter +@Builder +public class MailSendRequest { + + private List to; + private MailTemplate template; + @Builder.Default + private Map parameters = new HashMap<>(); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/common/model/response/SuccessResponse.java b/src/main/java/org/gelecekbilimde/scienceplatform/common/model/response/SuccessResponse.java index c74f4fad..3590df46 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/common/model/response/SuccessResponse.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/common/model/response/SuccessResponse.java @@ -21,7 +21,7 @@ public class SuccessResponse { private final Boolean isSuccess = true; @JsonInclude(JsonInclude.Include.NON_NULL) - private T content; + private T result; public static SuccessResponse success() { @@ -31,7 +31,7 @@ public static SuccessResponse success() { public static SuccessResponse success(final T content) { return SuccessResponse.builder() - .content(content) + .result(content) .build(); } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/common/service/MailService.java b/src/main/java/org/gelecekbilimde/scienceplatform/common/service/MailService.java new file mode 100644 index 00000000..b755c5a4 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/common/service/MailService.java @@ -0,0 +1,9 @@ +package org.gelecekbilimde.scienceplatform.common.service; + +import org.gelecekbilimde.scienceplatform.common.model.request.MailSendRequest; + +public interface MailService { + + void send(MailSendRequest sendRequest); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/common/service/impl/MailServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/common/service/impl/MailServiceImpl.java new file mode 100644 index 00000000..6e8ba377 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/common/service/impl/MailServiceImpl.java @@ -0,0 +1,95 @@ +package org.gelecekbilimde.scienceplatform.common.service.impl; + +import jakarta.mail.Message; +import jakarta.mail.MessagingException; +import jakarta.mail.internet.InternetAddress; +import jakarta.mail.internet.MimeMessage; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.gelecekbilimde.scienceplatform.common.model.enums.MailTemplate; +import org.gelecekbilimde.scienceplatform.common.model.request.MailSendRequest; +import org.gelecekbilimde.scienceplatform.common.service.MailService; +import org.springframework.core.io.ClassPathResource; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Service; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.context.request.async.AsyncRequestTimeoutException; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Service +@RequiredArgsConstructor +class MailServiceImpl implements MailService { + + private final JavaMailSender mailSender; + + @Override + public void send(MailSendRequest sendRequest) { + + CompletableFuture.runAsync(() -> this.sendEmail(sendRequest)) + .orTimeout(5, TimeUnit.SECONDS) + .exceptionally(throwable -> { + log.warn("Mail not sent to {} in 5 seconds with {} template", sendRequest.getTo(), sendRequest.getTemplate()); + throw new AsyncRequestTimeoutException(); + }); + + } + + private void sendEmail(final MailSendRequest sendRequest) { + try { + + MimeMessage mimeMessage = this.createMimeMessage(sendRequest); + + mailSender.send(mimeMessage); + + log.trace("Mail sent to {} with {} template", sendRequest.getTo(), sendRequest.getTemplate()); + + } catch (Exception exception) { + log.error("Received error while sending mail to {} with {} template", sendRequest.getTo(), sendRequest.getTemplate(), exception); + } + } + + private MimeMessage createMimeMessage(final MailSendRequest sendRequest) throws IOException, MessagingException { + + MimeMessage mimeMessage = mailSender.createMimeMessage(); + + String htmlContent = this.findTemplate(sendRequest.getTemplate()); + + String title = this.findTitle(htmlContent); + mimeMessage.setSubject(title); + + String htmlContentWithParameters = this.addParameters(htmlContent, sendRequest.getParameters()); + mimeMessage.setText(htmlContentWithParameters, "UTF-8", "html"); + + mimeMessage.setFrom(new InternetAddress("smtp@gelecekbilimde.net", "Gelecek Bilimde")); + + for (String to : sendRequest.getTo()) { + mimeMessage.addRecipients(Message.RecipientType.TO, to); + } + return mimeMessage; + } + + private String findTemplate(MailTemplate template) throws IOException { + ClassPathResource resource = new ClassPathResource("static/mail/template/" + template.getFile()); + byte[] binaryData = FileCopyUtils.copyToByteArray(resource.getInputStream()); + return new String(binaryData, StandardCharsets.UTF_8); + } + + private String findTitle(String htmlContent) { + return htmlContent.split("")[1].split("")[0]; + } + + private String addParameters(String htmlContent, Map parameters) { + String template = htmlContent; + for (Map.Entry parameter : parameters.entrySet()) { + template = template.replace("{" + parameter.getKey() + "}", parameter.getValue().toString()); + } + return template; + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/common/util/FileUtil.java b/src/main/java/org/gelecekbilimde/scienceplatform/common/util/FileUtil.java index 08f6d02d..4f88d2e3 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/common/util/FileUtil.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/common/util/FileUtil.java @@ -1,7 +1,6 @@ package org.gelecekbilimde.scienceplatform.common.util; import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; import org.gelecekbilimde.scienceplatform.common.exception.FileReadException; import java.io.IOException; @@ -9,7 +8,6 @@ import java.nio.file.Path; import java.nio.file.Paths; -@Slf4j @UtilityClass public class FileUtil { diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/notification/exception/LastYouTubeVideoNotFoundException.java b/src/main/java/org/gelecekbilimde/scienceplatform/notification/exception/LastYouTubeVideoNotFoundException.java index 56e7293f..8f49011a 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/notification/exception/LastYouTubeVideoNotFoundException.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/notification/exception/LastYouTubeVideoNotFoundException.java @@ -2,9 +2,13 @@ import java.io.Serial; -public class LastYouTubeVideoNotFoundException extends RuntimeException { +public final class LastYouTubeVideoNotFoundException extends RuntimeException { @Serial - private static final long serialVersionUID = -5775337541044176644L; + private static final long serialVersionUID = 3026069869731133992L; + + public LastYouTubeVideoNotFoundException(Throwable cause) { + super("last YouTube video not found!", cause); + } } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/notification/model/NotificationToken.java b/src/main/java/org/gelecekbilimde/scienceplatform/notification/model/NotificationToken.java new file mode 100644 index 00000000..fc9b1d03 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/notification/model/NotificationToken.java @@ -0,0 +1,20 @@ +package org.gelecekbilimde.scienceplatform.notification.model; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.SuperBuilder; +import org.gelecekbilimde.scienceplatform.common.model.BaseDomainModel; + +@Getter +@Setter +@SuperBuilder +@EqualsAndHashCode(callSuper = true) +public class NotificationToken extends BaseDomainModel { + + private Long id; + private String userId; + private String deviceId; + private String deviceToken; + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/notification/model/mapper/NotificationTokenEntityToDomainMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/notification/model/mapper/NotificationTokenEntityToDomainMapper.java new file mode 100644 index 00000000..393b2bc8 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/notification/model/mapper/NotificationTokenEntityToDomainMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.notification.model.mapper; + +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.gelecekbilimde.scienceplatform.notification.model.NotificationToken; +import org.gelecekbilimde.scienceplatform.notification.model.entity.NotificationTokenEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface NotificationTokenEntityToDomainMapper extends BaseMapper { + + static NotificationTokenEntityToDomainMapper initialize() { + return Mappers.getMapper(NotificationTokenEntityToDomainMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/notification/port/NotificationTokenReadPort.java b/src/main/java/org/gelecekbilimde/scienceplatform/notification/port/NotificationTokenReadPort.java new file mode 100644 index 00000000..eedf3baa --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/notification/port/NotificationTokenReadPort.java @@ -0,0 +1,11 @@ +package org.gelecekbilimde.scienceplatform.notification.port; + +import org.gelecekbilimde.scienceplatform.notification.model.NotificationToken; + +import java.util.List; + +public interface NotificationTokenReadPort { + + List findAllByUserId(String userId); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/notification/port/adapter/NotificationTokenAdapter.java b/src/main/java/org/gelecekbilimde/scienceplatform/notification/port/adapter/NotificationTokenAdapter.java new file mode 100644 index 00000000..6877c06a --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/notification/port/adapter/NotificationTokenAdapter.java @@ -0,0 +1,30 @@ +package org.gelecekbilimde.scienceplatform.notification.port.adapter; + +import lombok.RequiredArgsConstructor; +import org.gelecekbilimde.scienceplatform.notification.model.NotificationToken; +import org.gelecekbilimde.scienceplatform.notification.model.entity.NotificationTokenEntity; +import org.gelecekbilimde.scienceplatform.notification.model.mapper.NotificationTokenEntityToDomainMapper; +import org.gelecekbilimde.scienceplatform.notification.port.NotificationTokenReadPort; +import org.gelecekbilimde.scienceplatform.notification.repository.NotificationTokenRepository; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +@RequiredArgsConstructor +class NotificationTokenAdapter implements NotificationTokenReadPort { + + private final NotificationTokenRepository notificationTokenRepository; + + + private final NotificationTokenEntityToDomainMapper notificationTokenEntityToDomainMapper = NotificationTokenEntityToDomainMapper.initialize(); + + + @Override + public List findAllByUserId(final String userId) { + final List notificationTokenEntities = notificationTokenRepository + .findAllByUserId(userId); + return notificationTokenEntityToDomainMapper.map(notificationTokenEntities); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/notification/scheduler/YoutubeNotificationScheduler.java b/src/main/java/org/gelecekbilimde/scienceplatform/notification/scheduler/YoutubeNotificationScheduler.java index beb5abc4..6c21a9bf 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/notification/scheduler/YoutubeNotificationScheduler.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/notification/scheduler/YoutubeNotificationScheduler.java @@ -22,17 +22,16 @@ @RequiredArgsConstructor class YoutubeNotificationScheduler { + private final YoutubeClient youtubeClient; + private final PushNotificationService pushNotificationService; + + @Value("${youtubeDataApi.playlistId}") private String playlistId; + @Value("${youtubeDataApi.key}") private String apiKey; - public static final String YOUTUBE_NEW_VIDEO_TOPIC = "youtube-yeni-video"; - public static final String YOUTUBE_NEW_VIDEO_TITLE = "Yeni Video Yayınlandı!"; - - private final YoutubeClient youtubeClient; - private final PushNotificationService pushNotificationService; - private String lastVideoId; @PostConstruct @@ -40,6 +39,7 @@ private void init() { this.lastVideoId = this.getLastVideo().getId(); } + /** * This method will be executed every minute. */ @@ -51,15 +51,16 @@ private void sendNotificationForNewVideo() { if (!this.lastVideoId.equals(videoId)) { log.info("New video: {}", videoId); - pushNotificationService.sendPushNotificationToTopic( - PushNotificationTopicRequest.builder() - .topic(YOUTUBE_NEW_VIDEO_TOPIC) - .title(YOUTUBE_NEW_VIDEO_TITLE) - .message("Yeni video: " + lastVideo.getTitle()) - .thumbnailLink(lastVideo.getThumbnailLink()) - .build() - ); - log.info("Notifications has been sent to topic: {}", YOUTUBE_NEW_VIDEO_TOPIC); + + PushNotificationTopicRequest notificationTopicRequest = PushNotificationTopicRequest.builder() + .topic("youtube-yeni-video") + .title("Yeni Video Yayınlandı!") + .message("Yeni video: " + lastVideo.getTitle()) + .thumbnailLink(lastVideo.getThumbnailLink()) + .build(); + + pushNotificationService.sendPushNotificationToTopic(notificationTopicRequest); + log.info("Notifications has been sent to topic: {}", notificationTopicRequest.getTopic()); this.lastVideoId = videoId; } @@ -76,8 +77,7 @@ private YoutubeVideo getLastVideo() { .thumbnailLink(playlistItemsResponse.getItems().get(0).getSnippet().getThumbnails().getMaxres().getUrl()) .build(); } catch (Exception exception) { - log.error(exception.getMessage(), exception); - throw new LastYouTubeVideoNotFoundException(); + throw new LastYouTubeVideoNotFoundException(exception); } } @@ -88,4 +88,5 @@ private static class YoutubeVideo { private String title; private String thumbnailLink; } + } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/notification/service/PushNotificationService.java b/src/main/java/org/gelecekbilimde/scienceplatform/notification/service/PushNotificationService.java index 2da89d1b..85f69937 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/notification/service/PushNotificationService.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/notification/service/PushNotificationService.java @@ -1,47 +1,12 @@ package org.gelecekbilimde.scienceplatform.notification.service; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.gelecekbilimde.scienceplatform.notification.model.request.PushNotificationTopicRequest; import org.gelecekbilimde.scienceplatform.notification.model.request.PushNotificationUserRequest; -import org.springframework.stereotype.Service; -@Slf4j -@Service -@RequiredArgsConstructor -public class PushNotificationService { // TODO : interface yazılmalı ve bu sınıf package-private olmalı +public interface PushNotificationService { - private final FCMService fcmService; + void sendPushNotificationToUser(PushNotificationUserRequest request); - /** - * Send push notification to user by user id. - * - * @param request PushNotificationTopicRequest - */ - public void sendPushNotificationToUser(PushNotificationUserRequest request) { - try { - fcmService.sendMessageToTokenList(request); - } catch (Exception exception) { - log.error(exception.getMessage(), exception); - } - } + void sendPushNotificationToTopic(PushNotificationTopicRequest request); - /** - * Send push notification to topic. - * - * @param request PushNotificationTopicRequest - * @implNote PushNotificationTopicRequest.builder() - * .topic("youtube-yeni-video") - * .title("Yeni video yok") - * .message("Yeni video yok : " + videoTitle) - * .build() - * ); - */ - public void sendPushNotificationToTopic(PushNotificationTopicRequest request) { - try { - fcmService.sendMessageToTopic(request); - } catch (Exception exception) { - log.error(exception.getMessage(), exception); - } - } } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/notification/service/impl/FCMServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/notification/service/impl/FCMServiceImpl.java index 8c241331..66445c16 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/notification/service/impl/FCMServiceImpl.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/notification/service/impl/FCMServiceImpl.java @@ -10,14 +10,15 @@ import com.google.gson.GsonBuilder; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.gelecekbilimde.scienceplatform.notification.model.entity.NotificationTokenEntity; +import org.gelecekbilimde.scienceplatform.notification.model.NotificationToken; import org.gelecekbilimde.scienceplatform.notification.model.request.PushNotificationTopicRequest; import org.gelecekbilimde.scienceplatform.notification.model.request.PushNotificationUserRequest; -import org.gelecekbilimde.scienceplatform.notification.repository.NotificationTokenRepository; +import org.gelecekbilimde.scienceplatform.notification.port.NotificationTokenReadPort; import org.gelecekbilimde.scienceplatform.notification.service.FCMService; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Objects; import java.util.concurrent.ExecutionException; @Slf4j @@ -25,7 +26,7 @@ @RequiredArgsConstructor class FCMServiceImpl implements FCMService { - private final NotificationTokenRepository userTokenRepository; + private final NotificationTokenReadPort notificationTokenReadPort; private final FirebaseMessaging firebaseMessaging; @Override @@ -60,10 +61,10 @@ private Message.Builder getPreconfiguredMessageBuilder(PushNotificationTopicRequ } private MulticastMessage.Builder getPreconfiguredMulticastMessageBuilder(PushNotificationUserRequest request) { - List deviceTokens = userTokenRepository.findAllByUserId(request.getUserId()) + List deviceTokens = notificationTokenReadPort.findAllByUserId(request.getUserId()) .stream() - .filter(notificationToken -> notificationToken.getDeviceToken() != null) - .map(NotificationTokenEntity::getDeviceToken) + .map(NotificationToken::getDeviceToken) + .filter(Objects::nonNull) .toList(); log.info("Find Device Tokens : {}", deviceTokens); diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/notification/service/impl/PushNotificationServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/notification/service/impl/PushNotificationServiceImpl.java new file mode 100644 index 00000000..583f3eec --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/notification/service/impl/PushNotificationServiceImpl.java @@ -0,0 +1,55 @@ +package org.gelecekbilimde.scienceplatform.notification.service.impl; + +import com.google.firebase.messaging.FirebaseMessagingException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.gelecekbilimde.scienceplatform.notification.model.request.PushNotificationTopicRequest; +import org.gelecekbilimde.scienceplatform.notification.model.request.PushNotificationUserRequest; +import org.gelecekbilimde.scienceplatform.notification.service.FCMService; +import org.gelecekbilimde.scienceplatform.notification.service.PushNotificationService; +import org.springframework.stereotype.Service; + +import java.util.concurrent.ExecutionException; + +@Slf4j +@Service +@RequiredArgsConstructor +class PushNotificationServiceImpl implements PushNotificationService { + + private final FCMService fcmService; + + /** + * Send push notification to user by user id. + * + * @param request PushNotificationTopicRequest + */ + public void sendPushNotificationToUser(PushNotificationUserRequest request) { + try { + fcmService.sendMessageToTokenList(request); + } catch (FirebaseMessagingException exception) { + log.error("Error while sending push notification to userId: {}", request.getUserId()); + Thread.currentThread().interrupt(); + } + } + + /** + * Send push notification to topic. + * + * @param request PushNotificationTopicRequest + * @implNote PushNotificationTopicRequest.builder() + * .topic("youtube-yeni-video") + * .title("Yeni video yok") + * .message("Yeni video yok : " + videoTitle) + * .build() + * ); + */ + public void sendPushNotificationToTopic(PushNotificationTopicRequest request) { + try { + fcmService.sendMessageToTopic(request); + } catch (InterruptedException | ExecutionException exception) { + log.error("Error while sending push notification to topic: {}", request.getTopic()); + Thread.currentThread().interrupt(); + } + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/post/model/Category.java b/src/main/java/org/gelecekbilimde/scienceplatform/post/model/Category.java index a4aad826..3d5f384d 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/post/model/Category.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/post/model/Category.java @@ -20,4 +20,9 @@ public class Category extends BaseDomainModel { private String icon; private Long parentId; + + public void increaseOrderNumber() { + this.orderNumber++; + } + } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/post/model/entity/CategoryEntity.java b/src/main/java/org/gelecekbilimde/scienceplatform/post/model/entity/CategoryEntity.java index 63acebad..2fbdc94c 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/post/model/entity/CategoryEntity.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/post/model/entity/CategoryEntity.java @@ -51,7 +51,4 @@ public class CategoryEntity extends BaseEntity { @JoinColumn(name = "parent_id", updatable = false, insertable = false) private CategoryEntity parent; - public void increaseOrder() { - this.orderNumber++; - } } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/post/model/mapper/CategoryCreateRequestToDomainMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/post/model/mapper/CategoryCreateRequestToDomainMapper.java new file mode 100644 index 00000000..6162bfa2 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/post/model/mapper/CategoryCreateRequestToDomainMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.post.model.mapper; + +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.gelecekbilimde.scienceplatform.post.model.Category; +import org.gelecekbilimde.scienceplatform.post.model.request.CategoryCreateRequest; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface CategoryCreateRequestToDomainMapper extends BaseMapper { + + static CategoryCreateRequestToDomainMapper initialize() { + return Mappers.getMapper(CategoryCreateRequestToDomainMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/post/model/mapper/CategoryCreateRequestToEntityMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/post/model/mapper/CategoryCreateRequestToEntityMapper.java deleted file mode 100644 index c70a3e55..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/post/model/mapper/CategoryCreateRequestToEntityMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.gelecekbilimde.scienceplatform.post.model.mapper; - -import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; -import org.gelecekbilimde.scienceplatform.post.model.entity.CategoryEntity; -import org.gelecekbilimde.scienceplatform.post.model.request.CategoryCreateRequest; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface CategoryCreateRequestToEntityMapper extends BaseMapper { - - static CategoryCreateRequestToEntityMapper initialize() { - return Mappers.getMapper(CategoryCreateRequestToEntityMapper.class); - } - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/post/model/mapper/CategoryToEntityMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/post/model/mapper/CategoryToEntityMapper.java new file mode 100644 index 00000000..583b7fc5 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/post/model/mapper/CategoryToEntityMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.post.model.mapper; + +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.gelecekbilimde.scienceplatform.post.model.Category; +import org.gelecekbilimde.scienceplatform.post.model.entity.CategoryEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface CategoryToEntityMapper extends BaseMapper { + + static CategoryToEntityMapper initialize() { + return Mappers.getMapper(CategoryToEntityMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/post/port/CategoryDeletePort.java b/src/main/java/org/gelecekbilimde/scienceplatform/post/port/CategoryDeletePort.java new file mode 100644 index 00000000..57bd2ef8 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/post/port/CategoryDeletePort.java @@ -0,0 +1,9 @@ +package org.gelecekbilimde.scienceplatform.post.port; + +import org.gelecekbilimde.scienceplatform.post.model.Category; + +public interface CategoryDeletePort { + + void delete(Category category); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/post/port/CategoryReadPort.java b/src/main/java/org/gelecekbilimde/scienceplatform/post/port/CategoryReadPort.java new file mode 100644 index 00000000..eae2c48d --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/post/port/CategoryReadPort.java @@ -0,0 +1,28 @@ +package org.gelecekbilimde.scienceplatform.post.port; + +import org.gelecekbilimde.scienceplatform.common.model.BasePage; +import org.gelecekbilimde.scienceplatform.common.model.BasePageable; +import org.gelecekbilimde.scienceplatform.post.model.Category; + +import java.util.List; +import java.util.Optional; + +public interface CategoryReadPort { + + List findAll(); + + BasePage findAll(BasePageable basePageable); + + List findAllByParentId(Long parentId); + + Optional findById(Long id); + + Optional findBySlug(String slug); + + boolean notExistsById(Long id); + + boolean existsByParentId(Long parentId); + + boolean existsBySlug(String slug); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/post/port/CategorySavePort.java b/src/main/java/org/gelecekbilimde/scienceplatform/post/port/CategorySavePort.java new file mode 100644 index 00000000..064be81a --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/post/port/CategorySavePort.java @@ -0,0 +1,13 @@ +package org.gelecekbilimde.scienceplatform.post.port; + +import org.gelecekbilimde.scienceplatform.post.model.Category; + +import java.util.List; + +public interface CategorySavePort { + + void save(Category category); + + void saveAll(List categories); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/post/port/adapter/CategoryAdapter.java b/src/main/java/org/gelecekbilimde/scienceplatform/post/port/adapter/CategoryAdapter.java new file mode 100644 index 00000000..272881a0 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/post/port/adapter/CategoryAdapter.java @@ -0,0 +1,118 @@ +package org.gelecekbilimde.scienceplatform.post.port.adapter; + +import lombok.RequiredArgsConstructor; +import org.gelecekbilimde.scienceplatform.common.model.BasePage; +import org.gelecekbilimde.scienceplatform.common.model.BasePageable; +import org.gelecekbilimde.scienceplatform.post.model.Category; +import org.gelecekbilimde.scienceplatform.post.model.entity.CategoryEntity; +import org.gelecekbilimde.scienceplatform.post.model.mapper.CategoryEntityToDomainMapper; +import org.gelecekbilimde.scienceplatform.post.model.mapper.CategoryToEntityMapper; +import org.gelecekbilimde.scienceplatform.post.port.CategoryDeletePort; +import org.gelecekbilimde.scienceplatform.post.port.CategoryReadPort; +import org.gelecekbilimde.scienceplatform.post.port.CategorySavePort; +import org.gelecekbilimde.scienceplatform.post.repository.CategoryRepository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Optional; + +@Component +@RequiredArgsConstructor +class CategoryAdapter implements CategoryReadPort, CategorySavePort, CategoryDeletePort { + + private final CategoryRepository categoryRepository; + + + private final CategoryEntityToDomainMapper categoryEntityToDomainMapper = CategoryEntityToDomainMapper.initialize(); + private final CategoryToEntityMapper categoryToEntityMapper = CategoryToEntityMapper.initialize(); + + + @Override + public List findAll() { + return categoryRepository.findAll().stream() + .map(categoryEntityToDomainMapper::map) + .toList(); + } + + @Override + public BasePage findAll(final BasePageable basePageable) { + + final Pageable pageable = basePageable.toPageable(); + + final Page categoriesPage = categoryRepository + .findAll(Specification.allOf(), pageable); + + final List categories = categoryEntityToDomainMapper + .map(categoriesPage.getContent()); + + return BasePage.of( + categoriesPage, + categories + ); + } + + + @Override + public List findAllByParentId(final Long parentId) { + return categoryRepository.findAllByParentId(parentId).stream() + .map(categoryEntityToDomainMapper::map) + .toList(); + } + + + @Override + public Optional findById(final Long id) { + return categoryRepository.findById(id) + .map(categoryEntityToDomainMapper::map); + } + + + @Override + public Optional findBySlug(final String slug) { + return categoryRepository.findBySlug(slug) + .map(categoryEntityToDomainMapper::map); + } + + + @Override + public boolean notExistsById(final Long id) { + return !categoryRepository.existsById(id); + } + + + @Override + public boolean existsByParentId(Long parentId) { + return categoryRepository.existsByParentId(parentId); + } + + + @Override + public boolean existsBySlug(final String slug) { + return categoryRepository.existsBySlug(slug); + } + + + @Override + public void save(final Category category) { + final CategoryEntity categoryEntity = categoryToEntityMapper.map(category); + categoryRepository.save(categoryEntity); + } + + + @Override + public void saveAll(final List categories) { + final List categoryEntities = categoryToEntityMapper.map(categories); + categoryRepository.saveAll(categoryEntities); + } + + + @Override + public void delete(final Category category) { + final CategoryEntity categoryEntity = categoryToEntityMapper.map(category); + categoryRepository.delete(categoryEntity); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/post/repository/CategoryRepository.java b/src/main/java/org/gelecekbilimde/scienceplatform/post/repository/CategoryRepository.java index ed0f6088..0314bc24 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/post/repository/CategoryRepository.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/post/repository/CategoryRepository.java @@ -4,13 +4,13 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import java.util.List; import java.util.Optional; -import java.util.Set; public interface CategoryRepository extends JpaRepository, JpaSpecificationExecutor { - Set findAllByParentId(Long parentId); + List findAllByParentId(Long parentId); Optional findBySlug(String slug); diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/post/service/impl/CategoryServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/post/service/impl/CategoryServiceImpl.java index 50e0e8c7..639e223f 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/post/service/impl/CategoryServiceImpl.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/post/service/impl/CategoryServiceImpl.java @@ -8,17 +8,14 @@ import org.gelecekbilimde.scienceplatform.post.exception.CategoryNotFoundException; import org.gelecekbilimde.scienceplatform.post.exception.CategoryParentNotFoundException; import org.gelecekbilimde.scienceplatform.post.model.Category; -import org.gelecekbilimde.scienceplatform.post.model.entity.CategoryEntity; -import org.gelecekbilimde.scienceplatform.post.model.mapper.CategoryCreateRequestToEntityMapper; -import org.gelecekbilimde.scienceplatform.post.model.mapper.CategoryEntityToDomainMapper; +import org.gelecekbilimde.scienceplatform.post.model.mapper.CategoryCreateRequestToDomainMapper; import org.gelecekbilimde.scienceplatform.post.model.request.CategoryCreateRequest; import org.gelecekbilimde.scienceplatform.post.model.request.CategoryListRequest; import org.gelecekbilimde.scienceplatform.post.model.request.CategoryUpdateRequest; -import org.gelecekbilimde.scienceplatform.post.repository.CategoryRepository; +import org.gelecekbilimde.scienceplatform.post.port.CategoryDeletePort; +import org.gelecekbilimde.scienceplatform.post.port.CategoryReadPort; +import org.gelecekbilimde.scienceplatform.post.port.CategorySavePort; import org.gelecekbilimde.scienceplatform.post.service.CategoryService; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import java.util.List; @@ -27,113 +24,107 @@ @RequiredArgsConstructor class CategoryServiceImpl implements CategoryService { - private final CategoryRepository categoryRepository; + private final CategoryReadPort categoryReadPort; + private final CategorySavePort categorySavePort; + private final CategoryDeletePort categoryDeletePort; - private final CategoryEntityToDomainMapper categoryEntityToDomainMapper = CategoryEntityToDomainMapper.initialize(); - private final CategoryCreateRequestToEntityMapper categoryCreateRequestToEntityMapper = CategoryCreateRequestToEntityMapper.initialize(); + private final CategoryCreateRequestToDomainMapper categoryCreateRequestToDomainMapper = CategoryCreateRequestToDomainMapper.initialize(); @Override public BasePage findAll(final CategoryListRequest listRequest) { - - final Pageable pageable = listRequest.getPageable().toPageable(); - - final Page categoriesPage = categoryRepository - .findAll(Specification.allOf(), pageable); - - final List categories = categoryEntityToDomainMapper - .map(categoriesPage.getContent()); - - return BasePage.of( - categoriesPage, - categories - ); + return categoryReadPort.findAll(listRequest.getPageable()); } @Override public List findAll() { - List categories = categoryRepository.findAll(); - return categoryEntityToDomainMapper.map(categories); + return categoryReadPort.findAll(); } @Override public Category findById(Long id) { - CategoryEntity categoryEntity = categoryRepository.findById(id) + return categoryReadPort.findById(id) .orElseThrow(() -> new CategoryNotFoundException(id)); - return categoryEntityToDomainMapper.map(categoryEntity); } @Override - public void create(CategoryCreateRequest request) { + public void create(CategoryCreateRequest createRequest) { - final String slug = SlugUtil.slugging(request.getName()); - final boolean exists = categoryRepository.existsBySlug(slug); + final String slug = SlugUtil.slugging(createRequest.getName()); + final boolean exists = categoryReadPort.existsBySlug(slug); if (exists) { - throw new CategoryAlreadyExistException(request.getName()); + throw new CategoryAlreadyExistException(createRequest.getName()); } - if (request.getParentId() != null && !categoryRepository.existsById(request.getParentId())) { - throw new CategoryParentNotFoundException(request.getParentId()); + if (createRequest.getParentId() != null && categoryReadPort.notExistsById(createRequest.getParentId())) { + throw new CategoryParentNotFoundException(createRequest.getParentId()); } - List categories = categoryRepository.findAllByParentId(request.getParentId()).stream().toList(); - for (CategoryEntity categoryEntity : categories) { - if (categoryEntity.getOrderNumber() >= request.getOrderNumber()) { - categoryEntity.increaseOrder(); + final List reorderedSubCategories = this.reorderSubCategories( + createRequest.getParentId(), + createRequest.getOrderNumber() + ); + + final Category category = categoryCreateRequestToDomainMapper.map(createRequest); + category.setSlug(slug); + + categorySavePort.save(category); + categorySavePort.saveAll(reorderedSubCategories); + } + + private List reorderSubCategories(final Long parentId, final Integer orderNumber) { + final List categories = categoryReadPort.findAllByParentId(parentId); + for (Category category : categories) { + if (category.getOrderNumber() >= orderNumber) { + category.increaseOrderNumber(); } } - - CategoryEntity categoryEntity = categoryCreateRequestToEntityMapper.map(request); - categoryEntity.setSlug(slug); - categoryRepository.save(categoryEntity); - categoryRepository.saveAll(categories); + return categories; } @Override - public void update(Long id, CategoryUpdateRequest request) { + public void update(final Long id, final CategoryUpdateRequest updateRequest) { - CategoryEntity categoryEntity = categoryRepository.findById(id) + final Category category = categoryReadPort.findById(id) .orElseThrow(() -> new CategoryNotFoundException(id)); - final String slug = SlugUtil.slugging(request.getName()); - final boolean exists = categoryRepository.findBySlug(slug) + final String slug = SlugUtil.slugging(updateRequest.getName()); + final boolean exists = categoryReadPort.findBySlug(slug) .filter(existingCategory -> !existingCategory.getId().equals(id)) .isPresent(); if (exists) { - throw new CategoryAlreadyExistException(request.getName()); + throw new CategoryAlreadyExistException(updateRequest.getName()); } - categoryEntity.setName(request.getName()); - categoryEntity.setSlug(slug); - - if (request.getParentId() != null) { - if (!categoryRepository.existsById(request.getParentId())) { - throw new CategoryParentNotFoundException(request.getParentId()); - } - categoryEntity.setParentId(request.getParentId()); + if (updateRequest.getParentId() != null && categoryReadPort.notExistsById(updateRequest.getParentId())) { + throw new CategoryParentNotFoundException(updateRequest.getParentId()); } - categoryEntity.setDescription(request.getDescription()); + category.setName(updateRequest.getName()); + category.setSlug(slug); + category.setParentId(updateRequest.getParentId()); + category.setDescription(updateRequest.getDescription()); - categoryRepository.save(categoryEntity); + categorySavePort.save(category); } + @Override public void delete(Long id) { - CategoryEntity categoryEntity = categoryRepository.findById(id) - .orElseThrow(() -> new CategoryNotFoundException(id)); - boolean isCategoryParent = categoryRepository.existsByParentId(id); + Category category = categoryReadPort.findById(id) + .orElseThrow(() -> new CategoryNotFoundException(id)); + boolean isCategoryParent = categoryReadPort.existsByParentId(id); if (isCategoryParent) { throw new CategoryHasChildException(id); } - categoryRepository.delete(categoryEntity); + categoryDeletePort.delete(category); } } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/settings/exception/SettingsNotFoundByGroupNameException.java b/src/main/java/org/gelecekbilimde/scienceplatform/settings/exception/SettingsNotFoundByGroupNameException.java deleted file mode 100644 index dd9d1cbb..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/settings/exception/SettingsNotFoundByGroupNameException.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.gelecekbilimde.scienceplatform.settings.exception; - -import org.gelecekbilimde.scienceplatform.common.exception.AbstractNotFoundException; - -import java.io.Serial; - -public final class SettingsNotFoundByGroupNameException extends AbstractNotFoundException { - - @Serial - private static final long serialVersionUID = 6365994753340820279L; - - public SettingsNotFoundByGroupNameException(String groupName) { - super("settings not found! groupName: " + groupName); - } - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/settings/model/entity/SettingsEntity.java b/src/main/java/org/gelecekbilimde/scienceplatform/settings/model/entity/SettingsEntity.java deleted file mode 100644 index 97c8f617..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/settings/model/entity/SettingsEntity.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.gelecekbilimde.scienceplatform.settings.model.entity; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.experimental.SuperBuilder; -import org.gelecekbilimde.scienceplatform.common.model.entity.BaseEntity; - -@Entity -@Getter -@Setter -@SuperBuilder -@NoArgsConstructor -@AllArgsConstructor -@Table(name = "gb_setting") -public class SettingsEntity extends BaseEntity { - - @Id - @Column(name = "id") - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "group_name") - private String groupName; - - @Column(name = "name") - private String name; - - @Column(name = "definition") - private String definition; - - @Column(name = "is_hidden") - private boolean isHidden; - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/settings/model/mapper/SettingsEntityToSettingsMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/settings/model/mapper/SettingsEntityToSettingsMapper.java deleted file mode 100644 index 604d36ae..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/settings/model/mapper/SettingsEntityToSettingsMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.gelecekbilimde.scienceplatform.settings.model.mapper; - -import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; -import org.gelecekbilimde.scienceplatform.settings.model.Settings; -import org.gelecekbilimde.scienceplatform.settings.model.entity.SettingsEntity; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface SettingsEntityToSettingsMapper extends BaseMapper { - - static SettingsEntityToSettingsMapper initialize() { - return Mappers.getMapper(SettingsEntityToSettingsMapper.class); - } - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/settings/repository/SettingsRepository.java b/src/main/java/org/gelecekbilimde/scienceplatform/settings/repository/SettingsRepository.java deleted file mode 100644 index b369828b..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/settings/repository/SettingsRepository.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.gelecekbilimde.scienceplatform.settings.repository; - -import org.gelecekbilimde.scienceplatform.settings.model.entity.SettingsEntity; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.List; - -public interface SettingsRepository extends JpaRepository { - - List findAllByGroupName(String groupName); - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/settings/service/SettingService.java b/src/main/java/org/gelecekbilimde/scienceplatform/settings/service/SettingService.java deleted file mode 100644 index 50ac3d11..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/settings/service/SettingService.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.gelecekbilimde.scienceplatform.settings.service; - -import org.gelecekbilimde.scienceplatform.settings.model.Settings; - -import java.util.List; - -public interface SettingService { - - List getSettings(String groupName, String name); - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/settings/service/impl/SettingServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/settings/service/impl/SettingServiceImpl.java deleted file mode 100644 index 5be49e54..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/settings/service/impl/SettingServiceImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.gelecekbilimde.scienceplatform.settings.service.impl; - -import lombok.RequiredArgsConstructor; -import org.gelecekbilimde.scienceplatform.settings.exception.SettingsNotFoundByGroupNameException; -import org.gelecekbilimde.scienceplatform.settings.model.Settings; -import org.gelecekbilimde.scienceplatform.settings.model.entity.SettingsEntity; -import org.gelecekbilimde.scienceplatform.settings.model.mapper.SettingsEntityToSettingsMapper; -import org.gelecekbilimde.scienceplatform.settings.repository.SettingsRepository; -import org.gelecekbilimde.scienceplatform.settings.service.SettingService; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; - -import java.util.List; - -@Service -@RequiredArgsConstructor -class SettingServiceImpl implements SettingService { - - private final SettingsRepository settingsRepository; - - private final SettingsEntityToSettingsMapper settingsEntityToSettingsMapper = SettingsEntityToSettingsMapper.initialize(); - - public List getSettings(String groupName, String name) { - - List settings = settingsRepository.findAllByGroupName(groupName); - - if (CollectionUtils.isEmpty(settings)) { - throw new SettingsNotFoundByGroupNameException(groupName); - } - - return settingsEntityToSettingsMapper.map(settings); - } - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketCommentController.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketCommentController.java new file mode 100644 index 00000000..6379772a --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketCommentController.java @@ -0,0 +1,56 @@ +package org.gelecekbilimde.scienceplatform.ticket.controller; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.Positive; +import lombok.RequiredArgsConstructor; +import org.gelecekbilimde.scienceplatform.common.model.response.SuccessResponse; +import org.gelecekbilimde.scienceplatform.ticket.model.TicketComment; +import org.gelecekbilimde.scienceplatform.ticket.model.mapper.TicketCommentToResponseMapper; +import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketCommentAddRequest; +import org.gelecekbilimde.scienceplatform.ticket.model.response.TicketCommentResponse; +import org.gelecekbilimde.scienceplatform.ticket.service.TicketCommentService; +import org.springframework.security.access.prepost.PreAuthorize; +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 java.util.List; + +@Validated +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1") +class TicketCommentController { + + private final TicketCommentService ticketService; + + + private final TicketCommentToResponseMapper ticketCommentToResponseMapper = TicketCommentToResponseMapper.initialize(); + + + @GetMapping("/ticket/{id}/comments") + @PreAuthorize("hasAuthority('ticket:detail')") + SuccessResponse> findAllByTicketId(@PathVariable(name = "id") @Positive Long ticketId) { + + final List ticketComments = ticketService.findAllByTicketId(ticketId); + + final List ticketCommentResponses = ticketCommentToResponseMapper + .map(ticketComments); + return SuccessResponse.success(ticketCommentResponses); + } + + + @PostMapping("/ticket/{id}/comment") + @PreAuthorize("hasAuthority('ticket:comment:add')") + SuccessResponse add(@PathVariable(name = "id") @Positive Long ticketId, + @RequestBody @Valid TicketCommentAddRequest addRequest) { + + ticketService.add(ticketId, addRequest); + return SuccessResponse.success(); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketController.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketController.java index bef7901c..31cec4c5 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketController.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketController.java @@ -1,40 +1,85 @@ package org.gelecekbilimde.scienceplatform.ticket.controller; import jakarta.validation.Valid; +import jakarta.validation.constraints.Positive; import lombok.RequiredArgsConstructor; -import org.gelecekbilimde.scienceplatform.common.model.request.PagingRequest; +import org.gelecekbilimde.scienceplatform.common.model.BasePage; import org.gelecekbilimde.scienceplatform.common.model.response.PagingResponse; import org.gelecekbilimde.scienceplatform.common.model.response.SuccessResponse; import org.gelecekbilimde.scienceplatform.ticket.model.Ticket; +import org.gelecekbilimde.scienceplatform.ticket.model.mapper.TicketToResponseMapper; +import org.gelecekbilimde.scienceplatform.ticket.model.mapper.TicketToTicketsResponseMapper; +import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketCreateRequest; +import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketListRequest; import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketUpdateRequest; import org.gelecekbilimde.scienceplatform.ticket.model.response.TicketResponse; +import org.gelecekbilimde.scienceplatform.ticket.model.response.TicketsResponse; import org.gelecekbilimde.scienceplatform.ticket.service.TicketService; import org.springframework.security.access.prepost.PreAuthorize; +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.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +@Validated @RestController @RequiredArgsConstructor -@RequestMapping("/api/v1/ticket") +@RequestMapping("/api/v1") class TicketController { private final TicketService ticketService; - @GetMapping - @PreAuthorize("hasAuthority('ticket:read')") - SuccessResponse> ticketRead(@Valid PagingRequest request) { - final PagingResponse ticketResponses = ticketService.ticketRead(request); - return SuccessResponse.success(ticketResponses); + private final TicketToTicketsResponseMapper ticketToTicketsResponseMapper = TicketToTicketsResponseMapper.initialize(); + private final TicketToResponseMapper ticketToResponseMapper = TicketToResponseMapper.initialize(); + + + @PostMapping("/tickets") + @PreAuthorize("hasAuthority('ticket:list')") + SuccessResponse> findAll(@RequestBody @Valid TicketListRequest listRequest) { + + final BasePage pageOfTickets = ticketService.findAll(listRequest); + + final PagingResponse pageResponseOfTicket = PagingResponse + .builder() + .of(pageOfTickets) + .content( + ticketToTicketsResponseMapper.map(pageOfTickets.getContent()) + ) + .filteredBy(listRequest.getFilter()) + .build(); + + return SuccessResponse.success(pageResponseOfTicket); } - @PutMapping - @PreAuthorize("hasAuthority('ticket:update')") - SuccessResponse ticketUpdate(@RequestBody @Valid TicketUpdateRequest request) { - Ticket ticketResponse = ticketService.updateTicket(request); + + @GetMapping("/ticket/{id}") + @PreAuthorize("hasAuthority('ticket:detail')") + SuccessResponse findById(@PathVariable @Positive Long id) { + Ticket ticket = ticketService.findById(id); + TicketResponse ticketResponse = ticketToResponseMapper.map(ticket); return SuccessResponse.success(ticketResponse); } + + @PostMapping("/ticket") + @PreAuthorize("hasAuthority('ticket:create')") + SuccessResponse create(@RequestBody @Valid TicketCreateRequest createRequest) { + ticketService.create(createRequest); + return SuccessResponse.success(); + } + + + @PutMapping("/ticket/{id}") + @PreAuthorize("hasAuthority('ticket:update')") + SuccessResponse update(@PathVariable @Positive Long id, + @RequestBody @Valid TicketUpdateRequest request) { + + ticketService.update(id, request); + return SuccessResponse.success(); + } + } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketMessageController.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketMessageController.java deleted file mode 100644 index 814c4703..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketMessageController.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.gelecekbilimde.scienceplatform.ticket.controller; - -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.gelecekbilimde.scienceplatform.common.model.response.PagingResponse; -import org.gelecekbilimde.scienceplatform.common.model.response.SuccessResponse; -import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketMessageRequest; -import org.gelecekbilimde.scienceplatform.ticket.model.response.TicketMessageResponse; -import org.gelecekbilimde.scienceplatform.ticket.service.TicketMessageService; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/ticket-message") -class TicketMessageController { - - private final TicketMessageService ticketService; - - @GetMapping - @PreAuthorize("hasAuthority('ticket:read')") - SuccessResponse> ticketMessageRead(@Valid TicketMessageRequest request) { - final PagingResponse ticketResponses = ticketService.ticketMessageRead(request); - return SuccessResponse.success(ticketResponses); - } - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketUserController.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketUserController.java deleted file mode 100644 index 8ad72387..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketUserController.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.gelecekbilimde.scienceplatform.ticket.controller; - -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.gelecekbilimde.scienceplatform.common.model.request.PagingRequest; -import org.gelecekbilimde.scienceplatform.common.model.response.PagingResponse; -import org.gelecekbilimde.scienceplatform.common.model.response.SuccessResponse; -import org.gelecekbilimde.scienceplatform.ticket.model.Ticket; -import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketCreateRequest; -import org.gelecekbilimde.scienceplatform.ticket.model.response.TicketResponse; -import org.gelecekbilimde.scienceplatform.ticket.service.TicketService; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/user/ticket") -class TicketUserController { - - private final TicketService ticketService; - - @GetMapping - @Valid - @PreAuthorize("hasAuthority('self:ticket:read')") - SuccessResponse> ticketReadSelf(PagingRequest request) { - final PagingResponse ticketResponses = ticketService.ticketReadSelf(request); - return SuccessResponse.success(ticketResponses); - } - - @PostMapping - @PreAuthorize("hasAuthority('self:ticket:create')") - SuccessResponse ticketCreateSelf(@RequestBody @Valid TicketCreateRequest request) { - Ticket ticketResponse = ticketService.ticketCreateSelf(request); - return SuccessResponse.success(ticketResponse); - } - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketUserMessageController.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketUserMessageController.java deleted file mode 100644 index 8ff35bc8..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/controller/TicketUserMessageController.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.gelecekbilimde.scienceplatform.ticket.controller; - -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.gelecekbilimde.scienceplatform.common.model.response.PagingResponse; -import org.gelecekbilimde.scienceplatform.common.model.response.SuccessResponse; -import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketMessageCreateRequest; -import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketMessageRequest; -import org.gelecekbilimde.scienceplatform.ticket.model.response.TicketMessageResponse; -import org.gelecekbilimde.scienceplatform.ticket.service.TicketMessageService; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/user/ticket-message") -class TicketUserMessageController { - - private final TicketMessageService ticketService; - - @GetMapping - @PreAuthorize("hasAuthority('self:ticket:read')") - SuccessResponse> ticketMessageRead(@Valid TicketMessageRequest request) { - final PagingResponse ticketResponses = ticketService.ticketMessageReadSelf(request); - return SuccessResponse.success(ticketResponses); - } - - @PostMapping - @PreAuthorize("hasAuthority('self:ticket:create')") - SuccessResponse ticketCreateSelf(@RequestBody @Valid TicketMessageCreateRequest request) { - TicketMessageResponse ticketResponse = ticketService.ticketMessageCreate(request); - return SuccessResponse.success(ticketResponse); - } - - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/exception/TicketAlreadyHasStatusException.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/exception/TicketAlreadyHasStatusException.java new file mode 100644 index 00000000..58425343 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/exception/TicketAlreadyHasStatusException.java @@ -0,0 +1,17 @@ +package org.gelecekbilimde.scienceplatform.ticket.exception; + +import org.gelecekbilimde.scienceplatform.common.exception.AbstractConflictException; +import org.gelecekbilimde.scienceplatform.ticket.model.enums.TicketStatus; + +import java.io.Serial; + +public final class TicketAlreadyHasStatusException extends AbstractConflictException { + + @Serial + private static final long serialVersionUID = -1475053585476383993L; + + public TicketAlreadyHasStatusException(TicketStatus status) { + super("ticket already has " + status + " status"); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/exception/TicketNotFoundByIdException.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/exception/TicketNotFoundByIdException.java new file mode 100644 index 00000000..ee9c469b --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/exception/TicketNotFoundByIdException.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.ticket.exception; + +import org.gelecekbilimde.scienceplatform.common.exception.AbstractNotFoundException; + +import java.io.Serial; + +public final class TicketNotFoundByIdException extends AbstractNotFoundException { + + @Serial + private static final long serialVersionUID = 2578307933658765882L; + + public TicketNotFoundByIdException(Long id) { + super("ticket not found by id: " + id); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/Ticket.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/Ticket.java index 625f5c9d..75812edb 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/Ticket.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/Ticket.java @@ -1,10 +1,12 @@ package org.gelecekbilimde.scienceplatform.ticket.model; +import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import lombok.experimental.SuperBuilder; import org.gelecekbilimde.scienceplatform.common.model.BaseDomainModel; +import org.gelecekbilimde.scienceplatform.ticket.model.enums.TicketCategory; import org.gelecekbilimde.scienceplatform.ticket.model.enums.TicketStatus; @Getter @@ -15,7 +17,10 @@ public class Ticket extends BaseDomainModel { private Long id; private String userId; - private String message; - private TicketStatus status; + private TicketCategory category; + private String title; + private String description; + @Builder.Default + private TicketStatus status = TicketStatus.OPEN; } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/TicketComment.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/TicketComment.java new file mode 100644 index 00000000..59d8ba94 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/TicketComment.java @@ -0,0 +1,20 @@ +package org.gelecekbilimde.scienceplatform.ticket.model; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.SuperBuilder; +import org.gelecekbilimde.scienceplatform.common.model.BaseDomainModel; + +@Getter +@Setter +@SuperBuilder +@EqualsAndHashCode(callSuper = true) +public class TicketComment extends BaseDomainModel { + + private Long id; + private String userId; + private Long ticketId; + private String content; + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/TicketFilter.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/TicketFilter.java new file mode 100644 index 00000000..3394c0da --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/TicketFilter.java @@ -0,0 +1,57 @@ +package org.gelecekbilimde.scienceplatform.ticket.model; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.gelecekbilimde.scienceplatform.common.model.BaseFilter; +import org.gelecekbilimde.scienceplatform.ticket.model.entity.TicketEntity; +import org.gelecekbilimde.scienceplatform.ticket.model.enums.TicketCategory; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.util.CollectionUtils; + +import java.util.Set; + +@Getter +@Setter +@Builder +public class TicketFilter implements BaseFilter { + + private Set categories; + private User user; + + @Getter + @Setter + @Builder + public static class User { + private String id; + } + + public void addUserId(String userId) { + this.user = User.builder() + .id(userId) + .build(); + } + + + @Override + public Specification toSpecification() { + + Specification specification = Specification.where(null); + + if (!CollectionUtils.isEmpty(this.categories)) { + + Specification categorySpecification = this.categories.stream() + .map( + category -> (Specification) (root, query, criteriaBuilder) -> + criteriaBuilder.equal(root.get("category"), category) + ) + .reduce(Specification::or) + .orElse(null); + + specification = specification.and(categorySpecification); + } + + return specification; + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/TicketMessageFilter.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/TicketMessageFilter.java deleted file mode 100644 index 2831fe6b..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/TicketMessageFilter.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.gelecekbilimde.scienceplatform.ticket.model; - -import lombok.Getter; -import lombok.Setter; -import org.gelecekbilimde.scienceplatform.common.model.BaseFilter; -import org.gelecekbilimde.scienceplatform.ticket.model.entity.TicketEntity; -import org.springframework.data.jpa.domain.Specification; - -@Getter -@Setter -public class TicketMessageFilter implements BaseFilter { - - private Integer id; - - @Override - public Specification toSpecification() { - - Specification specification = Specification.where(null); - if (id != null) { - specification = specification.and((root, query, criteriaBuilder) -> - criteriaBuilder.equal(root.get("id"), id) - ); - } - return specification; - } -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/entity/TicketMessageEntity.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/entity/TicketCommentEntity.java similarity index 86% rename from src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/entity/TicketMessageEntity.java rename to src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/entity/TicketCommentEntity.java index 0378d1b4..487c20cc 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/entity/TicketMessageEntity.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/entity/TicketCommentEntity.java @@ -21,8 +21,8 @@ @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) -@Table(name = "gb_ticket_message") -public class TicketMessageEntity extends BaseEntity { +@Table(name = "gb_ticket_comment") +public class TicketCommentEntity extends BaseEntity { @Id @Column(name = "id") @@ -35,7 +35,7 @@ public class TicketMessageEntity extends BaseEntity { @Column(name = "user_id") private String userId; - @Column(name = "message") - private String message; + @Column(name = "content") + private String content; } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/entity/TicketEntity.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/entity/TicketEntity.java index 038babf7..ff28f065 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/entity/TicketEntity.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/entity/TicketEntity.java @@ -9,14 +9,13 @@ import jakarta.persistence.Id; import jakarta.persistence.Table; import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.SuperBuilder; import org.gelecekbilimde.scienceplatform.common.model.entity.BaseEntity; +import org.gelecekbilimde.scienceplatform.ticket.model.enums.TicketCategory; import org.gelecekbilimde.scienceplatform.ticket.model.enums.TicketStatus; -import org.gelecekbilimde.scienceplatform.ticket.model.enums.TicketSubject; @Entity @Getter @@ -35,17 +34,18 @@ public class TicketEntity extends BaseEntity { @Column(name = "user_id") private String userId; - @Builder.Default - @Column(name = "subject") + @Column(name = "category") @Enumerated(EnumType.STRING) - private TicketSubject subject = TicketSubject.OTHER; + private TicketCategory category; + + @Column(name = "title") + private String title; @Column(name = "description") - private String message; + private String description; - @Builder.Default @Column(name = "status") @Enumerated(EnumType.STRING) - private TicketStatus status = TicketStatus.OPEN; + private TicketStatus status; } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/enums/TicketSubject.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/enums/TicketCategory.java similarity index 83% rename from src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/enums/TicketSubject.java rename to src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/enums/TicketCategory.java index 7e1c9b26..3be04d03 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/enums/TicketSubject.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/enums/TicketCategory.java @@ -1,6 +1,6 @@ package org.gelecekbilimde.scienceplatform.ticket.model.enums; -public enum TicketSubject { +public enum TicketCategory { TECHNICAL, POST, YOUR_QUESTION_REQUESTS, diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketCommentEntityToDomainMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketCommentEntityToDomainMapper.java new file mode 100644 index 00000000..0d2aec66 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketCommentEntityToDomainMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.ticket.model.mapper; + +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.gelecekbilimde.scienceplatform.ticket.model.TicketComment; +import org.gelecekbilimde.scienceplatform.ticket.model.entity.TicketCommentEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface TicketCommentEntityToDomainMapper extends BaseMapper { + + static TicketCommentEntityToDomainMapper initialize() { + return Mappers.getMapper(TicketCommentEntityToDomainMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketCommentToEntityMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketCommentToEntityMapper.java new file mode 100644 index 00000000..8a0cab8a --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketCommentToEntityMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.ticket.model.mapper; + +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.gelecekbilimde.scienceplatform.ticket.model.TicketComment; +import org.gelecekbilimde.scienceplatform.ticket.model.entity.TicketCommentEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface TicketCommentToEntityMapper extends BaseMapper { + + static TicketCommentToEntityMapper initialize() { + return Mappers.getMapper(TicketCommentToEntityMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketCommentToResponseMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketCommentToResponseMapper.java new file mode 100644 index 00000000..8e09d160 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketCommentToResponseMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.ticket.model.mapper; + +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.gelecekbilimde.scienceplatform.ticket.model.TicketComment; +import org.gelecekbilimde.scienceplatform.ticket.model.response.TicketCommentResponse; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface TicketCommentToResponseMapper extends BaseMapper { + + static TicketCommentToResponseMapper initialize() { + return Mappers.getMapper(TicketCommentToResponseMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketMessageEntityToMessageResponseMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketMessageEntityToMessageResponseMapper.java deleted file mode 100644 index ff894a52..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketMessageEntityToMessageResponseMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.gelecekbilimde.scienceplatform.ticket.model.mapper; - -import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; -import org.gelecekbilimde.scienceplatform.ticket.model.entity.TicketMessageEntity; -import org.gelecekbilimde.scienceplatform.ticket.model.response.TicketMessageResponse; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface TicketMessageEntityToMessageResponseMapper extends BaseMapper { - - static TicketMessageEntityToMessageResponseMapper initialize() { - return Mappers.getMapper(TicketMessageEntityToMessageResponseMapper.class); - } - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketToEntityMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketToEntityMapper.java new file mode 100644 index 00000000..224f3925 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketToEntityMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.ticket.model.mapper; + +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.gelecekbilimde.scienceplatform.ticket.model.Ticket; +import org.gelecekbilimde.scienceplatform.ticket.model.entity.TicketEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface TicketToEntityMapper extends BaseMapper { + + static TicketToEntityMapper initialize() { + return Mappers.getMapper(TicketToEntityMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketEntityToResponseMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketToResponseMapper.java similarity index 51% rename from src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketEntityToResponseMapper.java rename to src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketToResponseMapper.java index 502da93f..cb0b2c34 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketEntityToResponseMapper.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketToResponseMapper.java @@ -1,16 +1,16 @@ package org.gelecekbilimde.scienceplatform.ticket.model.mapper; import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; -import org.gelecekbilimde.scienceplatform.ticket.model.entity.TicketEntity; +import org.gelecekbilimde.scienceplatform.ticket.model.Ticket; import org.gelecekbilimde.scienceplatform.ticket.model.response.TicketResponse; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @Mapper -public interface TicketEntityToResponseMapper extends BaseMapper { +public interface TicketToResponseMapper extends BaseMapper { - static TicketEntityToResponseMapper initialize() { - return Mappers.getMapper(TicketEntityToResponseMapper.class); + static TicketToResponseMapper initialize() { + return Mappers.getMapper(TicketToResponseMapper.class); } } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketToTicketsResponseMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketToTicketsResponseMapper.java new file mode 100644 index 00000000..96c2dfb2 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/mapper/TicketToTicketsResponseMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.ticket.model.mapper; + +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.gelecekbilimde.scienceplatform.ticket.model.Ticket; +import org.gelecekbilimde.scienceplatform.ticket.model.response.TicketsResponse; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface TicketToTicketsResponseMapper extends BaseMapper { + + static TicketToTicketsResponseMapper initialize() { + return Mappers.getMapper(TicketToTicketsResponseMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketCommentAddRequest.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketCommentAddRequest.java new file mode 100644 index 00000000..58cdea45 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketCommentAddRequest.java @@ -0,0 +1,14 @@ +package org.gelecekbilimde.scienceplatform.ticket.model.request; + +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class TicketCommentAddRequest { + + @NotBlank + private String content; + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketCreateRequest.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketCreateRequest.java index fba488a9..d0bb4187 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketCreateRequest.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketCreateRequest.java @@ -1,16 +1,26 @@ package org.gelecekbilimde.scienceplatform.ticket.model.request; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import lombok.Builder; import lombok.Getter; import lombok.Setter; +import org.gelecekbilimde.scienceplatform.ticket.model.enums.TicketCategory; @Getter @Setter @Builder public class TicketCreateRequest { + @NotNull + private TicketCategory category; + + @NotBlank + @Size(min = 2, max = 512) + private String title; + @NotBlank - private String message; + private String description; } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketListRequest.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketListRequest.java new file mode 100644 index 00000000..2fc5401c --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketListRequest.java @@ -0,0 +1,29 @@ +package org.gelecekbilimde.scienceplatform.ticket.model.request; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.validation.Valid; +import jakarta.validation.constraints.AssertTrue; +import lombok.Getter; +import lombok.Setter; +import org.gelecekbilimde.scienceplatform.common.model.request.PagingRequest; +import org.gelecekbilimde.scienceplatform.ticket.model.TicketFilter; + +import java.util.Set; + +@Getter +@Setter +public class TicketListRequest extends PagingRequest { + + @Valid + private TicketFilter filter; + + + @JsonIgnore + @AssertTrue + @Override + public boolean isOrderPropertyAccepted() { + final Set acceptedFilterFields = Set.of("createdAt"); + return this.isPropertyAccepted(acceptedFilterFields); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketMessageCreateRequest.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketMessageCreateRequest.java deleted file mode 100644 index 3d34eb1e..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketMessageCreateRequest.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.gelecekbilimde.scienceplatform.ticket.model.request; - -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.validation.constraints.NotNull; -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; -import org.gelecekbilimde.scienceplatform.ticket.model.enums.TicketSubject; - -@Getter -@Setter -@Builder -public class TicketMessageCreateRequest { - - @NotNull - private Long id; - - @NotNull - private String message; - - @Enumerated(EnumType.STRING) - private TicketSubject subject; - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketMessageRequest.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketMessageRequest.java deleted file mode 100644 index 014465f8..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketMessageRequest.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.gelecekbilimde.scienceplatform.ticket.model.request; - -import jakarta.validation.constraints.NotNull; -import lombok.Getter; -import lombok.Setter; -import org.gelecekbilimde.scienceplatform.common.model.request.PagingRequest; -import org.gelecekbilimde.scienceplatform.ticket.model.TicketMessageFilter; - -import java.util.Set; - -@Getter -@Setter -public class TicketMessageRequest extends PagingRequest { - - @NotNull - private TicketMessageFilter filter; - - @Override - public boolean isOrderPropertyAccepted() { - final Set acceptedFilterFields = Set.of(); - return this.isPropertyAccepted(acceptedFilterFields); - } -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketUpdateRequest.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketUpdateRequest.java index 94030328..af6d5faf 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketUpdateRequest.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/request/TicketUpdateRequest.java @@ -1,20 +1,40 @@ package org.gelecekbilimde.scienceplatform.ticket.model.request; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.validation.constraints.AssertTrue; import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; import org.gelecekbilimde.scienceplatform.ticket.model.enums.TicketStatus; +import java.util.EnumSet; + @Getter @Setter public class TicketUpdateRequest { @NotNull - private Long id; - - @Enumerated(EnumType.STRING) private TicketStatus status; + + @JsonIgnore + @AssertTrue + @SuppressWarnings("This method is unused by the application directly but Spring is using it in the background.") + private boolean isStatusAccepted() { + + if (this.status == null) { + return true; + } + + final EnumSet acceptedStatuses = EnumSet.of( + TicketStatus.IN_PROGRESS, + TicketStatus.ON_HOLD, + TicketStatus.CLOSED, + TicketStatus.REOPENED, + TicketStatus.CANCELED, + TicketStatus.RESOLVED + ); + return acceptedStatuses.contains(this.status); + } + } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/response/TicketMessageResponse.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/response/TicketCommentResponse.java similarity index 60% rename from src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/response/TicketMessageResponse.java rename to src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/response/TicketCommentResponse.java index 5d06ccdb..aaf984e7 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/response/TicketMessageResponse.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/response/TicketCommentResponse.java @@ -2,19 +2,16 @@ import lombok.Getter; import lombok.Setter; -import lombok.experimental.SuperBuilder; import java.time.LocalDateTime; @Getter @Setter -@SuperBuilder -public class TicketMessageResponse { +public class TicketCommentResponse { private Long id; - private Long userId; - private Long ticketId; - private String message; + private String userId; + private String content; private LocalDateTime createdAt; private LocalDateTime updatedAt; diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/response/TicketResponse.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/response/TicketResponse.java index 685c662b..f946985d 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/response/TicketResponse.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/response/TicketResponse.java @@ -2,21 +2,21 @@ import lombok.Getter; import lombok.Setter; -import lombok.experimental.SuperBuilder; +import org.gelecekbilimde.scienceplatform.ticket.model.enums.TicketCategory; import org.gelecekbilimde.scienceplatform.ticket.model.enums.TicketStatus; import java.time.LocalDateTime; @Getter @Setter -@SuperBuilder public class TicketResponse { private Long id; private String userId; - private String message; + private TicketCategory category; + private String title; + private String description; private TicketStatus status; private LocalDateTime createdAt; - private LocalDateTime updatedAt; } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/response/TicketsResponse.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/response/TicketsResponse.java new file mode 100644 index 00000000..852cfa19 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/model/response/TicketsResponse.java @@ -0,0 +1,21 @@ +package org.gelecekbilimde.scienceplatform.ticket.model.response; + +import lombok.Getter; +import lombok.Setter; +import org.gelecekbilimde.scienceplatform.ticket.model.enums.TicketCategory; +import org.gelecekbilimde.scienceplatform.ticket.model.enums.TicketStatus; + +import java.time.LocalDateTime; + +@Getter +@Setter +public class TicketsResponse { + + private Long id; + private String userId; + private TicketCategory category; + private String title; + private TicketStatus status; + private LocalDateTime createdAt; + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/TicketCommentReadPort.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/TicketCommentReadPort.java new file mode 100644 index 00000000..9062f95f --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/TicketCommentReadPort.java @@ -0,0 +1,11 @@ +package org.gelecekbilimde.scienceplatform.ticket.port; + +import org.gelecekbilimde.scienceplatform.ticket.model.TicketComment; + +import java.util.List; + +public interface TicketCommentReadPort { + + List findAllByTicketId(Long ticketId); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/TicketCommentSavePort.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/TicketCommentSavePort.java new file mode 100644 index 00000000..2e7bf42e --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/TicketCommentSavePort.java @@ -0,0 +1,9 @@ +package org.gelecekbilimde.scienceplatform.ticket.port; + +import org.gelecekbilimde.scienceplatform.ticket.model.TicketComment; + +public interface TicketCommentSavePort { + + void save(TicketComment ticketComment); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/TicketReadPort.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/TicketReadPort.java new file mode 100644 index 00000000..a5ca63fa --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/TicketReadPort.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.ticket.port; + +import org.gelecekbilimde.scienceplatform.common.model.BasePage; +import org.gelecekbilimde.scienceplatform.common.model.BasePageable; +import org.gelecekbilimde.scienceplatform.ticket.model.Ticket; +import org.gelecekbilimde.scienceplatform.ticket.model.TicketFilter; + +import java.util.Optional; + +public interface TicketReadPort { + + BasePage findAll(BasePageable basePageable, TicketFilter filter); + + Optional findById(Long id); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/TicketSavePort.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/TicketSavePort.java new file mode 100644 index 00000000..4bfa1d32 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/TicketSavePort.java @@ -0,0 +1,9 @@ +package org.gelecekbilimde.scienceplatform.ticket.port; + +import org.gelecekbilimde.scienceplatform.ticket.model.Ticket; + +public interface TicketSavePort { + + void save(Ticket ticket); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/adapter/TicketAdapter.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/adapter/TicketAdapter.java new file mode 100644 index 00000000..f425e6bd --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/adapter/TicketAdapter.java @@ -0,0 +1,71 @@ +package org.gelecekbilimde.scienceplatform.ticket.port.adapter; + +import lombok.RequiredArgsConstructor; +import org.gelecekbilimde.scienceplatform.common.model.BasePage; +import org.gelecekbilimde.scienceplatform.common.model.BasePageable; +import org.gelecekbilimde.scienceplatform.ticket.model.Ticket; +import org.gelecekbilimde.scienceplatform.ticket.model.TicketFilter; +import org.gelecekbilimde.scienceplatform.ticket.model.entity.TicketEntity; +import org.gelecekbilimde.scienceplatform.ticket.model.mapper.TicketEntityToTicketMapper; +import org.gelecekbilimde.scienceplatform.ticket.model.mapper.TicketToEntityMapper; +import org.gelecekbilimde.scienceplatform.ticket.port.TicketReadPort; +import org.gelecekbilimde.scienceplatform.ticket.port.TicketSavePort; +import org.gelecekbilimde.scienceplatform.ticket.repository.TicketRepository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Optional; + +@Component +@RequiredArgsConstructor +class TicketAdapter implements TicketReadPort, TicketSavePort { + + private final TicketRepository ticketRepository; + + + private final TicketToEntityMapper ticketToEntityMapper = TicketToEntityMapper.initialize(); + private final TicketEntityToTicketMapper ticketEntityToDomainMapper = TicketEntityToTicketMapper.initialize(); + + + @Override + public BasePage findAll(final BasePageable basePageable, + final TicketFilter filter) { + + final Pageable pageable = basePageable.toPageable(); + + final Specification specification = Optional + .ofNullable(filter) + .map(TicketFilter::toSpecification) + .orElse(Specification.allOf()); + + final Page ticketEntitiesPage = ticketRepository + .findAll(specification, pageable); + + final List tickets = ticketEntityToDomainMapper + .map(ticketEntitiesPage.getContent()); + + return BasePage.of( + filter, + ticketEntitiesPage, + tickets + ); + } + + + @Override + public Optional findById(Long id) { + return ticketRepository.findById(id) + .map(ticketEntityToDomainMapper::map); + } + + + @Override + public void save(Ticket ticket) { + final TicketEntity ticketEntity = ticketToEntityMapper.map(ticket); + ticketRepository.save(ticketEntity); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/adapter/TicketCommentAdapter.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/adapter/TicketCommentAdapter.java new file mode 100644 index 00000000..6579dd09 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/port/adapter/TicketCommentAdapter.java @@ -0,0 +1,39 @@ +package org.gelecekbilimde.scienceplatform.ticket.port.adapter; + +import lombok.RequiredArgsConstructor; +import org.gelecekbilimde.scienceplatform.ticket.model.TicketComment; +import org.gelecekbilimde.scienceplatform.ticket.model.entity.TicketCommentEntity; +import org.gelecekbilimde.scienceplatform.ticket.model.mapper.TicketCommentEntityToDomainMapper; +import org.gelecekbilimde.scienceplatform.ticket.model.mapper.TicketCommentToEntityMapper; +import org.gelecekbilimde.scienceplatform.ticket.port.TicketCommentReadPort; +import org.gelecekbilimde.scienceplatform.ticket.port.TicketCommentSavePort; +import org.gelecekbilimde.scienceplatform.ticket.repository.TicketCommentRepository; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +@RequiredArgsConstructor +class TicketCommentAdapter implements TicketCommentReadPort, TicketCommentSavePort { + + private final TicketCommentRepository ticketCommentRepository; + + + private final TicketCommentToEntityMapper ticketCommentToEntityMapper = TicketCommentToEntityMapper.initialize(); + private final TicketCommentEntityToDomainMapper ticketCommentEntityToDomainMapper = TicketCommentEntityToDomainMapper.initialize(); + + + @Override + public List findAllByTicketId(final Long ticketId) { + final List ticketCommentEntities = ticketCommentRepository.findAllByTicketId(ticketId); + return ticketCommentEntityToDomainMapper.map(ticketCommentEntities); + } + + + @Override + public void save(final TicketComment ticketComment) { + final TicketCommentEntity ticketCommentEntity = ticketCommentToEntityMapper.map(ticketComment); + ticketCommentRepository.save(ticketCommentEntity); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/repository/TicketCommentRepository.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/repository/TicketCommentRepository.java new file mode 100644 index 00000000..4766c2c0 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/repository/TicketCommentRepository.java @@ -0,0 +1,12 @@ +package org.gelecekbilimde.scienceplatform.ticket.repository; + +import org.gelecekbilimde.scienceplatform.ticket.model.entity.TicketCommentEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface TicketCommentRepository extends JpaRepository { + + List findAllByTicketId(Long ticketId); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/repository/TicketMessageRepository.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/repository/TicketMessageRepository.java deleted file mode 100644 index 990d20a3..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/repository/TicketMessageRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.gelecekbilimde.scienceplatform.ticket.repository; - -import org.gelecekbilimde.scienceplatform.ticket.model.entity.TicketMessageEntity; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; - -public interface TicketMessageRepository extends JpaRepository, JpaSpecificationExecutor { -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/TicketCommentService.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/TicketCommentService.java new file mode 100644 index 00000000..fa6efde2 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/TicketCommentService.java @@ -0,0 +1,14 @@ +package org.gelecekbilimde.scienceplatform.ticket.service; + +import org.gelecekbilimde.scienceplatform.ticket.model.TicketComment; +import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketCommentAddRequest; + +import java.util.List; + +public interface TicketCommentService { + + List findAllByTicketId(Long ticketId); + + void add(Long ticketId, TicketCommentAddRequest request); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/TicketMessageService.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/TicketMessageService.java deleted file mode 100644 index 88aaac14..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/TicketMessageService.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.gelecekbilimde.scienceplatform.ticket.service; - -import org.gelecekbilimde.scienceplatform.common.model.response.PagingResponse; -import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketMessageCreateRequest; -import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketMessageRequest; -import org.gelecekbilimde.scienceplatform.ticket.model.response.TicketMessageResponse; - -public interface TicketMessageService { - - PagingResponse ticketMessageRead(TicketMessageRequest request); - - PagingResponse ticketMessageReadSelf(TicketMessageRequest request); - - TicketMessageResponse ticketMessageCreate(TicketMessageCreateRequest request); - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/TicketService.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/TicketService.java index 0568ba92..ebaad0bd 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/TicketService.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/TicketService.java @@ -1,21 +1,20 @@ package org.gelecekbilimde.scienceplatform.ticket.service; -import org.gelecekbilimde.scienceplatform.common.model.request.PagingRequest; -import org.gelecekbilimde.scienceplatform.common.model.response.PagingResponse; +import org.gelecekbilimde.scienceplatform.common.model.BasePage; import org.gelecekbilimde.scienceplatform.ticket.model.Ticket; import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketCreateRequest; +import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketListRequest; import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketUpdateRequest; -import org.gelecekbilimde.scienceplatform.ticket.model.response.TicketResponse; public interface TicketService { - PagingResponse ticketRead(PagingRequest request); + BasePage findAll(final TicketListRequest listRequest); - PagingResponse ticketReadSelf(PagingRequest request); + Ticket findById(Long id); - Ticket updateTicket(TicketUpdateRequest request); + void create(TicketCreateRequest createRequest); - Ticket ticketCreateSelf(TicketCreateRequest request); + void update(Long id, TicketUpdateRequest updateRequest); } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/impl/TicketCommentServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/impl/TicketCommentServiceImpl.java new file mode 100644 index 00000000..708394f4 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/impl/TicketCommentServiceImpl.java @@ -0,0 +1,60 @@ +package org.gelecekbilimde.scienceplatform.ticket.service.impl; + +import lombok.RequiredArgsConstructor; +import org.gelecekbilimde.scienceplatform.auth.model.Identity; +import org.gelecekbilimde.scienceplatform.ticket.exception.TicketNotFoundByIdException; +import org.gelecekbilimde.scienceplatform.ticket.model.Ticket; +import org.gelecekbilimde.scienceplatform.ticket.model.TicketComment; +import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketCommentAddRequest; +import org.gelecekbilimde.scienceplatform.ticket.port.TicketCommentReadPort; +import org.gelecekbilimde.scienceplatform.ticket.port.TicketCommentSavePort; +import org.gelecekbilimde.scienceplatform.ticket.port.TicketReadPort; +import org.gelecekbilimde.scienceplatform.ticket.service.TicketCommentService; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +class TicketCommentServiceImpl implements TicketCommentService { + + private final TicketCommentReadPort ticketCommentReadPort; + private final TicketCommentSavePort ticketCommentSavePort; + private final TicketReadPort ticketReadPort; + private final Identity identity; + + + @Override + public List findAllByTicketId(final Long ticketId) { + + this.validateTicketIdAndCurrentUserPermission(ticketId); + + return ticketCommentReadPort.findAllByTicketId(ticketId); + } + + @Override + public void add(final Long ticketId, final TicketCommentAddRequest request) { + + this.validateTicketIdAndCurrentUserPermission(ticketId); + + final TicketComment ticketComment = TicketComment.builder() + .ticketId(ticketId) + .userId(identity.getUserId()) + .content(request.getContent()) + .build(); + ticketCommentSavePort.save(ticketComment); + } + + private void validateTicketIdAndCurrentUserPermission(final Long ticketId) { + + final Ticket ticket = ticketReadPort.findById(ticketId) + .orElseThrow(() -> new TicketNotFoundByIdException(ticketId)); + + boolean isNotAdmin = !identity.isAdmin(); + boolean isNotOwner = !ticket.getUserId().equals(identity.getUserId()); + if (isNotAdmin && isNotOwner) { + throw new TicketNotFoundByIdException(ticketId); + } + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/impl/TicketMessageServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/impl/TicketMessageServiceImpl.java deleted file mode 100644 index 01213f0b..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/impl/TicketMessageServiceImpl.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.gelecekbilimde.scienceplatform.ticket.service.impl; - -import lombok.RequiredArgsConstructor; -import org.gelecekbilimde.scienceplatform.auth.model.Identity; -import org.gelecekbilimde.scienceplatform.common.model.BasePage; -import org.gelecekbilimde.scienceplatform.common.model.response.PagingResponse; -import org.gelecekbilimde.scienceplatform.ticket.model.entity.TicketMessageEntity; -import org.gelecekbilimde.scienceplatform.ticket.model.mapper.TicketMessageEntityToMessageResponseMapper; -import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketMessageCreateRequest; -import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketMessageRequest; -import org.gelecekbilimde.scienceplatform.ticket.model.response.TicketMessageResponse; -import org.gelecekbilimde.scienceplatform.ticket.repository.TicketMessageRepository; -import org.gelecekbilimde.scienceplatform.ticket.service.TicketMessageService; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -@RequiredArgsConstructor -class TicketMessageServiceImpl implements TicketMessageService { - - private final Identity identity; - - private final TicketMessageRepository ticketMessageRepository; - - private final TicketMessageEntityToMessageResponseMapper ticketMessageEntityToMessageResponseMapper = TicketMessageEntityToMessageResponseMapper.initialize(); - - - @Override - public PagingResponse ticketMessageRead(TicketMessageRequest request) { - Pageable pageable = request.getPageable().toPageable(); - Page messagePage = ticketMessageRepository.findAll(pageable); - List ticketResponses = ticketMessageEntityToMessageResponseMapper.map(messagePage.getContent()); - final BasePage posts = BasePage.of(messagePage, ticketResponses); - return PagingResponse.builder() - .of(posts) - .content(ticketMessageEntityToMessageResponseMapper.map(messagePage.getContent())) - .build(); - } - - @Override - public PagingResponse ticketMessageReadSelf(TicketMessageRequest request) { - Specification spec = (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("userId"), identity.getUserId()); - Page messagePage = ticketMessageRepository.findAll(spec, request.getPageable().toPageable()); - List ticketMessageRespons = ticketMessageEntityToMessageResponseMapper.map(messagePage.getContent()); - final BasePage messageResponsesPage = BasePage.of(messagePage, ticketMessageRespons); - return PagingResponse.builder() - .of(messageResponsesPage) - .content(ticketMessageEntityToMessageResponseMapper.map(messagePage.getContent())) - .build(); - } - - @Override - public TicketMessageResponse ticketMessageCreate(TicketMessageCreateRequest request) { - TicketMessageEntity message = TicketMessageEntity.builder().userId(identity.getUserId()).ticketId(request.getId()).message(request.getMessage()).build(); - TicketMessageEntity saveTicket = this.ticketMessageRepository.save(message); - return ticketMessageEntityToMessageResponseMapper.map(saveTicket); - } -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/impl/TicketServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/impl/TicketServiceImpl.java index 0ca9fefe..c21363da 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/impl/TicketServiceImpl.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/ticket/service/impl/TicketServiceImpl.java @@ -3,65 +3,92 @@ import lombok.RequiredArgsConstructor; import org.gelecekbilimde.scienceplatform.auth.model.Identity; import org.gelecekbilimde.scienceplatform.common.model.BasePage; -import org.gelecekbilimde.scienceplatform.common.model.request.PagingRequest; -import org.gelecekbilimde.scienceplatform.common.model.response.PagingResponse; +import org.gelecekbilimde.scienceplatform.ticket.exception.TicketAlreadyHasStatusException; +import org.gelecekbilimde.scienceplatform.ticket.exception.TicketNotFoundByIdException; import org.gelecekbilimde.scienceplatform.ticket.model.Ticket; -import org.gelecekbilimde.scienceplatform.ticket.model.entity.TicketEntity; -import org.gelecekbilimde.scienceplatform.ticket.model.mapper.TicketEntityToResponseMapper; -import org.gelecekbilimde.scienceplatform.ticket.model.mapper.TicketEntityToTicketMapper; +import org.gelecekbilimde.scienceplatform.ticket.model.TicketFilter; import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketCreateRequest; +import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketListRequest; import org.gelecekbilimde.scienceplatform.ticket.model.request.TicketUpdateRequest; -import org.gelecekbilimde.scienceplatform.ticket.model.response.TicketResponse; -import org.gelecekbilimde.scienceplatform.ticket.repository.TicketRepository; +import org.gelecekbilimde.scienceplatform.ticket.port.TicketReadPort; +import org.gelecekbilimde.scienceplatform.ticket.port.TicketSavePort; import org.gelecekbilimde.scienceplatform.ticket.service.TicketService; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; -import java.util.List; +import java.util.Optional; @Service @RequiredArgsConstructor class TicketServiceImpl implements TicketService { + private final TicketReadPort ticketReadPort; + private final TicketSavePort ticketSavePort; private final Identity identity; - private final TicketRepository ticketRepository; - - private final TicketEntityToResponseMapper ticketEntityToResponseMapper = TicketEntityToResponseMapper.initialize(); - private final TicketEntityToTicketMapper ticketEntityToTicketMapper = TicketEntityToTicketMapper.initialize(); @Override - public PagingResponse ticketRead(PagingRequest request) { - Pageable pageable = request.getPageable().toPageable(); - Page ticketPage = ticketRepository.findAll(pageable); - List ticketResponses = ticketEntityToResponseMapper.map(ticketPage.getContent()); - final BasePage posts = BasePage.of(ticketPage, ticketResponses); - return PagingResponse.builder().of(posts).content(ticketEntityToResponseMapper.map(ticketPage.getContent())).build(); + public BasePage findAll(final TicketListRequest listRequest) { + + if (identity.isAdmin()) { + return ticketReadPort.findAll(listRequest.getPageable(), listRequest.getFilter()); + } + + Optional.ofNullable(listRequest.getFilter()) + .ifPresentOrElse( + filter -> filter.addUserId(identity.getUserId()), + () -> { + TicketFilter filter = TicketFilter.builder().build(); + filter.addUserId(identity.getUserId()); + listRequest.setFilter(filter); + } + ); + + return ticketReadPort.findAll(listRequest.getPageable(), listRequest.getFilter()); } + @Override - public Ticket updateTicket(TicketUpdateRequest request) { - TicketEntity ticketEntity = ticketRepository.getReferenceById(request.getId()); // TODO : getReferenceById yerine findById kullanılmalı - ticketEntity.setStatus(request.getStatus()); - ticketRepository.save(ticketEntity); - return ticketEntityToTicketMapper.map(ticketEntity); + public Ticket findById(final Long id) { + + final Ticket ticket = ticketReadPort.findById(id) + .orElseThrow(() -> new TicketNotFoundByIdException(id)); + + boolean isNotAdmin = !identity.isAdmin(); + boolean isNotOwner = !ticket.getUserId().equals(identity.getUserId()); + if (isNotAdmin && isNotOwner) { + throw new TicketNotFoundByIdException(id); + } + + return ticket; } + @Override - public Ticket ticketCreateSelf(TicketCreateRequest request) { - TicketEntity ticketEntity = TicketEntity.builder().userId(identity.getUserId()).message(request.getMessage()).build(); - TicketEntity saveTicketEntity = this.ticketRepository.save(ticketEntity); - return ticketEntityToTicketMapper.map(saveTicketEntity); + public void create(final TicketCreateRequest createRequest) { + + final Ticket ticket = Ticket.builder() + .userId(identity.getUserId()) + .title(createRequest.getTitle()) + .description(createRequest.getDescription()) + .build(); + + ticketSavePort.save(ticket); } + @Override - public PagingResponse ticketReadSelf(PagingRequest request) { - Specification spec = (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("userId"), identity.getUserId()); - Page ticketPage = ticketRepository.findAll(spec, request.getPageable().toPageable()); - List ticketResponses = ticketEntityToResponseMapper.map(ticketPage.getContent()); - final BasePage posts = BasePage.of(ticketPage, ticketResponses); - return PagingResponse.builder().of(posts).content(ticketEntityToResponseMapper.map(ticketPage.getContent())).build(); + public void update(final Long id, + final TicketUpdateRequest updateRequest) { + + final Ticket ticket = ticketReadPort.findById(id) + .orElseThrow(() -> new TicketNotFoundByIdException(id)); + + if (updateRequest.getStatus() == ticket.getStatus()) { + throw new TicketAlreadyHasStatusException(ticket.getStatus()); + } + + ticket.setStatus(updateRequest.getStatus()); + ticketSavePort.save(ticket); } + } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/controller/UserFollowController.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/controller/UserFollowController.java index f30560fa..8630790d 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/user/controller/UserFollowController.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/controller/UserFollowController.java @@ -1,19 +1,17 @@ package org.gelecekbilimde.scienceplatform.user.controller; -import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.gelecekbilimde.scienceplatform.common.model.response.SuccessResponse; import org.gelecekbilimde.scienceplatform.user.model.User; import org.gelecekbilimde.scienceplatform.user.model.mapper.UserToUserFollowResponseMapper; -import org.gelecekbilimde.scienceplatform.user.model.request.UnfollowRequest; import org.gelecekbilimde.scienceplatform.user.model.response.UserFollowResponse; import org.gelecekbilimde.scienceplatform.user.service.UserFollowService; import org.hibernate.validator.constraints.UUID; +import org.springframework.security.access.prepost.PreAuthorize; 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; @@ -22,36 +20,34 @@ @Validated @RestController @RequiredArgsConstructor -@RequestMapping("/api/v1/users") +@RequestMapping("/api/v1") class UserFollowController { private final UserFollowService userFollowService; private final UserToUserFollowResponseMapper userToUserFollowResponseMapper = UserToUserFollowResponseMapper.initialize(); - @PostMapping("/{id}/follow/toggle") - SuccessResponse followToggle(@PathVariable @UUID String id) { - this.userFollowService.followToggle(id); - return SuccessResponse.success(); - } - @PostMapping("/followers/remove") - SuccessResponse removeFollowers(@RequestBody @Valid UnfollowRequest request) { - this.userFollowService.removeFollower(request); - return SuccessResponse.success(); + @GetMapping("/user/{id}/followings") + SuccessResponse> findAllFollowings(@PathVariable @UUID String id) { + List users = this.userFollowService.findAllFollowings(id); + List userFollowResponses = userToUserFollowResponseMapper.map(users); + return SuccessResponse.success(userFollowResponses); } - @GetMapping("/{id}/followers") + + @GetMapping("/user/{id}/followers") SuccessResponse> findAllFollowers(@PathVariable @UUID String id) { List users = this.userFollowService.findAllFollowers(id); List userFollowResponses = userToUserFollowResponseMapper.map(users); return SuccessResponse.success(userFollowResponses); } - @GetMapping("/{id}/followings") - SuccessResponse> findAllFollowings(@PathVariable @UUID String id) { - List users = this.userFollowService.findAllFollowings(id); - List userFollowResponses = userToUserFollowResponseMapper.map(users); - return SuccessResponse.success(userFollowResponses); + + @PostMapping("/user/{id}/follow/toggle") + @PreAuthorize("hasAnyAuthority('user:follow', 'user:unfollow')") + SuccessResponse followToggle(@PathVariable @UUID String id) { + this.userFollowService.followToggle(id); + return SuccessResponse.success(); } } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/exception/UserAlreadyUnfollowedException.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/exception/UserAlreadyUnfollowedException.java deleted file mode 100644 index 01b7e465..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/user/exception/UserAlreadyUnfollowedException.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.gelecekbilimde.scienceplatform.user.exception; - -import org.gelecekbilimde.scienceplatform.common.exception.AbstractConflictException; - -import java.io.Serial; - -public class UserAlreadyUnfollowedException extends AbstractConflictException { - - @Serial - private static final long serialVersionUID = -5943822734840037155L; - - public UserAlreadyUnfollowedException(String followerUserId, String followedUserId) { - super("user with id " + followerUserId + " already unfollowed user with id " + followedUserId); - } - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/exception/UserCannotFollowItselfException.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/exception/UserCannotFollowItselfException.java new file mode 100644 index 00000000..33cbce9a --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/exception/UserCannotFollowItselfException.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.user.exception; + +import org.gelecekbilimde.scienceplatform.common.exception.AbstractConflictException; + +import java.io.Serial; + +public final class UserCannotFollowItselfException extends AbstractConflictException { + + @Serial + private static final long serialVersionUID = -1651758308998005837L; + + public UserCannotFollowItselfException(String userId) { + super("user cannot follow itself by userId:" + userId); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/User.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/User.java index 3f0a5cf6..1cdd862c 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/User.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/User.java @@ -4,6 +4,7 @@ import lombok.Getter; import lombok.Setter; import lombok.experimental.SuperBuilder; +import org.gelecekbilimde.scienceplatform.auth.model.Role; import org.gelecekbilimde.scienceplatform.common.model.BaseDomainModel; import org.gelecekbilimde.scienceplatform.user.model.enums.UserDegree; import org.gelecekbilimde.scienceplatform.user.model.enums.UserGender; @@ -19,6 +20,7 @@ public class User extends BaseDomainModel { private String id; private String email; + private String password; private String firstName; private String lastName; private String avatarPath; @@ -27,5 +29,16 @@ public class User extends BaseDomainModel { private UserDegree degree; private UserGender gender; private UserStatus status; + private Role role; + + + public boolean isVerified() { + return this.status == UserStatus.VERIFIED; + } + + + public void verify() { + this.status = UserStatus.VERIFIED; + } } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/UserFollow.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/UserFollow.java new file mode 100644 index 00000000..4484ea7a --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/UserFollow.java @@ -0,0 +1,19 @@ +package org.gelecekbilimde.scienceplatform.user.model; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.SuperBuilder; +import org.gelecekbilimde.scienceplatform.common.model.BaseDomainModel; + +@Getter +@Setter +@SuperBuilder +@EqualsAndHashCode(callSuper = true) +public class UserFollow extends BaseDomainModel { + + private Long id; + private User follower; + private User followed; + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/UserVerification.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/UserVerification.java new file mode 100644 index 00000000..7096ecf8 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/UserVerification.java @@ -0,0 +1,30 @@ +package org.gelecekbilimde.scienceplatform.user.model; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.SuperBuilder; +import org.gelecekbilimde.scienceplatform.common.model.BaseDomainModel; +import org.gelecekbilimde.scienceplatform.user.model.enums.UserVerificationStatus; + +@Getter +@Setter +@SuperBuilder +@EqualsAndHashCode(callSuper = true) +public class UserVerification extends BaseDomainModel { + + private String id; + private User user; + private UserVerificationStatus status; + + + public void complete() { + this.status = UserVerificationStatus.COMPLETED; + } + + + public boolean isCompleted() { + return this.status == UserVerificationStatus.COMPLETED; + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/entity/UserEntity.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/entity/UserEntity.java index c0c1bba3..9c19af83 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/entity/UserEntity.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/entity/UserEntity.java @@ -100,14 +100,4 @@ public class UserEntity extends BaseEntity { @OneToMany(mappedBy = "userEntity", cascade = CascadeType.ALL) private List postEntity; - - public void verify() { - this.status = UserStatus.VERIFIED; - } - - - public boolean isVerified() { - return this.status == UserStatus.VERIFIED; - } - } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/entity/UserFollowEntity.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/entity/UserFollowEntity.java index e550389a..ba14c4dd 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/entity/UserFollowEntity.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/entity/UserFollowEntity.java @@ -1,7 +1,18 @@ package org.gelecekbilimde.scienceplatform.user.model.entity; -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.OneToOne; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; import org.gelecekbilimde.scienceplatform.common.model.entity.BaseEntity; @Entity @@ -18,10 +29,12 @@ public class UserFollowEntity extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(name = "follower_user_id") - private String followerUserId; + @OneToOne + @JoinColumn(name = "follower_user_id") + private UserEntity follower; - @Column(name = "followed_user_id") - private String followedUserId; + @OneToOne + @JoinColumn(name = "followed_user_id") + private UserEntity followed; } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/entity/UserVerificationEntity.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/entity/UserVerificationEntity.java index 047a8e58..ebcdeb87 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/entity/UserVerificationEntity.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/entity/UserVerificationEntity.java @@ -7,6 +7,8 @@ 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 lombok.AllArgsConstructor; import lombok.Getter; @@ -30,21 +32,12 @@ public class UserVerificationEntity extends BaseEntity { @GeneratedValue(strategy = GenerationType.UUID) private String id; - @Column(name = "user_id") - private String userId; + @OneToOne + @JoinColumn(name = "user_id") + private UserEntity user; @Enumerated(EnumType.STRING) @Column(name = "status") private UserVerificationStatus status; - - public void complete() { - this.status = UserVerificationStatus.COMPLETED; - } - - - public boolean isCompleted() { - return this.status == UserVerificationStatus.COMPLETED; - } - } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserFollowEntityToDomainMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserFollowEntityToDomainMapper.java new file mode 100644 index 00000000..d9f8e5bc --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserFollowEntityToDomainMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.user.model.mapper; + +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.gelecekbilimde.scienceplatform.user.model.UserFollow; +import org.gelecekbilimde.scienceplatform.user.model.entity.UserFollowEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface UserFollowEntityToDomainMapper extends BaseMapper { + + static UserFollowEntityToDomainMapper initialize() { + return Mappers.getMapper(UserFollowEntityToDomainMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserFollowToEntityMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserFollowToEntityMapper.java new file mode 100644 index 00000000..9d91509f --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserFollowToEntityMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.user.model.mapper; + +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.gelecekbilimde.scienceplatform.user.model.UserFollow; +import org.gelecekbilimde.scienceplatform.user.model.entity.UserFollowEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface UserFollowToEntityMapper extends BaseMapper { + + static UserFollowToEntityMapper initialize() { + return Mappers.getMapper(UserFollowToEntityMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserToEntityMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserToEntityMapper.java new file mode 100644 index 00000000..2b353319 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserToEntityMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.user.model.mapper; + +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.gelecekbilimde.scienceplatform.user.model.User; +import org.gelecekbilimde.scienceplatform.user.model.entity.UserEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface UserToEntityMapper extends BaseMapper { + + static UserToEntityMapper initialize() { + return Mappers.getMapper(UserToEntityMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserVerificationEntityToDomainMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserVerificationEntityToDomainMapper.java new file mode 100644 index 00000000..f4fedf11 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserVerificationEntityToDomainMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.user.model.mapper; + +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.gelecekbilimde.scienceplatform.user.model.UserVerification; +import org.gelecekbilimde.scienceplatform.user.model.entity.UserVerificationEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface UserVerificationEntityToDomainMapper extends BaseMapper { + + static UserVerificationEntityToDomainMapper initialize() { + return Mappers.getMapper(UserVerificationEntityToDomainMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserVerificationToEntityMapper.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserVerificationToEntityMapper.java new file mode 100644 index 00000000..8625e231 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/mapper/UserVerificationToEntityMapper.java @@ -0,0 +1,16 @@ +package org.gelecekbilimde.scienceplatform.user.model.mapper; + +import org.gelecekbilimde.scienceplatform.common.model.mapper.BaseMapper; +import org.gelecekbilimde.scienceplatform.user.model.UserVerification; +import org.gelecekbilimde.scienceplatform.user.model.entity.UserVerificationEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface UserVerificationToEntityMapper extends BaseMapper { + + static UserVerificationToEntityMapper initialize() { + return Mappers.getMapper(UserVerificationToEntityMapper.class); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/request/UnfollowRequest.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/request/UnfollowRequest.java deleted file mode 100644 index 6edc3232..00000000 --- a/src/main/java/org/gelecekbilimde/scienceplatform/user/model/request/UnfollowRequest.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.gelecekbilimde.scienceplatform.user.model.request; - -import jakarta.validation.constraints.NotBlank; -import lombok.Getter; -import lombok.Setter; -import org.hibernate.validator.constraints.UUID; - -@Getter -@Setter -public class UnfollowRequest { - - @UUID - @NotBlank - private String followerId; - -} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/auth/model/response/UserFollowResponse.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/model/response/UserFollowResponse.java similarity index 100% rename from src/main/java/org/gelecekbilimde/scienceplatform/auth/model/response/UserFollowResponse.java rename to src/main/java/org/gelecekbilimde/scienceplatform/user/model/response/UserFollowResponse.java diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserFollowDeletePort.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserFollowDeletePort.java new file mode 100644 index 00000000..30726afb --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserFollowDeletePort.java @@ -0,0 +1,9 @@ +package org.gelecekbilimde.scienceplatform.user.port; + +import org.gelecekbilimde.scienceplatform.user.model.UserFollow; + +public interface UserFollowDeletePort { + + void delete(UserFollow userFollow); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserFollowReadPort.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserFollowReadPort.java new file mode 100644 index 00000000..d341b32f --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserFollowReadPort.java @@ -0,0 +1,17 @@ +package org.gelecekbilimde.scienceplatform.user.port; + +import org.gelecekbilimde.scienceplatform.user.model.User; +import org.gelecekbilimde.scienceplatform.user.model.UserFollow; + +import java.util.List; +import java.util.Optional; + +public interface UserFollowReadPort { + + List findAllByFollowed(User followed); + + List findAllByFollower(User follower); + + Optional findByFollowedAndFollower(User followed, User follower); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserFollowSavePort.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserFollowSavePort.java new file mode 100644 index 00000000..10b4f70e --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserFollowSavePort.java @@ -0,0 +1,9 @@ +package org.gelecekbilimde.scienceplatform.user.port; + +import org.gelecekbilimde.scienceplatform.user.model.UserFollow; + +public interface UserFollowSavePort { + + void save(UserFollow userFollow); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserReadPort.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserReadPort.java new file mode 100644 index 00000000..d39ebedb --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserReadPort.java @@ -0,0 +1,15 @@ +package org.gelecekbilimde.scienceplatform.user.port; + +import org.gelecekbilimde.scienceplatform.user.model.User; + +import java.util.Optional; + +public interface UserReadPort { + + Optional findById(String id); + + Optional findByEmail(String email); + + boolean existsByEmail(String email); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserSavePort.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserSavePort.java new file mode 100644 index 00000000..169a0fc9 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserSavePort.java @@ -0,0 +1,9 @@ +package org.gelecekbilimde.scienceplatform.user.port; + +import org.gelecekbilimde.scienceplatform.user.model.User; + +public interface UserSavePort { + + User save(User user); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserVerificationReadPort.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserVerificationReadPort.java new file mode 100644 index 00000000..99d91f5c --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserVerificationReadPort.java @@ -0,0 +1,11 @@ +package org.gelecekbilimde.scienceplatform.user.port; + +import org.gelecekbilimde.scienceplatform.user.model.UserVerification; + +import java.util.Optional; + +public interface UserVerificationReadPort { + + Optional findById(String id); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserVerificationSavePort.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserVerificationSavePort.java new file mode 100644 index 00000000..5cf27680 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/UserVerificationSavePort.java @@ -0,0 +1,9 @@ +package org.gelecekbilimde.scienceplatform.user.port; + +import org.gelecekbilimde.scienceplatform.user.model.UserVerification; + +public interface UserVerificationSavePort { + + UserVerification save(UserVerification userVerification); + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/port/adapter/UserAdapter.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/adapter/UserAdapter.java new file mode 100644 index 00000000..65a3d573 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/adapter/UserAdapter.java @@ -0,0 +1,53 @@ +package org.gelecekbilimde.scienceplatform.user.port.adapter; + +import lombok.RequiredArgsConstructor; +import org.gelecekbilimde.scienceplatform.user.model.User; +import org.gelecekbilimde.scienceplatform.user.model.entity.UserEntity; +import org.gelecekbilimde.scienceplatform.user.model.mapper.UserEntityToUserMapper; +import org.gelecekbilimde.scienceplatform.user.model.mapper.UserToEntityMapper; +import org.gelecekbilimde.scienceplatform.user.port.UserReadPort; +import org.gelecekbilimde.scienceplatform.user.port.UserSavePort; +import org.gelecekbilimde.scienceplatform.user.repository.UserRepository; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +@Component +@RequiredArgsConstructor +class UserAdapter implements UserReadPort, UserSavePort { + + private final UserRepository userRepository; + + + private final UserEntityToUserMapper userEntityToUserMapper = UserEntityToUserMapper.initialize(); + private final UserToEntityMapper userToEntityMapper = UserToEntityMapper.initialize(); + + + @Override + public Optional findById(final String id) { + return userRepository.findById(id) + .map(userEntityToUserMapper::map); + } + + + @Override + public Optional findByEmail(final String email) { + return userRepository.findByEmail(email) + .map(userEntityToUserMapper::map); + } + + + @Override + public boolean existsByEmail(final String email) { + return userRepository.existsByEmail(email); + } + + + @Override + public User save(User user) { + final UserEntity userEntity = userToEntityMapper.map(user); + final UserEntity savedUserEntity = userRepository.save(userEntity); + return userEntityToUserMapper.map(savedUserEntity); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/port/adapter/UserFollowAdapter.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/adapter/UserFollowAdapter.java new file mode 100644 index 00000000..12ca97a0 --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/adapter/UserFollowAdapter.java @@ -0,0 +1,75 @@ +package org.gelecekbilimde.scienceplatform.user.port.adapter; + +import lombok.RequiredArgsConstructor; +import org.gelecekbilimde.scienceplatform.user.model.User; +import org.gelecekbilimde.scienceplatform.user.model.UserFollow; +import org.gelecekbilimde.scienceplatform.user.model.entity.UserEntity; +import org.gelecekbilimde.scienceplatform.user.model.entity.UserFollowEntity; +import org.gelecekbilimde.scienceplatform.user.model.mapper.UserFollowEntityToDomainMapper; +import org.gelecekbilimde.scienceplatform.user.model.mapper.UserFollowToEntityMapper; +import org.gelecekbilimde.scienceplatform.user.model.mapper.UserToEntityMapper; +import org.gelecekbilimde.scienceplatform.user.port.UserFollowDeletePort; +import org.gelecekbilimde.scienceplatform.user.port.UserFollowReadPort; +import org.gelecekbilimde.scienceplatform.user.port.UserFollowSavePort; +import org.gelecekbilimde.scienceplatform.user.repository.UserFollowRepository; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Optional; + +@Component +@RequiredArgsConstructor +class UserFollowAdapter implements UserFollowReadPort, UserFollowSavePort, UserFollowDeletePort { + + private final UserFollowRepository userFollowRepository; + + private final UserToEntityMapper userToEntityMapper = UserToEntityMapper.initialize(); + private final UserFollowEntityToDomainMapper userFollowEntityToDomainMapper = UserFollowEntityToDomainMapper.initialize(); + private final UserFollowToEntityMapper userFollowToEntityMapper = UserFollowToEntityMapper.initialize(); + + + @Override + public List findAllByFollowed(User followed) { + final UserEntity followedEntity = userToEntityMapper.map(followed); + return userFollowRepository.findAllByFollowed(followedEntity) + .stream() + .map(userFollowEntityToDomainMapper::map) + .toList(); + } + + + @Override + public List findAllByFollower(User follower) { + final UserEntity followerEntity = userToEntityMapper.map(follower); + return userFollowRepository.findAllByFollower(followerEntity) + .stream() + .map(userFollowEntityToDomainMapper::map) + .toList(); + } + + + @Override + public Optional findByFollowedAndFollower(final User followed, + final User follower) { + + final UserEntity followedEntity = userToEntityMapper.map(followed); + final UserEntity followerEntity = userToEntityMapper.map(follower); + return userFollowRepository.findByFollowedAndFollower(followedEntity, followerEntity) + .map(userFollowEntityToDomainMapper::map); + } + + + @Override + public void save(final UserFollow userFollow) { + final UserFollowEntity userFollowEntity = userFollowToEntityMapper.map(userFollow); + userFollowRepository.save(userFollowEntity); + } + + + @Override + public void delete(final UserFollow userFollow) { + final UserFollowEntity userFollowEntity = userFollowToEntityMapper.map(userFollow); + userFollowRepository.delete(userFollowEntity); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/port/adapter/UserVerificationAdapter.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/adapter/UserVerificationAdapter.java new file mode 100644 index 00000000..36ac38ad --- /dev/null +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/port/adapter/UserVerificationAdapter.java @@ -0,0 +1,40 @@ +package org.gelecekbilimde.scienceplatform.user.port.adapter; + +import lombok.RequiredArgsConstructor; +import org.gelecekbilimde.scienceplatform.user.model.UserVerification; +import org.gelecekbilimde.scienceplatform.user.model.entity.UserVerificationEntity; +import org.gelecekbilimde.scienceplatform.user.model.mapper.UserVerificationEntityToDomainMapper; +import org.gelecekbilimde.scienceplatform.user.model.mapper.UserVerificationToEntityMapper; +import org.gelecekbilimde.scienceplatform.user.port.UserVerificationReadPort; +import org.gelecekbilimde.scienceplatform.user.port.UserVerificationSavePort; +import org.gelecekbilimde.scienceplatform.user.repository.UserVerificationRepository; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +@Component +@RequiredArgsConstructor +class UserVerificationAdapter implements UserVerificationReadPort, UserVerificationSavePort { + + private final UserVerificationRepository userVerificationRepository; + + + private final UserVerificationEntityToDomainMapper userVerificationEntityToDomainMapper = UserVerificationEntityToDomainMapper.initialize(); + private final UserVerificationToEntityMapper userVerificationToEntityMapper = UserVerificationToEntityMapper.initialize(); + + + @Override + public Optional findById(final String id) { + return userVerificationRepository.findById(id) + .map(userVerificationEntityToDomainMapper::map); + } + + + @Override + public UserVerification save(final UserVerification userVerification) { + final UserVerificationEntity userVerificationEntity = userVerificationToEntityMapper.map(userVerification); + final UserVerificationEntity savedUserVerificationEntity = userVerificationRepository.save(userVerificationEntity); + return userVerificationEntityToDomainMapper.map(savedUserVerificationEntity); + } + +} diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/repository/UserFollowRepository.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/repository/UserFollowRepository.java index 60f36ab5..6bef50b9 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/user/repository/UserFollowRepository.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/repository/UserFollowRepository.java @@ -1,12 +1,18 @@ package org.gelecekbilimde.scienceplatform.user.repository; +import org.gelecekbilimde.scienceplatform.user.model.entity.UserEntity; import org.gelecekbilimde.scienceplatform.user.model.entity.UserFollowEntity; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; import java.util.Optional; public interface UserFollowRepository extends JpaRepository { - Optional findByFollowedUserIdAndFollowerUserId(String followedUserId, String followerUserId); + List findAllByFollowed(UserEntity followed); + + List findAllByFollower(UserEntity follower); + + Optional findByFollowedAndFollower(UserEntity followed, UserEntity follower); } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/service/UserEmailService.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/service/UserEmailService.java index 7727fd6a..a65d5c75 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/user/service/UserEmailService.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/service/UserEmailService.java @@ -2,8 +2,8 @@ public interface UserEmailService { - void sendVerifyMessage(String email, String verificationId); + void sendVerification(String email, String verificationId); - void sendWelcomeMessage(String email); + void sendWelcome(String email); } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/service/UserFollowService.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/service/UserFollowService.java index 04593cc4..64092f83 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/user/service/UserFollowService.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/service/UserFollowService.java @@ -1,7 +1,6 @@ package org.gelecekbilimde.scienceplatform.user.service; import org.gelecekbilimde.scienceplatform.user.model.User; -import org.gelecekbilimde.scienceplatform.user.model.request.UnfollowRequest; import java.util.List; @@ -13,6 +12,4 @@ public interface UserFollowService { void followToggle(String id); - void removeFollower(UnfollowRequest request); - } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/service/impl/UserEmailServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/service/impl/UserEmailServiceImpl.java index d252d7f4..bbedc010 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/user/service/impl/UserEmailServiceImpl.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/service/impl/UserEmailServiceImpl.java @@ -1,12 +1,14 @@ package org.gelecekbilimde.scienceplatform.user.service.impl; import lombok.RequiredArgsConstructor; -import org.gelecekbilimde.scienceplatform.common.mail.model.request.EmailSendRequest; -import org.gelecekbilimde.scienceplatform.common.mail.service.EmailService; +import org.gelecekbilimde.scienceplatform.common.model.enums.MailTemplate; +import org.gelecekbilimde.scienceplatform.common.model.request.MailSendRequest; +import org.gelecekbilimde.scienceplatform.common.service.MailService; import org.gelecekbilimde.scienceplatform.user.service.UserEmailService; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import java.util.List; import java.util.Map; @Service @@ -14,30 +16,36 @@ class UserEmailServiceImpl implements UserEmailService { @Value("${application.front-end.url}") - public String frontEndUrl; + private String frontEndUrl; - private final EmailService emailService; + private final MailService mailService; @Override - public void sendVerifyMessage(String email, String verificationId) { - Map templateVariables = Map.of( - "BASE_URL", frontEndUrl + "/auth/verify?verificationId=" + verificationId // todo frontendten url istenecek + public void sendVerification(final String email, + final String verificationId) { + + final Map parameters = Map.of( + "BASE_URL", frontEndUrl + "/auth/verify?verificationId=" + verificationId ); - EmailSendRequest emailSendRequest = EmailSendRequest.builder() - .to(email) - .templateFileName("user-verification.html") - .templateVariables(templateVariables) + + final MailSendRequest mailSendRequest = MailSendRequest.builder() + .to(List.of(email)) + .template(MailTemplate.USER_VERIFICATION) + .parameters(parameters) .build(); - emailService.send(emailSendRequest); + + mailService.send(mailSendRequest); } @Override - public void sendWelcomeMessage(String email) { - EmailSendRequest emailSendRequest = EmailSendRequest.builder() - .to(email) - .templateFileName("user-welcome.html") + public void sendWelcome(final String email) { + + final MailSendRequest mailSendRequest = MailSendRequest.builder() + .to(List.of(email)) + .template(MailTemplate.USER_WELCOME) .build(); - emailService.send(emailSendRequest); + + mailService.send(mailSendRequest); } } diff --git a/src/main/java/org/gelecekbilimde/scienceplatform/user/service/impl/UserFollowServiceImpl.java b/src/main/java/org/gelecekbilimde/scienceplatform/user/service/impl/UserFollowServiceImpl.java index b947ef84..2d878a6e 100644 --- a/src/main/java/org/gelecekbilimde/scienceplatform/user/service/impl/UserFollowServiceImpl.java +++ b/src/main/java/org/gelecekbilimde/scienceplatform/user/service/impl/UserFollowServiceImpl.java @@ -3,14 +3,13 @@ import lombok.RequiredArgsConstructor; import org.gelecekbilimde.scienceplatform.auth.exception.UserNotFoundByIdException; import org.gelecekbilimde.scienceplatform.auth.model.Identity; -import org.gelecekbilimde.scienceplatform.user.exception.UserAlreadyUnfollowedException; +import org.gelecekbilimde.scienceplatform.user.exception.UserCannotFollowItselfException; import org.gelecekbilimde.scienceplatform.user.model.User; -import org.gelecekbilimde.scienceplatform.user.model.entity.UserEntity; -import org.gelecekbilimde.scienceplatform.user.model.entity.UserFollowEntity; -import org.gelecekbilimde.scienceplatform.user.model.mapper.UserEntityToUserMapper; -import org.gelecekbilimde.scienceplatform.user.model.request.UnfollowRequest; -import org.gelecekbilimde.scienceplatform.user.repository.UserFollowRepository; -import org.gelecekbilimde.scienceplatform.user.repository.UserRepository; +import org.gelecekbilimde.scienceplatform.user.model.UserFollow; +import org.gelecekbilimde.scienceplatform.user.port.UserFollowDeletePort; +import org.gelecekbilimde.scienceplatform.user.port.UserFollowReadPort; +import org.gelecekbilimde.scienceplatform.user.port.UserFollowSavePort; +import org.gelecekbilimde.scienceplatform.user.port.UserReadPort; import org.gelecekbilimde.scienceplatform.user.service.UserFollowService; import org.springframework.stereotype.Service; @@ -19,70 +18,72 @@ @Service @RequiredArgsConstructor -public class UserFollowServiceImpl implements UserFollowService { +class UserFollowServiceImpl implements UserFollowService { + private final UserFollowReadPort userFollowReadPort; + private final UserFollowSavePort userFollowSavePort; + private final UserFollowDeletePort userFollowDeletePort; + private final UserReadPort userReadPort; private final Identity identity; - private final UserRepository userRepository; - private final UserFollowRepository userFollowRepository; - private final UserEntityToUserMapper userEntityToUserMapper = UserEntityToUserMapper.initialize(); + @Override - public List findAllFollowings(String id) { - final UserEntity userEntity = userRepository.findById(id) + public List findAllFollowings(final String id) { + + final User user = userReadPort.findById(id) .orElseThrow(() -> new UserNotFoundByIdException(id)); - return userEntityToUserMapper.map(userEntity.getFollowings()); + return userFollowReadPort.findAllByFollower(user) + .stream() + .map(UserFollow::getFollowed) + .toList(); } @Override - public List findAllFollowers(String id) { - final UserEntity userEntity = userRepository.findById(id) + public List findAllFollowers(final String id) { + + final User user = userReadPort.findById(id) .orElseThrow(() -> new UserNotFoundByIdException(id)); - return userEntityToUserMapper.map(userEntity.getFollowers()); + return userFollowReadPort.findAllByFollowed(user) + .stream() + .map(UserFollow::getFollower) + .toList(); } @Override - public void followToggle(String id) { - final UserEntity userEntity = userRepository.findById(id) + public void followToggle(final String id) { + + if (identity.getUserId().equals(id)) { + throw new UserCannotFollowItselfException(id); + } + + final User user = userReadPort.findById(id) .orElseThrow(() -> new UserNotFoundByIdException(id)); - Optional followerUserFromDatabase = userFollowRepository - .findByFollowedUserIdAndFollowerUserId(userEntity.getId(), identity.getUserId()); + Optional followerUserFromDatabase = userFollowReadPort + .findByFollowedAndFollower(user, User.builder().id(identity.getUserId()).build()); if (followerUserFromDatabase.isPresent()) { this.unfollowUser(followerUserFromDatabase.get()); return; } - this.followUser(userEntity); + this.followUser(user); } - private void unfollowUser(UserFollowEntity followerUserFromDatabase) { - userFollowRepository.delete(followerUserFromDatabase); + private void unfollowUser(UserFollow userFollow) { + userFollowDeletePort.delete(userFollow); } - private void followUser(UserEntity userEntity) { - UserFollowEntity userFollowEntity = UserFollowEntity.builder() - .followerUserId(identity.getUserId()) - .followedUserId(userEntity.getId()) + private void followUser(User user) { + UserFollow userFollow = UserFollow.builder() + .follower(User.builder().id(identity.getUserId()).build()) + .followed(user) .build(); - userFollowRepository.save(userFollowEntity); + userFollowSavePort.save(userFollow); } - - @Override - public void removeFollower(UnfollowRequest request) { - - final UserEntity userEntity = userRepository.findById(request.getFollowerId()) - .orElseThrow(() -> new UserNotFoundByIdException(request.getFollowerId())); - - final UserFollowEntity userFollowEntity = userFollowRepository - .findByFollowedUserIdAndFollowerUserId(identity.getUserId(), userEntity.getId()) - .orElseThrow(() -> new UserAlreadyUnfollowedException(userEntity.getId(), identity.getUserId())); - - userFollowRepository.delete(userFollowEntity); - } } diff --git a/src/main/resources/db/migration/V1__ddl.sql b/src/main/resources/db/migration/V1__ddl.sql index 53ebcf2a..1c011656 100644 --- a/src/main/resources/db/migration/V1__ddl.sql +++ b/src/main/resources/db/migration/V1__ddl.sql @@ -85,6 +85,7 @@ create table if not exists gb_user_follow updated_by varchar(255), updated_at timestamp(0), constraint u__gb_user_follow__follower_user_id__followed_user_id unique (follower_user_id, followed_user_id), + constraint c__gb_user_follow__follower_user_id__followed_user_id check (follower_user_id != followed_user_id), constraint fk__gb_user_follow__follower_user_id foreign key (follower_user_id) references gb_user (id), constraint fk__gb_user_follow__followed_user_id foreign key (followed_user_id) references gb_user (id) ); @@ -261,26 +262,25 @@ create table if not exists gb_invalid_token ); -create table if not exists gb_setting +create table if not exists gb_parameter ( id bigint generated always as identity primary key, - group_name varchar(100) not null, name varchar(100) not null, definition text, is_hidden boolean, created_by varchar(255) not null, created_at timestamp(0) not null, updated_by varchar(255), - updated_at timestamp(0), - constraint u__gb_setting__name__group_name unique (group_name, name) + updated_at timestamp(0) ); create table if not exists gb_ticket ( - id varchar(36) not null primary key, + id bigint generated always as identity primary key, user_id varchar(36) not null, - subject varchar(255) not null, + category varchar(255) not null, + title varchar(512) not null, description text not null, status varchar(50) not null, created_by varchar(255) not null, @@ -288,23 +288,25 @@ create table if not exists gb_ticket updated_by varchar(255), updated_at timestamp(0), constraint fk__gb_ticket__user_id foreign key (user_id) references gb_user (id), - constraint c__gb_ticket__subject check ( status in ('TECHNICAL', 'POST', 'YOUR_QUESTION_REQUESTS', 'FEEDBACK', - 'COLLABORATION', 'OTHER')), + constraint c__gb_ticket__category check ( category in ('TECHNICAL', 'POST', 'YOUR_QUESTION_REQUESTS', 'FEEDBACK', + 'COLLABORATION', 'OTHER')), constraint c__gb_ticket__status check ( status in ('OPEN', 'IN_PROGRESS', 'ON_HOLD', 'CLOSED', 'REOPENED', 'CANCELED', 'RESOLVED')) ); -create table if not exists gb_ticket_message +create table if not exists gb_ticket_comment ( id bigint generated always as identity primary key, - ticket_id varchar(36) not null, + ticket_id bigint not null, user_id varchar(36) not null, - message text, + content text, created_by varchar(255) not null, created_at timestamp(0) not null, updated_by varchar(255), - updated_at timestamp(0) + updated_at timestamp(0), + constraint fk__gb_ticket_message__ticket_id foreign key (ticket_id) references gb_ticket (id), + constraint fk__gb_ticket_message__user_id foreign key (user_id) references gb_user (id) ); diff --git a/src/main/resources/db/migration/V2__dml.sql b/src/main/resources/db/migration/V2__dml.sql index 5e1609d8..c92fdf86 100644 --- a/src/main/resources/db/migration/V2__dml.sql +++ b/src/main/resources/db/migration/V2__dml.sql @@ -46,18 +46,21 @@ insert into gb_permission (id, description, name, is_hidden, created_by, created values ('d16020f2-1331-4e2f-94aa-7f6d08b6e157', 'Yorum Beğenir', 'comment:like', false, 'gelecekbilimde', current_timestamp); insert into gb_permission (id, description, name, is_hidden, created_by, created_at) -values ('0150a560-8536-427e-8e76-fb1f6d41f5e7', 'Kendi Çağrısı Kayıtlarını Listeler', - 'self:ticket:read', false, 'gelecekbilimde', current_timestamp); -insert into gb_permission (id, description, name, is_hidden, created_by, created_at) values ('b7c4f0d1-3f0e-46aa-9c02-ee7e7cbf49bb', 'Bütün Çağrı Kayıtlarını Listeler', - 'ticket:read', false, 'gelecekbilimde', current_timestamp); + 'ticket:list', false, 'gelecekbilimde', current_timestamp); +insert into gb_permission (id, description, name, is_hidden, created_by, created_at) +values ('6270e6e9-28a4-4811-bf20-a7c4b7dc41b5', 'Çağrı Kaydının Detayını Görüntüler', + 'ticket:detail', false, 'gelecekbilimde', current_timestamp); insert into gb_permission (id, description, name, is_hidden, created_by, created_at) values ('1bb69fdf-d470-4c37-8075-58ff0fa0d19e', 'Çağrı Kaydı Oluşturur', - 'self:ticket:create', false, 'gelecekbilimde', current_timestamp); + 'ticket:create', false, 'gelecekbilimde', current_timestamp); insert into gb_permission (id, description, name, is_hidden, created_by, created_at) values ('7572d942-b048-40bf-8cf4-c7a87d9be586', 'Çağrı Kaydını Günceller', 'ticket:update', false, 'gelecekbilimde', current_timestamp); insert into gb_permission (id, description, name, is_hidden, created_by, created_at) +values ('08cc7245-ed0f-47ee-a892-702f000a2ab5', 'Çağrı Kaydına Yorum Ekler', + 'ticket:comment:add', false, 'gelecekbilimde', current_timestamp); +insert into gb_permission (id, description, name, is_hidden, created_by, created_at) values ('f8217f8d-8d67-496f-8761-53201e690078', 'Profil Düzenler', 'profile:edit', false, 'gelecekbilimde', current_timestamp); insert into gb_permission (id, description, name, is_hidden, created_by, created_at) @@ -79,6 +82,12 @@ insert into gb_permission (id, description, name, is_hidden, created_by, created values ('d7a49ea4-fae1-4dac-8e07-c1d823841b50', 'Kendi Adına Var Olan Rol Başvurusunu İptal Eder', 'role:application:cancel:self', false, 'gelecekbilimde', current_timestamp); insert into gb_permission (id, description, name, is_hidden, created_by, created_at) +values ('26474155-f207-45e9-8798-a4cdd9cf8f31', 'Kullanıcıyı Takip Eder', + 'user:follow', false, 'gelecekbilimde', current_timestamp); +insert into gb_permission (id, description, name, is_hidden, created_by, created_at) +values ('91e30d16-b9f7-40a2-a4f6-eecf3157aa74', 'Kullanıcıyı Takibi Bırakır', + 'user:unfollow', false, 'gelecekbilimde', current_timestamp); +insert into gb_permission (id, description, name, is_hidden, created_by, created_at) values ('5a32defb-14c0-44b2-b518-fb482ca768e6', 'Kategorileri Listeler', 'category:list', false, 'gelecekbilimde', current_timestamp); insert into gb_permission (id, description, name, is_hidden, created_by, created_at) @@ -95,7 +104,6 @@ values ('889c4c62-73c8-465f-a6e3-ee54ab790007', 'Kategori Siler', 'category:delete', false, 'gelecekbilimde', current_timestamp); - insert into gb_role_permission (role_id, permission_id) values ('c147b5c2-87f7-4bb7-a165-368f639d8c3c', '836e0a9c-b2bb-4ecf-bf8b-870ea7bb8bc7'); insert into gb_role_permission (role_id, permission_id) @@ -111,12 +119,20 @@ values ('c147b5c2-87f7-4bb7-a165-368f639d8c3c', '35bc91b4-3b92-4ff5-b204-439ef21 insert into gb_role_permission (role_id, permission_id) values ('c147b5c2-87f7-4bb7-a165-368f639d8c3c', 'b7c4f0d1-3f0e-46aa-9c02-ee7e7cbf49bb'); insert into gb_role_permission (role_id, permission_id) +values ('c147b5c2-87f7-4bb7-a165-368f639d8c3c', '6270e6e9-28a4-4811-bf20-a7c4b7dc41b5'); +insert into gb_role_permission (role_id, permission_id) values ('c147b5c2-87f7-4bb7-a165-368f639d8c3c', '7572d942-b048-40bf-8cf4-c7a87d9be586'); insert into gb_role_permission (role_id, permission_id) +values ('c147b5c2-87f7-4bb7-a165-368f639d8c3c', '08cc7245-ed0f-47ee-a892-702f000a2ab5'); +insert into gb_role_permission (role_id, permission_id) values ('c147b5c2-87f7-4bb7-a165-368f639d8c3c', '0352ee79-e844-4e91-968f-c9f3e4a27515'); insert into gb_role_permission (role_id, permission_id) values ('c147b5c2-87f7-4bb7-a165-368f639d8c3c', '31366d9d-5282-4fe2-9d45-4551e114bc7d'); insert into gb_role_permission (role_id, permission_id) +values ('c147b5c2-87f7-4bb7-a165-368f639d8c3c', '26474155-f207-45e9-8798-a4cdd9cf8f31'); +insert into gb_role_permission (role_id, permission_id) +values ('c147b5c2-87f7-4bb7-a165-368f639d8c3c', '91e30d16-b9f7-40a2-a4f6-eecf3157aa74'); +insert into gb_role_permission (role_id, permission_id) values ('c147b5c2-87f7-4bb7-a165-368f639d8c3c', '5a32defb-14c0-44b2-b518-fb482ca768e6'); insert into gb_role_permission (role_id, permission_id) values ('c147b5c2-87f7-4bb7-a165-368f639d8c3c', '9e25ae21-9b35-4511-bdd5-c0e2ec96b8d4'); @@ -138,18 +154,24 @@ VALUES ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', '6842cfea-0568-4970-af2e-bc9e3f7 INSERT INTO gb_role_permission (role_id, permission_id) VALUES ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', 'd16020f2-1331-4e2f-94aa-7f6d08b6e157'); insert into gb_role_permission (role_id, permission_id) -values ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', '01bc1089-bd27-4b41-bfde-8e63c988fec3'); -insert into gb_role_permission (role_id, permission_id) -values ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', '0150a560-8536-427e-8e76-fb1f6d41f5e7'); +values ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', '6270e6e9-28a4-4811-bf20-a7c4b7dc41b5'); insert into gb_role_permission (role_id, permission_id) values ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', '1bb69fdf-d470-4c37-8075-58ff0fa0d19e'); insert into gb_role_permission (role_id, permission_id) +values ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', '01bc1089-bd27-4b41-bfde-8e63c988fec3'); +insert into gb_role_permission (role_id, permission_id) +values ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', '08cc7245-ed0f-47ee-a892-702f000a2ab5'); +insert into gb_role_permission (role_id, permission_id) values ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', '5b27d86c-ae00-49c2-8adc-07ed762920ce'); insert into gb_role_permission (role_id, permission_id) values ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', 'e7c0ddb6-5371-449f-841e-65b14f53f200'); insert into gb_role_permission (role_id, permission_id) values ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', 'f8217f8d-8d67-496f-8761-53201e690078'); insert into gb_role_permission (role_id, permission_id) +values ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', '26474155-f207-45e9-8798-a4cdd9cf8f31'); +insert into gb_role_permission (role_id, permission_id) +values ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', '91e30d16-b9f7-40a2-a4f6-eecf3157aa74'); +insert into gb_role_permission (role_id, permission_id) values ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', '5a32defb-14c0-44b2-b518-fb482ca768e6'); insert into gb_role_permission (role_id, permission_id) values ('1ed82a25-d348-4576-b4e6-1f2a7c430ca7', '9e25ae21-9b35-4511-bdd5-c0e2ec96b8d4'); @@ -169,12 +191,14 @@ VALUES ('4d98a76c-9841-4aea-b296-2f27aa610b6c', '6842cfea-0568-4970-af2e-bc9e3f7 INSERT INTO gb_role_permission (role_id, permission_id) VALUES ('4d98a76c-9841-4aea-b296-2f27aa610b6c', 'd16020f2-1331-4e2f-94aa-7f6d08b6e157'); insert into gb_role_permission (role_id, permission_id) -values ('4d98a76c-9841-4aea-b296-2f27aa610b6c', '01bc1089-bd27-4b41-bfde-8e63c988fec3'); -insert into gb_role_permission (role_id, permission_id) -values ('4d98a76c-9841-4aea-b296-2f27aa610b6c', '0150a560-8536-427e-8e76-fb1f6d41f5e7'); +values ('4d98a76c-9841-4aea-b296-2f27aa610b6c', '6270e6e9-28a4-4811-bf20-a7c4b7dc41b5'); insert into gb_role_permission (role_id, permission_id) values ('4d98a76c-9841-4aea-b296-2f27aa610b6c', '1bb69fdf-d470-4c37-8075-58ff0fa0d19e'); insert into gb_role_permission (role_id, permission_id) +values ('4d98a76c-9841-4aea-b296-2f27aa610b6c', '01bc1089-bd27-4b41-bfde-8e63c988fec3'); +insert into gb_role_permission (role_id, permission_id) +values ('4d98a76c-9841-4aea-b296-2f27aa610b6c', '08cc7245-ed0f-47ee-a892-702f000a2ab5'); +insert into gb_role_permission (role_id, permission_id) values ('4d98a76c-9841-4aea-b296-2f27aa610b6c', '5b27d86c-ae00-49c2-8adc-07ed762920ce'); insert into gb_role_permission (role_id, permission_id) values ('4d98a76c-9841-4aea-b296-2f27aa610b6c', 'e7c0ddb6-5371-449f-841e-65b14f53f200'); @@ -186,6 +210,10 @@ insert into gb_role_permission (role_id, permission_id) values ('4d98a76c-9841-4aea-b296-2f27aa610b6c', 'd7a49ea4-fae1-4dac-8e07-c1d823841b50'); insert into gb_role_permission (role_id, permission_id) values ('4d98a76c-9841-4aea-b296-2f27aa610b6c', '2902d3c0-040e-47f6-b894-e72484252a0a'); +insert into gb_role_permission (role_id, permission_id) +values ('4d98a76c-9841-4aea-b296-2f27aa610b6c', '26474155-f207-45e9-8798-a4cdd9cf8f31'); +insert into gb_role_permission (role_id, permission_id) +values ('4d98a76c-9841-4aea-b296-2f27aa610b6c', '91e30d16-b9f7-40a2-a4f6-eecf3157aa74'); insert into gb_role_permission (role_id, permission_id) values ('e3a1a32d-fcd7-46f0-bb2b-201df6b2b808', '01bc1089-bd27-4b41-bfde-8e63c988fec3'); @@ -194,10 +222,12 @@ values ('e3a1a32d-fcd7-46f0-bb2b-201df6b2b808', '6842cfea-0568-4970-af2e-bc9e3f7 insert into gb_role_permission (role_id, permission_id) values ('e3a1a32d-fcd7-46f0-bb2b-201df6b2b808', 'd16020f2-1331-4e2f-94aa-7f6d08b6e157'); insert into gb_role_permission (role_id, permission_id) -values ('e3a1a32d-fcd7-46f0-bb2b-201df6b2b808', '0150a560-8536-427e-8e76-fb1f6d41f5e7'); +values ('e3a1a32d-fcd7-46f0-bb2b-201df6b2b808', '6270e6e9-28a4-4811-bf20-a7c4b7dc41b5'); insert into gb_role_permission (role_id, permission_id) values ('e3a1a32d-fcd7-46f0-bb2b-201df6b2b808', '1bb69fdf-d470-4c37-8075-58ff0fa0d19e'); insert into gb_role_permission (role_id, permission_id) +values ('e3a1a32d-fcd7-46f0-bb2b-201df6b2b808', '08cc7245-ed0f-47ee-a892-702f000a2ab5'); +insert into gb_role_permission (role_id, permission_id) values ('e3a1a32d-fcd7-46f0-bb2b-201df6b2b808', '5b27d86c-ae00-49c2-8adc-07ed762920ce'); insert into gb_role_permission (role_id, permission_id) values ('e3a1a32d-fcd7-46f0-bb2b-201df6b2b808', 'e7c0ddb6-5371-449f-841e-65b14f53f200'); @@ -209,7 +239,10 @@ insert into gb_role_permission (role_id, permission_id) values ('e3a1a32d-fcd7-46f0-bb2b-201df6b2b808', 'd7a49ea4-fae1-4dac-8e07-c1d823841b50'); insert into gb_role_permission (role_id, permission_id) values ('e3a1a32d-fcd7-46f0-bb2b-201df6b2b808', '2902d3c0-040e-47f6-b894-e72484252a0a'); - +insert into gb_role_permission (role_id, permission_id) +values ('e3a1a32d-fcd7-46f0-bb2b-201df6b2b808', '26474155-f207-45e9-8798-a4cdd9cf8f31'); +insert into gb_role_permission (role_id, permission_id) +values ('e3a1a32d-fcd7-46f0-bb2b-201df6b2b808', '91e30d16-b9f7-40a2-a4f6-eecf3157aa74'); insert into gb_category (order_number, parent_id, name, description, slug, icon, created_by, created_at) diff --git a/src/main/resources/static/mailtemplate/user-verification.html b/src/main/resources/static/mail/template/user-verification.html similarity index 98% rename from src/main/resources/static/mailtemplate/user-verification.html rename to src/main/resources/static/mail/template/user-verification.html index 56565084..603d791a 100644 --- a/src/main/resources/static/mailtemplate/user-verification.html +++ b/src/main/resources/static/mail/template/user-verification.html @@ -1,5 +1,5 @@ - + Hesabınızı Onaylayın! diff --git a/src/main/resources/static/mailtemplate/user-welcome.html b/src/main/resources/static/mail/template/user-welcome.html similarity index 98% rename from src/main/resources/static/mailtemplate/user-welcome.html rename to src/main/resources/static/mail/template/user-welcome.html index 9a5e4397..34399c5a 100644 --- a/src/main/resources/static/mailtemplate/user-welcome.html +++ b/src/main/resources/static/mail/template/user-welcome.html @@ -1,5 +1,5 @@ - + Gelecek Bilimde Ekibine Hoşgeldiniz!