Skip to content

Commit b6ba623

Browse files
committed
for gmail pub sub
1 parent db5bf48 commit b6ba623

34 files changed

+166
-331
lines changed

backend/src/main/java/com/thughari/jobtrackerpro/config/AsyncConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public Executor dashboardExecutor() {
2222
return executor;
2323
}
2424

25-
@Primary // This tells Spring: "Use this one for @Async by default"
25+
@Primary
2626
@Bean(name = "taskExecutor")
2727
public Executor taskExecutor() {
2828
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

backend/src/main/java/com/thughari/jobtrackerpro/config/PasswordConfig.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ public class PasswordConfig {
1010

1111
@Bean
1212
public PasswordEncoder passwordEncoder() {
13-
// High Performance: BCrypt is standard, but you can tune strength
14-
// if login latency becomes a bottleneck. 10 is the balanced default.
1513
return new BCryptPasswordEncoder();
1614
}
1715
}

backend/src/main/java/com/thughari/jobtrackerpro/controller/WebhookController.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ public ResponseEntity<String> handleInboundEmail(@RequestBody Map<String, Object
118118
log.warn("User unknown. From: [{}], To: [{}]", from, to);
119119
return ResponseEntity.ok("User Unknown");
120120
}
121+
122+
if (Boolean.TRUE.equals(user.getGmailConnected())) {
123+
log.info("Forwarding Webhook: Discarding email for {} (Direct Sync is ACTIVE)", user.getEmail());
124+
return ResponseEntity.ok("Ignored: Direct Sync Active");
125+
}
121126

122127
JobDTO job = geminiService.extractJobFromEmail(from, subject, plainText);
123128

backend/src/main/java/com/thughari/jobtrackerpro/entity/VerificationToken.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class VerificationToken {
1818
@Column(nullable = false, unique = true)
1919
private String token;
2020

21-
@OneToOne(fetch = FetchType.LAZY) // Clean coding: don't load user unless needed
21+
@OneToOne(fetch = FetchType.LAZY)
2222
@JoinColumn(name = "user_id", nullable = false)
2323
private User user;
2424

backend/src/main/java/com/thughari/jobtrackerpro/exception/GlobalExceptionHandler.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,14 @@ public ResponseEntity<ErrorResponse> handleMaxSizeException(MaxUploadSizeExceede
3131
return buildResponse(HttpStatus.PAYLOAD_TOO_LARGE, "File size exceeds the limit (5MB).");
3232
}
3333

34-
// High Performance: Catch-all for security and unexpected errors
3534
@ExceptionHandler(Exception.class)
3635
public ResponseEntity<ErrorResponse> handleGeneralException(Exception ex) {
37-
log.error("UNEXPECTED ERROR: ", ex); // Log full stack trace for dev tracking
36+
log.error("UNEXPECTED ERROR: ", ex);
3837
return buildResponse(HttpStatus.INTERNAL_SERVER_ERROR, "An unexpected error occurred.");
3938
}
4039

4140
@ExceptionHandler(IllegalStateException.class)
4241
public ResponseEntity<ErrorResponse> handleUnauthorized(IllegalStateException ex) {
43-
// High Performance: Use 401 for verification/state locks
4442
return buildResponse(HttpStatus.UNAUTHORIZED, ex.getMessage());
4543
}
4644

backend/src/main/java/com/thughari/jobtrackerpro/scheduler/JobScheduler.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ public class JobScheduler {
2626
private final PasswordResetTokenRepository passwordTokenRepo;
2727
private final VerificationTokenRepository verificationTokenRepo;
2828

29-
// Clean Coding: Single constructor injection
3029
public JobScheduler(JobService jobService,
3130
UserRepository userRepository,
3231
GmailIntegrationService gmailIntegrationService,
@@ -56,7 +55,6 @@ public void runStaleJobCleanup() {
5655

5756
/**
5857
* Gmail Security: Renews the 7-day watch lease every 5 days.
59-
* High Performance: Processes users in parallel threads.
6058
*/
6159
@Scheduled(cron = "0 0 0 */5 * *")
6260
public void renewGmailWatches() {

backend/src/main/java/com/thughari/jobtrackerpro/security/JwtAuthenticationFilter.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
2828
String authHeader = request.getHeader("Authorization");
2929

3030
if (authHeader == null && request.getRequestURI().contains("/api/notifications/stream")) {
31-
System.out.println("-----hereee");
3231
String paramToken = request.getParameter("token");
3332
if (paramToken != null) {
3433
authHeader = "Bearer " + paramToken;

backend/src/main/java/com/thughari/jobtrackerpro/security/OAuth2SuccessHandler.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,11 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo
4646
String registrationId = authToken.getAuthorizedClientRegistrationId();
4747
UserInfo userInfo = extractUserInfo(registrationId, authToken.getPrincipal().getAttributes());
4848

49-
// DELEGATION: Business logic belongs in the Service
5049
User user = authService.processOAuthUser(userInfo.email(), userInfo.name(), userInfo.imageUrl(), registrationId);
5150

5251
String token = jwtUtils.generateAccessToken(user.getEmail());
5352
String refreshToken = jwtUtils.generateRefreshToken(user.getEmail());
5453

55-
// High Performance: Single Header construction
5654
response.addHeader("Set-Cookie", buildRefreshCookie(refreshToken, "/", refreshExpirationMs / 1000).toString());
5755

5856
getRedirectStrategy().sendRedirect(request, response, uiUrl + "/login-success?token=" + token);

backend/src/main/java/com/thughari/jobtrackerpro/service/AuthService.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -193,18 +193,15 @@ public void resendVerificationEmail(String email) {
193193
throw new IllegalStateException("Account is already verified. Please log in.");
194194
}
195195

196-
// 1. ATOMIC CLEANUP: Delete any previous tokens for this user
197196
verificationTokenRepository.deleteByUser(user);
198197

199-
// 2. Generate New Token
200198
String token = UUID.randomUUID().toString();
201199
VerificationToken vToken = new VerificationToken();
202200
vToken.setToken(token);
203201
vToken.setUser(user);
204202
vToken.setExpiryDate(LocalDateTime.now().plusHours(24));
205203
verificationTokenRepository.save(vToken);
206204

207-
// 3. ASYNC DELIVERY: Use the same high-performance thread pool
208205
emailService.sendVerificationEmail(user.getEmail(), token);
209206

210207
log.info("Verification email resent to: {}", user.getEmail());
@@ -280,7 +277,7 @@ else if (imageUrl != null && !imageUrl.isEmpty()) {
280277

281278

282279
/**
283-
* High Performance OAuth User Sync
280+
* OAuth User Sync
284281
* Consolidates find, create, and profile update into one DB trip.
285282
*/
286283
@Caching(evict = {
@@ -306,18 +303,14 @@ public User processOAuthUser(String email, String name, String imageUrl, String
306303
log.info("User {} auto-verified via {} login.", email, provider);
307304
}
308305

309-
// Only update if data actually changed to avoid redundant SQL UPDATE statements
310306
if (user.getName() == null || !user.getName().equals(name)) {
311307
user.setName(name);
312308
needsUpdate = true;
313309
}
314310

315-
// High Performance: We check if the image is already a JobTrackerPro/R2 URL
316-
// to avoid re-uploading social images every single login.
317311
if (user.getImageUrl() == null || (!user.getImageUrl().contains("r2") && !user.getImageUrl().equals(imageUrl))) {
318312
if (imageUrl != null && !imageUrl.isBlank()) {
319313
try {
320-
// Offload image sync to storage service
321314
String synchronizedUrl = storageService.uploadFromUrl(imageUrl,
322315
user.getId() != null ? user.getId().toString() : UUID.randomUUID().toString());
323316
user.setImageUrl(synchronizedUrl);

backend/src/main/java/com/thughari/jobtrackerpro/service/CloudStorageService.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,12 @@ public class CloudStorageService implements StorageService {
3232
private static final long MAX_IMAGE_FILE_SIZE = 5 * 1024 * 1024; // 5MB
3333
private static final long MAX_RESOURCE_FILE_SIZE = 10 * 1024 * 1024; // 10MB
3434

35-
// Avatar Bucket Config
3635
@Value("${cloudflare.r2.bucket.avatars}")
3736
private String avatarBucket;
3837

3938
@Value("${cloudflare.r2.public-url.avatars}")
4039
private String avatarPublicUrl;
4140

42-
// Resource Bucket Config
4341
@Value("${cloudflare.r2.bucket.resources}")
4442
private String resourceBucket;
4543

@@ -93,7 +91,6 @@ public String uploadResourceFile(MultipartFile file, String userId) {
9391

9492
try {
9593
String extension = getExtensionFromFilename(file.getOriginalFilename());
96-
// Using a flat structure since we are in a dedicated resource bucket
9794
String fileName = userId + "-" + System.currentTimeMillis() + extension;
9895

9996
uploadToS3(resourceBucket, fileName, contentType, file);
@@ -153,7 +150,6 @@ public String uploadFromUrl(String externalUrl, String userId) {
153150

154151
} catch (Exception e) {
155152
log.error("Failed to sync social image to R2: {}", e.getMessage());
156-
// Fallback: return original URL so the profile still has an image
157153
return externalUrl;
158154
}
159155
}
@@ -167,8 +163,6 @@ public void deleteFile(String fileUrl) {
167163
return;
168164
}
169165

170-
// FIX: Must use AND (&&) here. If we used OR (||), a valid avatar URL would trigger
171-
// the return because it doesn't start with the resource URL.
172166
if (!fileUrl.startsWith(avatarPublicUrl) && !fileUrl.startsWith(resourcePublicUrl)) {
173167
return;
174168
}
@@ -197,7 +191,6 @@ public void deleteFile(String fileUrl) {
197191
}
198192
}
199193

200-
// --- Private Helpers ---
201194

202195
private void uploadToS3(String bucket, String key, String contentType, MultipartFile file) throws Exception {
203196
PutObjectRequest putObj = PutObjectRequest.builder()

0 commit comments

Comments
 (0)