Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion book-my-show/backend/java/bms-monolith/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ build/
!**/src/test/**/build/

### VS Code ###
.vscode/
.vscode
30 changes: 30 additions & 0 deletions book-my-show/backend/java/bms-monolith/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>


<dependency>
<groupId>org.projectlombok</groupId>
Expand All @@ -74,6 +84,26 @@
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.18.0</version> <!-- Use the latest version compatible with your project -->
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>


</dependencies>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.lbcc.bms.bms_monolith.common.constants;

public final class BMSErrorMessageConstants {
private BMSErrorMessageConstants() {
}

public static final String UNEXPECTED_ERROR_MESSAGE = "An unexpected error occurred";
public static final String UNEXPECTED_ERROR_CODE = "UNEXPECTED_ERROR";
public static final String EVENT_SERVICE_ERROR = "EVENT_SERVICE_ERROR";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.lbcc.bms.bms_monolith.common.constants;

public final class BMSSuccessMessageConstants {
private BMSSuccessMessageConstants() {
}

public static final String EVENT_SUCCESS_MESSAGE = "Events fetched successfully";
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ public abstract class BaseAuditingEntity {

@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column(columnDefinition = "CHAR(36)")
private UUID id;
@Column(columnDefinition = "CHAR(36)", updatable = false, nullable = false)
private String id;

@CreatedDate
@Column(updatable = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.FetchType;
import jakarta.persistence.Column;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
import jakarta.persistence.FetchType;
import jakarta.validation.constraints.NotNull;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.lbcc.bms.bms_monolith.common.enums.Genre;

Expand All @@ -25,6 +27,8 @@
@Table(name = "event_shows")
@Getter
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
public class EventShow extends BaseAuditingEntity {

@ElementCollection(targetClass = Genre.class)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.lbcc.bms.bms_monolith.common.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

import java.util.HashSet;
import java.util.Set;

@AllArgsConstructor
@SuperBuilder
@Data
@Entity
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@Table(name = "registered_users")
public class RegisteredUser extends BaseAuditingEntity {

@Column(length = 20)
private String username;

@Column(length = 25)
private String email;

@Column(columnDefinition = "CHAR(10)")
private String phone;

@Column(length = 20)
@JsonIgnore
private String password;

@Builder.Default
@Column(columnDefinition = "TINYINT(1)")
private Boolean isActive = true;

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "user_roles",
joinColumns = {@JoinColumn(name = "user_id")},
inverseJoinColumns = {@JoinColumn(name = "role_id")})
@Builder.Default
private Set<Role> roles = new HashSet<>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.lbcc.bms.bms_monolith.common.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.lbcc.bms.bms_monolith.common.enums.RoleType;

@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "roles")
public class Role extends BaseAuditingEntity {

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private RoleType label;

@Column(nullable = false, length = 50)
private String description;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import jakarta.persistence.ManyToOne;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.Column;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

import java.math.BigDecimal;
Expand All @@ -14,6 +16,8 @@
@Table(name = "seat_type_in_shows")
@Getter
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
public class SeatTypeInShow extends BaseAuditingEntity {

@ManyToOne
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.lbcc.bms.bms_monolith.common.enums;

public enum RoleType {
GUEST,
VENDOR,
ADMIN,
USER,
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@

import org.lbcc.bms.bms_monolith.common.constants.BMSConstants;
import org.lbcc.bms.bms_monolith.common.response.ApiErrorResponse;
import org.lbcc.bms.bms_monolith.security.uesrnamepassword.exeception.RoleNotFoundException;
import org.lbcc.bms.bms_monolith.security.uesrnamepassword.exeception.UserAlreadyExistsException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import java.util.ArrayList;
import java.util.List;

@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(Exception.class)
public ResponseEntity<ApiErrorResponse> handleGlobalException(Exception ex) {
return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, BMSConstants.UNEXPECTED_ERROR_MESSAGE, BMSConstants.UNEXPECTED_ERROR_CODE);
Expand All @@ -21,4 +28,47 @@ public static ResponseEntity<ApiErrorResponse> buildErrorResponse(HttpStatus sta
.build();
return ResponseEntity.status(status).body(errorResponse);
}

@ExceptionHandler(value = MethodArgumentNotValidException.class)
public ResponseEntity<ApiErrorResponse> MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException exception) {

List<String> errorMessage = new ArrayList<>();

exception.getBindingResult().getFieldErrors().forEach(error -> {
errorMessage.add(error.getDefaultMessage());
});
return ResponseEntity
.badRequest()
.body(
ApiErrorResponse.builder()
// .isSuccess(false)
.message("Registration Failed: Please provide valid data.")
.code(errorMessage.toString())
.build()
);
}

@ExceptionHandler(value = UserAlreadyExistsException.class)
public ResponseEntity<ApiErrorResponse> UserAlreadyExistsExceptionHandler(UserAlreadyExistsException exception) {
return ResponseEntity
.status(HttpStatus.CONFLICT)
.body(
ApiErrorResponse.builder()
// .isSuccess(false)
.message(exception.getMessage())
.build()
);
}

@ExceptionHandler(value = RoleNotFoundException.class)
public ResponseEntity<ApiErrorResponse> RoleNotFoundExceptionHandler(RoleNotFoundException exception) {
return ResponseEntity
.status(HttpStatus.NOT_FOUND)
.body(
ApiErrorResponse.builder()
.message(exception.getMessage())
.build()
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
@Getter
public class SeatInShowResponse {

private UUID seatTypeInShowId;
private String seatTypeInShowId;
private String bookingStatus;

// Constructors, Getters, and Setters

public SeatInShowResponse(UUID seatTypeInShowId, String bookingStatus) {
public SeatInShowResponse(String seatTypeInShowId, String bookingStatus) {
this.seatTypeInShowId = seatTypeInShowId;
this.bookingStatus = bookingStatus;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
@Getter
public class SeatTypeInShowResponse {

private UUID seatTypeId;
private String seatTypeId;
private String seatTypeName;
private BigDecimal price;

public SeatTypeInShowResponse(UUID seatTypeId, String seatTypeName, BigDecimal price) {
public SeatTypeInShowResponse(String seatTypeId, String seatTypeName, BigDecimal price) {
this.seatTypeId = seatTypeId;
this.seatTypeName = seatTypeName;
this.price = price;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.lbcc.bms.bms_monolith.security.uesrnamepassword.bootstrap;

import jakarta.transaction.Transactional;
import org.lbcc.bms.bms_monolith.common.entity.Role;
import org.lbcc.bms.bms_monolith.common.enums.RoleType;
import org.lbcc.bms.bms_monolith.security.uesrnamepassword.repository.RoleRepository;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

@Component
public class RoleDataSeeder {
private final RoleRepository roleRepository;

public RoleDataSeeder(RoleRepository roleRepository) {
this.roleRepository = roleRepository;
}

@EventListener
@Transactional
public void loadRoles(ContextRefreshedEvent event) {

List<RoleType> roles = Arrays.stream(RoleType.values()).toList();

for (RoleType roleType : roles) {
if (roleRepository.findByLabel(roleType) == null) {
Role role = new Role();
role.setId(UUID.randomUUID().toString());
role.setLabel(roleType);
role.setDescription(roleType.name());
role.setCreatedBy("system");
role.setCreatedDate(Instant.now());
roleRepository.save(role);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.lbcc.bms.bms_monolith.security.uesrnamepassword.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Component
public class AuthEntryPointJwt implements AuthenticationEntryPoint {

private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class);

@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException {
logger.error("Unauthorized error: {}", authException.getMessage());

response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

final Map<String, Object> body = new HashMap<>();
body.put("status", HttpServletResponse.SC_UNAUTHORIZED);
body.put("error", "Unauthorized");
body.put("message", authException.getMessage());
body.put("path", request.getServletPath());

final ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(response.getOutputStream(), body);
}
}
Loading