-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from ShopSmartSG/feature/cor_design_pattern
Chain of Responsibility design pattern implementation
- Loading branch information
Showing
23 changed files
with
1,315 additions
and
598 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
src/main/java/sg/edu/nus/iss/shopsmart_backend/chains/Chain.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package sg.edu.nus.iss.shopsmart_backend.chains; | ||
|
||
import sg.edu.nus.iss.shopsmart_backend.model.ApiRequestResolver; | ||
import sg.edu.nus.iss.shopsmart_backend.model.ApiResponseResolver; | ||
|
||
import java.util.concurrent.CompletableFuture; | ||
|
||
public interface Chain { | ||
CompletableFuture<ApiResponseResolver> handleRequest(ApiRequestResolver request, String profileType); | ||
} |
77 changes: 77 additions & 0 deletions
77
src/main/java/sg/edu/nus/iss/shopsmart_backend/chains/GenerateOtpForLoginChain.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package sg.edu.nus.iss.shopsmart_backend.chains; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.databind.node.ObjectNode; | ||
import io.swagger.v3.core.util.Json; | ||
import lombok.Getter; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.stereotype.Service; | ||
import sg.edu.nus.iss.shopsmart_backend.handlers.CheckProfileExistsHandler; | ||
import sg.edu.nus.iss.shopsmart_backend.handlers.GenerateOtpHandler; | ||
import sg.edu.nus.iss.shopsmart_backend.handlers.Handler; | ||
import sg.edu.nus.iss.shopsmart_backend.model.ApiRequestResolver; | ||
import sg.edu.nus.iss.shopsmart_backend.model.ApiResponseResolver; | ||
import sg.edu.nus.iss.shopsmart_backend.service.ProfileService; | ||
import sg.edu.nus.iss.shopsmart_backend.utils.Constants; | ||
|
||
import java.util.concurrent.CompletableFuture; | ||
|
||
@Service | ||
public class GenerateOtpForLoginChain extends Constants implements Chain{ | ||
private static final Logger log = LoggerFactory.getLogger(GenerateOtpForLoginChain.class); | ||
private final ObjectMapper mapper = Json.mapper(); | ||
|
||
@Getter | ||
private final Handler handlerChain; | ||
private final ProfileService profileService; | ||
|
||
@Autowired | ||
public GenerateOtpForLoginChain(ProfileService profileService) { | ||
this.profileService = profileService; | ||
Handler checkProfileExistsHandler = new CheckProfileExistsHandler(profileService); | ||
Handler generateOtpHandler = new GenerateOtpHandler(profileService); | ||
|
||
generateOtpHandler.setNext(null); | ||
checkProfileExistsHandler.setNext(generateOtpHandler); | ||
|
||
this.handlerChain = checkProfileExistsHandler; | ||
} | ||
|
||
@Override | ||
public CompletableFuture<ApiResponseResolver> handleRequest(ApiRequestResolver apiRequestResolver, String profileType) { | ||
log.info("Starting GenerateOtpForLoginChain, for apiRequestResolver : {}, and profileType {}", apiRequestResolver, profileType); | ||
log.info("{} Generating OTP for profile login with requestObt : {}", apiRequestResolver.getLoggerString(), apiRequestResolver.getRequestBody()); | ||
ApiResponseResolver apiResponseResolver = new ApiResponseResolver(); | ||
ObjectNode data = mapper.createObjectNode(); | ||
JsonNode payload = apiRequestResolver.getRequestBody(); | ||
if(payload.isNull() || payload.isEmpty()){ | ||
log.info("{} No request body found for opt generation for login", apiRequestResolver.getLoggerString()); | ||
apiResponseResolver.setStatusCode(HttpStatus.BAD_REQUEST); // 400 bad request | ||
data.put(MESSAGE, "No request body found for otp generation for email"); | ||
apiResponseResolver.setRespData(data); | ||
return CompletableFuture.completedFuture(apiResponseResolver); | ||
} | ||
if(!payload.hasNonNull(EMAIL)){ | ||
log.info("{} No Email provided for generating OTP for login", apiRequestResolver.getLoggerString()); | ||
apiResponseResolver.setStatusCode(HttpStatus.BAD_REQUEST); // 400 bad request | ||
data.put(MESSAGE, "Email is required for generating OTP for login"); | ||
apiResponseResolver.setRespData(data); | ||
return CompletableFuture.completedFuture(apiResponseResolver); | ||
} | ||
String email = payload.get(EMAIL).asText(); | ||
if(ADMIN.equalsIgnoreCase(profileType) && !profileService.checkIfValidAdminEmailId(email)){ | ||
log.info("{} Email {} is not valid for admin, not authorized", apiRequestResolver.getLoggerString(), email); | ||
apiResponseResolver.setStatusCode(HttpStatus.UNAUTHORIZED); // 401 unauthorized | ||
data.put(MESSAGE, "Email is not authorized for admin OTP generation"); | ||
apiResponseResolver.setRespData(data); | ||
return CompletableFuture.completedFuture(apiResponseResolver); | ||
} | ||
apiRequestResolver.addParamValue(EMAIL, email); | ||
apiRequestResolver.addParamValue(NEEDS_USER_PROF, "true"); | ||
return handlerChain.handle(apiRequestResolver, profileType); | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
src/main/java/sg/edu/nus/iss/shopsmart_backend/chains/GenerateOtpForRegisterChain.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package sg.edu.nus.iss.shopsmart_backend.chains; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.databind.node.ObjectNode; | ||
import io.swagger.v3.core.util.Json; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.stereotype.Service; | ||
import sg.edu.nus.iss.shopsmart_backend.handlers.CheckProfileExistsHandler; | ||
import sg.edu.nus.iss.shopsmart_backend.handlers.GenerateOtpHandler; | ||
import sg.edu.nus.iss.shopsmart_backend.handlers.Handler; | ||
import sg.edu.nus.iss.shopsmart_backend.model.ApiRequestResolver; | ||
import sg.edu.nus.iss.shopsmart_backend.model.ApiResponseResolver; | ||
import sg.edu.nus.iss.shopsmart_backend.service.ProfileService; | ||
import sg.edu.nus.iss.shopsmart_backend.utils.Constants; | ||
|
||
import java.util.concurrent.CompletableFuture; | ||
|
||
@Service | ||
public class GenerateOtpForRegisterChain extends Constants implements Chain { | ||
private static final Logger log = LoggerFactory.getLogger(GenerateOtpForRegisterChain.class); | ||
private final ObjectMapper mapper = Json.mapper(); | ||
|
||
private final Handler handlerChain; | ||
private final ProfileService profileService; | ||
|
||
@Autowired | ||
public GenerateOtpForRegisterChain(ProfileService profileService) { | ||
this.profileService = profileService; | ||
Handler checkProfileExistsHandler = new CheckProfileExistsHandler(profileService); | ||
Handler generateOtpHandler = new GenerateOtpHandler(profileService); | ||
|
||
generateOtpHandler.setNext(null); | ||
checkProfileExistsHandler.setNext(generateOtpHandler); | ||
|
||
this.handlerChain = checkProfileExistsHandler; | ||
} | ||
|
||
@Override | ||
public CompletableFuture<ApiResponseResolver> handleRequest(ApiRequestResolver apiRequestResolver, String profileType) { | ||
log.info("Starting GenerateOtpForRegisterChain, for apiRequestResolver : {}, and profileType {}", apiRequestResolver, profileType); | ||
log.info("{} Generating OTP for profile registration with requestObt : {}", apiRequestResolver.getLoggerString(), apiRequestResolver.getRequestBody()); | ||
ApiResponseResolver apiResponseResolver = new ApiResponseResolver(); | ||
ObjectNode data = mapper.createObjectNode(); | ||
JsonNode payload = apiRequestResolver.getRequestBody(); | ||
if(payload.isNull() || payload.isEmpty()){ | ||
log.info("{} No request body found for fetching user id for email", apiRequestResolver.getLoggerString()); | ||
apiResponseResolver.setStatusCode(HttpStatus.BAD_REQUEST); // 400 bad request | ||
data.put(MESSAGE, "No request body found for otp generation for email"); | ||
apiResponseResolver.setRespData(data); | ||
return CompletableFuture.completedFuture(apiResponseResolver); | ||
} | ||
if(!payload.hasNonNull(EMAIL)){ | ||
log.info("{} No Email provided for generating OTP for registration", apiRequestResolver.getLoggerString()); | ||
apiResponseResolver.setStatusCode(HttpStatus.BAD_REQUEST); // 400 bad request | ||
data.put(MESSAGE, "Email is required for generating OTP for registration"); | ||
apiResponseResolver.setRespData(data); | ||
return CompletableFuture.completedFuture(apiResponseResolver); | ||
} | ||
String email = payload.get(EMAIL).asText(); | ||
if(ADMIN.equalsIgnoreCase(profileType) && !profileService.checkIfValidAdminEmailId(email)){ | ||
log.info("{} Email {} is not valid for admin, not authorized", apiRequestResolver.getLoggerString(), email); | ||
apiResponseResolver.setStatusCode(HttpStatus.UNAUTHORIZED); // 401 unauthorized | ||
data.put(MESSAGE, "Email is not authorized for admin OTP generation"); | ||
apiResponseResolver.setRespData(data); | ||
return CompletableFuture.completedFuture(apiResponseResolver); | ||
} | ||
apiRequestResolver.addParamValue(EMAIL, email); | ||
apiRequestResolver.addParamValue(NEEDS_USER_PROF, "false"); | ||
return handlerChain.handle(apiRequestResolver, profileType); | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
src/main/java/sg/edu/nus/iss/shopsmart_backend/chains/ValidateOtpAndLoginChain.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package sg.edu.nus.iss.shopsmart_backend.chains; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.databind.node.ObjectNode; | ||
import io.swagger.v3.core.util.Json; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.stereotype.Service; | ||
import sg.edu.nus.iss.shopsmart_backend.handlers.FetchUserIdForEmailHandler; | ||
import sg.edu.nus.iss.shopsmart_backend.handlers.Handler; | ||
import sg.edu.nus.iss.shopsmart_backend.handlers.ValidateOtpHandler; | ||
import sg.edu.nus.iss.shopsmart_backend.model.ApiRequestResolver; | ||
import sg.edu.nus.iss.shopsmart_backend.model.ApiResponseResolver; | ||
import sg.edu.nus.iss.shopsmart_backend.service.ProfileService; | ||
import sg.edu.nus.iss.shopsmart_backend.utils.Constants; | ||
|
||
import java.util.concurrent.CompletableFuture; | ||
|
||
@Service | ||
public class ValidateOtpAndLoginChain extends Constants implements Chain{ | ||
private static final Logger log = LoggerFactory.getLogger(ValidateOtpAndLoginChain.class); | ||
private final ObjectMapper mapper = Json.mapper(); | ||
|
||
private final Handler handlerChain; | ||
private final ProfileService profileService; | ||
|
||
@Autowired | ||
public ValidateOtpAndLoginChain(ProfileService profileService) { | ||
this.profileService = profileService; | ||
Handler validateOtpHandler = new ValidateOtpHandler(profileService); | ||
Handler fetchUserIdForEmailHandler = new FetchUserIdForEmailHandler(profileService); | ||
|
||
validateOtpHandler.setNext(fetchUserIdForEmailHandler); | ||
fetchUserIdForEmailHandler.setNext(null); | ||
|
||
this.handlerChain = validateOtpHandler; | ||
} | ||
|
||
@Override | ||
public CompletableFuture<ApiResponseResolver> handleRequest(ApiRequestResolver apiRequestResolver, String profileType){ | ||
log.info("Starting ValidateOtpAndLoginChain, for apiRequestResolver : {}, and profileType {}", apiRequestResolver, profileType); | ||
log.info("{} validating OTP for profile login with requestObt : {}", apiRequestResolver.getLoggerString(), apiRequestResolver.getRequestBody()); | ||
ApiResponseResolver apiResponseResolver = new ApiResponseResolver(); | ||
ObjectNode data = mapper.createObjectNode(); | ||
JsonNode payload = apiRequestResolver.getRequestBody(); | ||
if(payload.isNull() || payload.isEmpty()){ | ||
log.info("{} No request body found for OTP validation for login", apiRequestResolver.getLoggerString()); | ||
apiResponseResolver.setStatusCode(HttpStatus.BAD_REQUEST); // 400 bad request | ||
data.put(MESSAGE, "No request body found for otp validation of email"); | ||
apiResponseResolver.setRespData(data); | ||
return CompletableFuture.completedFuture(apiResponseResolver); | ||
} | ||
if(!payload.hasNonNull(EMAIL) || !payload.hasNonNull(OTP)){ | ||
log.info("{} No Email or OTP provided for validating OTP for login", apiRequestResolver.getLoggerString()); | ||
apiResponseResolver.setStatusCode(HttpStatus.BAD_REQUEST); // 400 bad request | ||
data.put(MESSAGE, "Email and OTP are required for validating OTP for login"); | ||
apiResponseResolver.setRespData(data); | ||
return CompletableFuture.completedFuture(apiResponseResolver); | ||
} | ||
String email = payload.get(EMAIL).asText(); | ||
String otp = payload.get(OTP).asText(); | ||
apiRequestResolver.addParamValue(EMAIL, email); | ||
apiRequestResolver.addParamValue(OTP, otp); | ||
return handlerChain.handle(apiRequestResolver, profileType); | ||
} | ||
} |
72 changes: 72 additions & 0 deletions
72
src/main/java/sg/edu/nus/iss/shopsmart_backend/chains/ValidateOtpAndRegisterChain.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package sg.edu.nus.iss.shopsmart_backend.chains; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.databind.node.ObjectNode; | ||
import io.swagger.v3.core.util.Json; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.stereotype.Service; | ||
import sg.edu.nus.iss.shopsmart_backend.handlers.CreateProfileHandler; | ||
import sg.edu.nus.iss.shopsmart_backend.handlers.FetchUserIdForEmailHandler; | ||
import sg.edu.nus.iss.shopsmart_backend.handlers.Handler; | ||
import sg.edu.nus.iss.shopsmart_backend.handlers.ValidateOtpHandler; | ||
import sg.edu.nus.iss.shopsmart_backend.model.ApiRequestResolver; | ||
import sg.edu.nus.iss.shopsmart_backend.model.ApiResponseResolver; | ||
import sg.edu.nus.iss.shopsmart_backend.service.ProfileService; | ||
import sg.edu.nus.iss.shopsmart_backend.utils.Constants; | ||
|
||
import java.util.concurrent.CompletableFuture; | ||
|
||
@Service | ||
public class ValidateOtpAndRegisterChain extends Constants implements Chain{ | ||
private static final Logger log = LoggerFactory.getLogger(ValidateOtpAndRegisterChain.class); | ||
private final ObjectMapper mapper = Json.mapper(); | ||
|
||
private final Handler handlerChain; | ||
private final ProfileService profileService; | ||
|
||
@Autowired | ||
public ValidateOtpAndRegisterChain(ProfileService profileService) { | ||
this.profileService = profileService; | ||
Handler validateOtpHandler = new ValidateOtpHandler(profileService); | ||
Handler createProfileHandler = new CreateProfileHandler(profileService); | ||
Handler fetchUserIdForEmailHandler = new FetchUserIdForEmailHandler(profileService); | ||
|
||
validateOtpHandler.setNext(createProfileHandler); | ||
createProfileHandler.setNext(fetchUserIdForEmailHandler); | ||
fetchUserIdForEmailHandler.setNext(null); | ||
|
||
this.handlerChain = validateOtpHandler; | ||
} | ||
|
||
@Override | ||
public CompletableFuture<ApiResponseResolver> handleRequest(ApiRequestResolver apiRequestResolver, String profileType){ | ||
log.info("Starting ValidateOtpAndRegisterChain, for apiRequestResolver : {}, and profileType {}", apiRequestResolver, profileType); | ||
log.info("{} validating OTP for profile register with requestObt : {}", apiRequestResolver.getLoggerString(), apiRequestResolver.getRequestBody()); | ||
ApiResponseResolver apiResponseResolver = new ApiResponseResolver(); | ||
ObjectNode data = mapper.createObjectNode(); | ||
JsonNode payload = apiRequestResolver.getRequestBody(); | ||
if(payload.isNull() || payload.isEmpty()){ | ||
log.info("{} No request body found for OTP validation for registration", apiRequestResolver.getLoggerString()); | ||
apiResponseResolver.setStatusCode(HttpStatus.BAD_REQUEST); // 400 bad request | ||
data.put(MESSAGE, "No request body found for otp validation of email"); | ||
apiResponseResolver.setRespData(data); | ||
return CompletableFuture.completedFuture(apiResponseResolver); | ||
} | ||
if(!payload.hasNonNull(EMAIL) || !payload.hasNonNull(OTP)){ | ||
log.info("{} No Email or OTP provided for validating OTP for registration", apiRequestResolver.getLoggerString()); | ||
apiResponseResolver.setStatusCode(HttpStatus.BAD_REQUEST); // 400 bad request | ||
data.put(MESSAGE, "Email and OTP are required for validating OTP for registration"); | ||
apiResponseResolver.setRespData(data); | ||
return CompletableFuture.completedFuture(apiResponseResolver); | ||
} | ||
String email = payload.get(EMAIL).asText(); | ||
String otp = payload.get(OTP).asText(); | ||
apiRequestResolver.addParamValue(EMAIL, email); | ||
apiRequestResolver.addParamValue(OTP, otp); | ||
return handlerChain.handle(apiRequestResolver, profileType); | ||
} | ||
} |
Oops, something went wrong.