Skip to content

Commit

Permalink
System Tests Have Been Created for Admin User Auth Flows
Browse files Browse the repository at this point in the history
  • Loading branch information
agitrubard committed Aug 10, 2023
1 parent 90d28c6 commit d1baf87
Show file tree
Hide file tree
Showing 5 changed files with 360 additions and 0 deletions.
101 changes: 101 additions & 0 deletions src/test/java/com/ays/AbstractSystemTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.ays;

import com.ays.admin_user.model.entity.AdminUserEntityBuilder;
import com.ays.auth.config.AysTokenConfigurationParameter;
import com.ays.auth.model.AysToken;
import com.ays.auth.model.enums.AysTokenClaims;
import com.ays.common.util.AysRandomUtil;
import com.ays.parameter.model.AysParameter;
import com.ays.parameter.model.AysParameterBuilder;
import com.ays.parameter.service.AysParameterService;
import com.ays.user.model.entity.UserEntityBuilder;
import com.ays.util.AysTestData;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.time.DateUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.test.web.servlet.MockMvc;

import java.util.Date;
import java.util.Map;
import java.util.Set;

@SpringBootTest
@ExtendWith(MockitoExtension.class)
@AutoConfigureMockMvc
public abstract class AbstractSystemTest extends AbstractTestContainerConfiguration {

@Autowired
protected MockMvc mockMvc;
protected AysToken mockAdminUserToken;
protected AysToken mockUserToken;


@Mock
private AysTokenConfigurationParameter tokenConfiguration;
@Mock
private AysParameterService parameterService;

@BeforeEach
public void initializeAuth() {
Set<AysParameter> parameters = AysParameterBuilder.getParameters();
Mockito.when(parameterService.getParameters(Mockito.anyString()))
.thenReturn(parameters);
this.tokenConfiguration = new AysTokenConfigurationParameter(parameterService);

final Map<String, Object> claimsOfAdminUser = new AdminUserEntityBuilder()
.withId(AysTestData.AdminUser.VALID_ID_ONE)
.withUsername(AysTestData.AdminUser.VALID_USERNAME_ONE)
.withEmail(AysTestData.AdminUser.VALID_EMAIL_ONE)
.build()
.getClaims();
this.mockAdminUserToken = this.generate(claimsOfAdminUser);
this.mockUserToken = this.generate(new UserEntityBuilder().build().getClaims());
}

private AysToken generate(Map<String, Object> claims) {
final long currentTimeMillis = System.currentTimeMillis();

final Date tokenIssuedAt = new Date(currentTimeMillis);

final Date accessTokenExpiresAt = DateUtils.addMinutes(new Date(currentTimeMillis), tokenConfiguration.getAccessTokenExpireMinute());
final String accessToken = Jwts.builder()
.setId(AysRandomUtil.generateUUID())
.setIssuer(tokenConfiguration.getIssuer())
.setIssuedAt(tokenIssuedAt)
.setExpiration(accessTokenExpiresAt)
.signWith(tokenConfiguration.getPrivateKey(), SignatureAlgorithm.RS512)
.setHeaderParam(AysTokenClaims.TYPE.getValue(), OAuth2AccessToken.TokenType.BEARER.getValue())
.addClaims(claims)
.compact();

final Date refreshTokenExpiresAt = DateUtils.addDays(new Date(currentTimeMillis), tokenConfiguration.getRefreshTokenExpireDay());
final JwtBuilder refreshTokenBuilder = Jwts.builder();
final String refreshToken = refreshTokenBuilder
.setId(AysRandomUtil.generateUUID())
.setIssuer(tokenConfiguration.getIssuer())
.setIssuedAt(tokenIssuedAt)
.setExpiration(refreshTokenExpiresAt)
.signWith(tokenConfiguration.getPrivateKey(), SignatureAlgorithm.RS512)
.setHeaderParam(AysTokenClaims.TYPE.getValue(), OAuth2AccessToken.TokenType.BEARER.getValue())
.claim(AysTokenClaims.USER_ID.getValue(), claims.get(AysTokenClaims.USER_ID.getValue()))
.claim(AysTokenClaims.USERNAME.getValue(), claims.get(AysTokenClaims.USERNAME.getValue()))
.compact();

return AysToken.builder()
.accessToken(accessToken)
.accessTokenExpiresAt(accessTokenExpiresAt.toInstant().getEpochSecond())
.refreshToken(refreshToken)
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
package com.ays.admin_user.controller;

import com.ays.AbstractSystemTest;
import com.ays.admin_user.model.dto.request.AdminUserRegisterRequest;
import com.ays.admin_user.model.dto.request.AdminUserRegisterRequestBuilder;
import com.ays.auth.model.dto.request.AysLoginRequest;
import com.ays.auth.model.dto.request.AysLoginRequestBuilder;
import com.ays.auth.model.dto.request.AysTokenInvalidateRequest;
import com.ays.auth.model.dto.request.AysTokenRefreshRequest;
import com.ays.auth.model.dto.response.AysTokenResponse;
import com.ays.auth.model.mapper.AysTokenToAysTokenResponseMapper;
import com.ays.common.model.AysPhoneNumber;
import com.ays.common.model.AysPhoneNumberBuilder;
import com.ays.common.model.dto.response.AysResponse;
import com.ays.common.model.dto.response.AysResponseBuilder;
import com.ays.common.util.exception.model.AysError;
import com.ays.common.util.exception.model.AysErrorBuilder;
import com.ays.util.AysMockMvcRequestBuilders;
import com.ays.util.AysMockResultMatchersBuilders;
import com.ays.util.AysTestData;
import org.junit.jupiter.api.Test;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

class AdminUserAuthSystemTest extends AbstractSystemTest {

private final AysTokenToAysTokenResponseMapper aysTokenToAysTokenResponseMapper = AysTokenToAysTokenResponseMapper.initialize();

private static final String BASE_PATH = "/api/v1/authentication/admin";

@Test
void givenValidAdminUserRegisterRequest_whenAdminUserRegistered_thenReturnSuccessResponse() throws Exception {
// Given
AdminUserRegisterRequest mockRequest = new AdminUserRegisterRequestBuilder()
.withValidFields()
.withInstitutionId(AysTestData.VALID_INSTITUTION_ID_ONE)
.withVerificationId(AysTestData.VALID_VERIFICATION_ID)
.build();

// Then
AysResponse<Void> mockResponse = AysResponseBuilder.SUCCESS;
mockMvc.perform(AysMockMvcRequestBuilders
.post(BASE_PATH.concat("/register"), mockRequest))
.andDo(MockMvcResultHandlers.print())
.andExpect(AysMockResultMatchersBuilders.status().isOk())
.andExpect(AysMockResultMatchersBuilders.time()
.isNotEmpty())
.andExpect(AysMockResultMatchersBuilders.httpStatus()
.value(mockResponse.getHttpStatus().name()))
.andExpect(AysMockResultMatchersBuilders.isSuccess()
.value(mockResponse.getIsSuccess()))
.andExpect(AysMockResultMatchersBuilders.response()
.doesNotExist());
}

@Test
void givenPhoneNumberWithAlphanumericCharacter_whenPhoneNumberIsNotValid_thenReturnValidationError() throws Exception {
// Given
AysPhoneNumber mockPhoneNumber = new AysPhoneNumberBuilder()
.withCountryCode("ABC")
.withLineNumber("ABC").build();
AdminUserRegisterRequest mockRequest = new AdminUserRegisterRequestBuilder()
.withValidFields()
.withPhoneNumber(mockPhoneNumber).build();

// Then
AysError mockErrorResponse = AysErrorBuilder.VALIDATION_ERROR;
mockMvc.perform(AysMockMvcRequestBuilders
.post(BASE_PATH.concat("/register"), mockRequest))
.andDo(MockMvcResultHandlers.print())
.andExpect(AysMockResultMatchersBuilders.status().isBadRequest())
.andExpect(AysMockResultMatchersBuilders.time()
.isNotEmpty())
.andExpect(AysMockResultMatchersBuilders.httpStatus()
.value(mockErrorResponse.getHttpStatus().name()))
.andExpect(AysMockResultMatchersBuilders.header()
.value(mockErrorResponse.getHeader()))
.andExpect(AysMockResultMatchersBuilders.isSuccess()
.value(mockErrorResponse.getIsSuccess()))
.andExpect(AysMockResultMatchersBuilders.response()
.doesNotExist())
.andExpect(AysMockResultMatchersBuilders.subErrors()
.isNotEmpty());
}

@Test
void givenPhoneNumberWithInvalidLength_whenPhoneNumberIsNotValid_thenReturnValidationError() throws Exception {
// Given
AysPhoneNumber mockPhoneNumber = new AysPhoneNumberBuilder()
.withCountryCode("456786745645")
.withLineNumber("6546467456435548676845321346656654").build();
AdminUserRegisterRequest mockRequest = new AdminUserRegisterRequestBuilder()
.withValidFields()
.withPhoneNumber(mockPhoneNumber).build();

// Then
AysError mockErrorResponse = AysErrorBuilder.VALIDATION_ERROR;
mockMvc.perform(AysMockMvcRequestBuilders
.post(BASE_PATH.concat("/register"), mockRequest))
.andDo(MockMvcResultHandlers.print())
.andExpect(AysMockResultMatchersBuilders.status().isBadRequest())
.andExpect(AysMockResultMatchersBuilders.time()
.isNotEmpty())
.andExpect(AysMockResultMatchersBuilders.httpStatus()
.value(mockErrorResponse.getHttpStatus().name()))
.andExpect(AysMockResultMatchersBuilders.header()
.value(mockErrorResponse.getHeader()))
.andExpect(AysMockResultMatchersBuilders.isSuccess()
.value(mockErrorResponse.getIsSuccess()))
.andExpect(AysMockResultMatchersBuilders.response()
.doesNotExist())
.andExpect(AysMockResultMatchersBuilders.subErrors()
.isNotEmpty());
}

@Test
void givenValidLoginRequest_whenTokensGeneratedSuccessfully_thenReturnTokenResponse() throws Exception {
// Given
AysLoginRequest mockRequest = new AysLoginRequestBuilder()
.withUsername(AysTestData.AdminUser.VALID_USERNAME_ONE)
.withPassword(AysTestData.AdminUser.VALID_PASSWORD_ONE).build();

// Then
AysTokenResponse mockResponse = aysTokenToAysTokenResponseMapper.map(mockAdminUserToken);
AysResponse<AysTokenResponse> mockAysResponse = AysResponseBuilder.successOf(mockResponse);
mockMvc.perform(AysMockMvcRequestBuilders
.post(BASE_PATH.concat("/token"), mockRequest))
.andDo(MockMvcResultHandlers.print())
.andExpect(AysMockResultMatchersBuilders.status().isOk())
.andExpect(AysMockResultMatchersBuilders.time()
.isNotEmpty())
.andExpect(AysMockResultMatchersBuilders.httpStatus()
.value(mockAysResponse.getHttpStatus().getReasonPhrase()))
.andExpect(AysMockResultMatchersBuilders.isSuccess()
.value(mockAysResponse.getIsSuccess()))
.andExpect(AysMockResultMatchersBuilders.response()
.isNotEmpty())
.andExpect(MockMvcResultMatchers.jsonPath("$.response.accessToken")
.isNotEmpty())
.andExpect(MockMvcResultMatchers.jsonPath("$.response.accessTokenExpiresAt")
.isNotEmpty())
.andExpect(MockMvcResultMatchers.jsonPath("$.response.refreshToken")
.isNotEmpty());

}

@Test
void givenValidTokenRefreshRequest_whenAccessTokenGeneratedSuccessfully_thenReturnTokenResponse() throws Exception {
// Given
AysTokenRefreshRequest mockRequest = AysTokenRefreshRequest.builder()
.refreshToken(mockAdminUserToken.getRefreshToken())
.build();

// Then
AysTokenResponse mockResponse = aysTokenToAysTokenResponseMapper.map(mockAdminUserToken);
AysResponse<AysTokenResponse> mockAysResponse = AysResponseBuilder.successOf(mockResponse);
mockMvc.perform(AysMockMvcRequestBuilders
.post(BASE_PATH.concat("/token/refresh"), mockRequest))
.andDo(MockMvcResultHandlers.print())
.andExpect(AysMockResultMatchersBuilders.status().isOk())
.andExpect(AysMockResultMatchersBuilders.time()
.isNotEmpty())
.andExpect(AysMockResultMatchersBuilders.httpStatus()
.value(mockAysResponse.getHttpStatus().getReasonPhrase()))
.andExpect(AysMockResultMatchersBuilders.isSuccess()
.value(mockAysResponse.getIsSuccess()))
.andExpect(AysMockResultMatchersBuilders.response()
.isNotEmpty())
.andExpect(MockMvcResultMatchers.jsonPath("$.response.accessToken")
.isNotEmpty())
.andExpect(MockMvcResultMatchers.jsonPath("$.response.accessTokenExpiresAt")
.isNotEmpty())
.andExpect(MockMvcResultMatchers.jsonPath("$.response.refreshToken")
.isNotEmpty());
}

@Test
void givenValidAysTokenInvalidateRequest_whenTokensInvalidated_thenReturnSuccessResponse() throws Exception {
// Given
AysTokenInvalidateRequest mockRequest = AysTokenInvalidateRequest.builder()
.refreshToken(mockAdminUserToken.getRefreshToken())
.build();

// Then
String endpoint = BASE_PATH.concat("/token/invalidate");
AysResponse<Void> mockResponse = AysResponseBuilder.SUCCESS;
mockMvc.perform(AysMockMvcRequestBuilders
.post(endpoint, mockAdminUserToken.getAccessToken(), mockRequest))
.andDo(MockMvcResultHandlers.print())
.andExpect(AysMockResultMatchersBuilders.status().isOk())
.andExpect(AysMockResultMatchersBuilders.time()
.isNotEmpty())
.andExpect(AysMockResultMatchersBuilders.httpStatus()
.value(mockResponse.getHttpStatus().name()))
.andExpect(AysMockResultMatchersBuilders.isSuccess()
.value(mockResponse.getIsSuccess()))
.andExpect(AysMockResultMatchersBuilders.response()
.doesNotExist());
}

@Test
void givenValidAysTokenInvalidateRequest_whenUserUnauthorizedForTokensInvalidating_thenReturnAccessDeniedException() throws Exception {
// Given
AysTokenInvalidateRequest mockRequest = AysTokenInvalidateRequest.builder()
.refreshToken(mockAdminUserToken.getRefreshToken())
.build();

// Then
String endpoint = BASE_PATH.concat("/token/invalidate");
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
.post(endpoint, mockUserToken.getAccessToken(), mockRequest);

AysResponse<AysError> mockResponse = AysResponseBuilder.FORBIDDEN;
mockMvc.perform(mockHttpServletRequestBuilder)
.andDo(MockMvcResultHandlers.print())
.andExpect(AysMockResultMatchersBuilders.status().isForbidden())
.andExpect(AysMockResultMatchersBuilders.time()
.isNotEmpty())
.andExpect(AysMockResultMatchersBuilders.httpStatus()
.value(mockResponse.getHttpStatus().name()))
.andExpect(AysMockResultMatchersBuilders.isSuccess()
.value(mockResponse.getIsSuccess()))
.andExpect(AysMockResultMatchersBuilders.response()
.doesNotExist());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ public AdminUserEntityBuilder withPassword(String password) {
return this;
}

public AdminUserEntityBuilder withEmail(String email) {
data.setEmail(email);
return this;
}

public AdminUserEntityBuilder withPhoneNumber(AysPhoneNumber phoneNumber) {
data.setCountryCode(phoneNumber.getCountryCode());
data.setLineNumber(phoneNumber.getLineNumber());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,14 @@ public AysLoginRequestBuilder() {
super(AysLoginRequest.class);
}

public AysLoginRequestBuilder withUsername(final String username) {
data.setUsername(username);
return this;
}

public AysLoginRequestBuilder withPassword(final String password) {
data.setPassword(password);
return this;
}

}
16 changes: 16 additions & 0 deletions src/test/java/com/ays/util/AysTestData.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,21 @@
public class AysTestData {

public static final String VALID_EMAIL = "[email protected]";
public static final String VALID_VERIFICATION_ID = "3cfeb994-88f4-48d0-b105-309f42f91412";
public static final String VALID_INSTITUTION_ID_ONE = "77ece256-bf0e-4bbe-801d-173083f8bdcf";
public static final String VALID_INSTITUTION_ID_TWO = "91df7ae9-d5b9-44ae-b54f-d5d55359c4a4";

public static class AdminUser {
public static final String VALID_ID_ONE = "9262f0fc-93db-4f7e-81c6-aaad85c2b206";
public static final String VALID_USERNAME_ONE = "ays-admin-1";
public static final String VALID_PASSWORD_ONE = "A123y456S.";
public static final String VALID_EMAIL_ONE = "[email protected]";


public static final String VALID_ID_TWO = "87ab173b-1b7d-4264-abd7-438e5ed2c1fa";
public static final String VALID_USERNAME_TWO = "ays-admin-2";
public static final String VALID_PASSWORD_TWO = "A123y456S.";
public static final String VALID_EMAIL_TWO = "[email protected]";
}

}

0 comments on commit d1baf87

Please sign in to comment.