Skip to content

Commit 4c01610

Browse files
committed
- Created Google SignUp
- Added isGoogleUser variable at User entity - Wrote 2 test case for user controller to check CI/CD
1 parent 0b73f08 commit 4c01610

File tree

8 files changed

+211
-6
lines changed

8 files changed

+211
-6
lines changed

.github/workflows/deploy.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: CI/CD Pipeline
2+
3+
on:
4+
push:
5+
branches:
6+
- test
7+
8+
jobs:
9+
build-deploy:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Checkout code
14+
uses: actions/checkout@v3
15+
16+
- name: Set up Java
17+
uses: actions/setup-java@v3
18+
with:
19+
distribution: 'temurin'
20+
java-version: '21'
21+
22+
- name: Build with Maven
23+
run: mvn clean install
24+
25+
- name: Run Tests
26+
run: mvn test
27+
28+
- name: Trigger Render Deploy
29+
run: curl -X POST https://api.render.com/deploy/srv-d1lspd2li9vc73eb65e0?key=BKlQTrnxze4

src/main/java/com/hrms/backend/controllers/AuthenticationController.java

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,23 @@
55
import com.google.api.client.http.javanet.NetHttpTransport;
66
import com.google.api.client.json.gson.GsonFactory;
77
import com.hrms.backend.dtos.entityDtos.LoginSignUp.GoogleLoginRequest;
8+
import com.hrms.backend.dtos.entityDtos.LoginSignUp.GoogleSignUpRequest;
89
import com.hrms.backend.dtos.entityDtos.LoginSignUp.JwtRequest;
910
import com.hrms.backend.dtos.entityDtos.LoginSignUp.JwtResponse;
1011
import com.hrms.backend.dtos.entityDtos.User.response.UserResponseDto;
12+
import com.hrms.backend.exceptions.BadApiRequestException;
1113
import com.hrms.backend.exceptions.ResourceNotFoundException;
14+
import com.hrms.backend.models.Company;
1215
import com.hrms.backend.models.User;
1316
import com.hrms.backend.models.enums.Role;
17+
import com.hrms.backend.repositories.CompanyRepository;
1418
import com.hrms.backend.repositories.UserRepository;
1519
import com.hrms.backend.security.JwtHelper;
20+
import com.hrms.backend.utils.CodeGenerator;
21+
import jakarta.validation.Valid;
1622
import org.modelmapper.ModelMapper;
1723
import org.springframework.beans.factory.annotation.Autowired;
1824
import org.springframework.beans.factory.annotation.Value;
19-
import org.springframework.http.HttpStatus;
2025
import org.springframework.http.ResponseEntity;
2126
import org.springframework.security.authentication.AuthenticationManager;
2227
import org.springframework.security.authentication.BadCredentialsException;
@@ -29,6 +34,7 @@
2934
import org.springframework.web.bind.annotation.RestController;
3035

3136
import java.util.Collections;
37+
import java.util.Optional;
3238

3339
@RestController
3440
@RequestMapping("/auth")
@@ -52,6 +58,9 @@ public class AuthenticationController {
5258
@Autowired
5359
private UserDetailsService userDetailsService;
5460

61+
@Autowired
62+
private CompanyRepository companyRepository;
63+
5564
@Value("${web.client.id}")
5665
private String webClientId;
5766

@@ -114,4 +123,67 @@ public ResponseEntity<JwtResponse> googleLogin(@RequestBody GoogleLoginRequest r
114123

115124
return ResponseEntity.ok(jwtResponse);
116125
}
126+
127+
@PostMapping("/googleSignUp")
128+
public ResponseEntity<JwtResponse> googleSignUp(@Valid @RequestBody GoogleSignUpRequest request) {
129+
String idTokenString = request.getIdToken();
130+
131+
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), new GsonFactory())
132+
.setAudience(Collections.singletonList(webClientId)) // Your Google Web Client ID
133+
.build();
134+
135+
GoogleIdToken idToken;
136+
try {
137+
idToken = verifier.verify(idTokenString);
138+
} catch (Exception e) {
139+
throw new ResourceNotFoundException("Invalid Google ID token");
140+
}
141+
142+
if (idToken == null) {
143+
throw new ResourceNotFoundException("Invalid Google ID token");
144+
}
145+
146+
GoogleIdToken.Payload payload = idToken.getPayload();
147+
String email = payload.getEmail();
148+
149+
Optional<User> existingUser = userRepository.findByEmail(email);
150+
151+
if (existingUser.isPresent()) {
152+
throw new BadApiRequestException("User already registered with this email");
153+
}
154+
155+
// Create new user
156+
User newUser = User.builder()
157+
.email(email)
158+
.name((String) payload.get("name"))
159+
.imageUrl((String) payload.get("picture"))
160+
.role(Role.valueOf(request.getRole())) // Ensure enum matches (ROLE_USER or ROLE_HR)
161+
.isGoogleUser(true)
162+
.build();
163+
164+
if(newUser.getRole().equals(Role.ROLE_HR)){
165+
String companyCode = CodeGenerator.generateBase64Code();;
166+
while(companyRepository.findByCompanyCode(companyCode).isPresent()){
167+
companyCode = CodeGenerator.generateBase64Code();
168+
}
169+
newUser.setCompanyCode(companyCode);
170+
}
171+
172+
173+
User savedUser = userRepository.save(newUser);
174+
175+
Company company = Company.builder().hr(savedUser.getId()).companyCode(savedUser.getCompanyCode()).build();
176+
companyRepository.save(company);
177+
178+
String jwt = jwtHelper.generateToken(savedUser, savedUser.getRole().name());
179+
UserResponseDto userResponseDto = modelMapper.map(savedUser, UserResponseDto.class);
180+
181+
JwtResponse jwtResponse = JwtResponse.builder()
182+
.user(userResponseDto)
183+
.token(jwt)
184+
.build();
185+
186+
return ResponseEntity.ok(jwtResponse);
187+
}
188+
117189
}

src/main/java/com/hrms/backend/controllers/PingController.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
package com.hrms.backend.controllers;
22

3-
import com.hrms.backend.dtos.entityDtos.User.response.UserResponseDto;
43
import com.hrms.backend.dtos.response_message.SuccessApiResponseMessage;
54
import com.hrms.backend.security.JwtHelper;
65
import com.hrms.backend.services.userService.UserServiceInterface;
76
import org.springframework.beans.factory.annotation.Autowired;
87
import org.springframework.http.ResponseEntity;
98
import org.springframework.web.bind.annotation.GetMapping;
10-
import org.springframework.web.bind.annotation.RequestHeader;
119
import org.springframework.web.bind.annotation.RequestMapping;
1210
import org.springframework.web.bind.annotation.RestController;
1311

src/main/java/com/hrms/backend/controllers/UserController.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@
1313
import org.springframework.beans.factory.annotation.Autowired;
1414
import org.springframework.http.HttpStatus;
1515
import org.springframework.http.ResponseEntity;
16-
import org.springframework.validation.annotation.Validated;
1716
import org.springframework.web.bind.annotation.*;
1817
import org.springframework.web.multipart.MultipartFile;
1918

20-
@Validated
2119
@RestController
2220
@RequestMapping("/users")
2321
public class UserController {

src/main/java/com/hrms/backend/dtos/entityDtos/LoginSignUp/GoogleLoginRequest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import jakarta.validation.constraints.NotBlank;
44
import jakarta.validation.constraints.NotNull;
5-
import jakarta.validation.constraints.Pattern;
65
import lombok.*;
76

87
@Setter
@@ -11,5 +10,7 @@
1110
@AllArgsConstructor
1211
@Builder
1312
public class GoogleLoginRequest {
13+
@NotNull(message = "token is required")
14+
@NotBlank(message = "token cannot be empty")
1415
private String idToken;
1516
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.hrms.backend.dtos.entityDtos.LoginSignUp;
2+
3+
import jakarta.validation.constraints.NotBlank;
4+
import jakarta.validation.constraints.NotNull;
5+
import jakarta.validation.constraints.Pattern;
6+
import lombok.*;
7+
8+
9+
@Getter
10+
@Setter
11+
@NoArgsConstructor
12+
@AllArgsConstructor
13+
@Builder
14+
public class GoogleSignUpRequest {
15+
16+
@NotNull(message = "token is required")
17+
@NotBlank(message = "token cannot be empty")
18+
private String idToken;
19+
@NotBlank(message = "Role is required")
20+
@Pattern(
21+
regexp = "ROLE_USER|ROLE_HR",
22+
message = "Role must be one of: ROLE_USER, or ROLE_HR"
23+
)
24+
private String role;
25+
}

src/main/java/com/hrms/backend/models/User.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,14 @@ public class User implements UserDetails {
3030

3131
private String email;
3232

33+
@Field(write = Field.Write.ALWAYS)
3334
private String phone;
3435

36+
@Field(write = Field.Write.ALWAYS)
3537
private String password;
3638

39+
private Boolean isGoogleUser = false;
40+
3741
@Field(write = Field.Write.ALWAYS)
3842
private String gender;
3943

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package com.hrms.backend.User;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import com.hrms.backend.controllers.UserController;
5+
import com.hrms.backend.dtos.entityDtos.User.request.UserUpdateProfileRequestDto;
6+
import com.hrms.backend.dtos.entityDtos.User.response.UserResponseDto;
7+
import com.hrms.backend.security.JwtHelper;
8+
import com.hrms.backend.services.userService.UserServiceInterface;
9+
import org.junit.jupiter.api.BeforeEach;
10+
import org.junit.jupiter.api.Test;
11+
import org.springframework.http.MediaType;
12+
import org.springframework.test.util.ReflectionTestUtils;
13+
import org.springframework.test.web.servlet.MockMvc;
14+
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
15+
16+
import static org.mockito.ArgumentMatchers.any;
17+
import static org.mockito.ArgumentMatchers.eq;
18+
import static org.mockito.Mockito.mock;
19+
import static org.mockito.Mockito.when;
20+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
21+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
22+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
23+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
24+
25+
class UserControllerTests {
26+
27+
private MockMvc mockMvc;
28+
private final UserServiceInterface userService = mock(UserServiceInterface.class);
29+
private final JwtHelper jwtHelper = mock(JwtHelper.class);
30+
private final ObjectMapper objectMapper = new ObjectMapper();
31+
private final String token = "Bearer valid.jwt.token";
32+
33+
@BeforeEach
34+
void setUp() {
35+
UserController userController = new UserController();
36+
ReflectionTestUtils.setField(userController, "userServiceInterface", userService);
37+
ReflectionTestUtils.setField(userController, "jwtHelper", jwtHelper);
38+
this.mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
39+
}
40+
41+
42+
@Test
43+
void getUserProfile_shouldReturn200() throws Exception {
44+
String userId = "u123";
45+
UserResponseDto response = new UserResponseDto();
46+
response.setId(userId);
47+
response.setEmail("[email protected]");
48+
49+
when(jwtHelper.getUserIdFromToken("valid.jwt.token")).thenReturn(userId);
50+
when(userService.getUserById(userId)).thenReturn(response);
51+
52+
mockMvc.perform(get("/users")
53+
.header("Authorization", token))
54+
.andExpect(status().isOk())
55+
.andExpect(jsonPath("$.id").value(userId));
56+
}
57+
58+
@Test
59+
void updateProfile_shouldReturn202() throws Exception {
60+
String userId = "u123";
61+
UserUpdateProfileRequestDto request = new UserUpdateProfileRequestDto();
62+
request.setName("Jane Doe");
63+
64+
UserResponseDto response = new UserResponseDto();
65+
response.setId(userId);
66+
response.setName("Jane Doe");
67+
68+
when(jwtHelper.getUserIdFromToken("valid.jwt.token")).thenReturn(userId);
69+
when(userService.updateUser(any(), eq(userId))).thenReturn(response);
70+
71+
mockMvc.perform(patch("/users")
72+
.header("Authorization", token)
73+
.contentType(MediaType.APPLICATION_JSON)
74+
.content(objectMapper.writeValueAsString(request)))
75+
.andExpect(status().isAccepted())
76+
.andExpect(jsonPath("$.name").value("Jane Doe"));
77+
}
78+
}

0 commit comments

Comments
 (0)