implemented QR code tips controller, delete email message, delete all email messages

This commit is contained in:
ltiongku
2024-08-13 19:19:56 +08:00
parent c8cfe610a6
commit 63e2d299fd
15 changed files with 195 additions and 12 deletions

View File

@@ -24,9 +24,12 @@ public class APIConstants {
public static final String API_URL_USER_SET_BOOKMARK = "/user/setBookmark"; public static final String API_URL_USER_SET_BOOKMARK = "/user/setBookmark";
public static final String API_URL_USER_DELETE_BOOKMARK = "/user/deleteBookmark"; public static final String API_URL_USER_DELETE_BOOKMARK = "/user/deleteBookmark";
public static final String API_URL_USER_DELETE_ALL_BOOKMARK = "/user/deleteAllBookmark"; public static final String API_URL_USER_DELETE_ALL_BOOKMARK = "/user/deleteAllBookmark";
public static final String API_URL_GMAIL_GET_EMAILS = "/gmail/getEmails"; public static final String API_URL_GMAIL_GET_EMAILS = "/gmail/getEmails";
public static final String API_URL_GMAIL_GET_SCANNED_EMAILS = "/gmail/getScannedEmails"; public static final String API_URL_GMAIL_GET_SCANNED_EMAILS = "/gmail/getScannedEmails";
public static final String API_URL_GMAIL_DELETE_MESSAGE = "/gmail/deleteMessage";
public static final String API_URL_GMAIL_DELETE_ALL_MESSAGES = "/gmail/deleteAllMessages";
public static final String API_URL_TIPS_GET = "/tips/getTips";
} }

View File

@@ -22,4 +22,11 @@ public class CommonConstants {
public static final String CLASSIFY_WARNING = "WARNING"; public static final String CLASSIFY_WARNING = "WARNING";
public static final String CLASSIFY_UNSAFE = "UNSAFE"; public static final String CLASSIFY_UNSAFE = "UNSAFE";
public static final String CLASSIFY_UNKNOWN = "UNKNOWN"; public static final String CLASSIFY_UNKNOWN = "UNKNOWN";
public static final String CAT_BENIGN = "benign";
public static final String CAT_DEFACEMENT = "defacement";
public static final String CAT_MALWARE = "malware";
public static final String CAT_PHISHING = "phishing";
public static final Integer GMAIL_ACTIVE = 1;
} }

View File

@@ -1,8 +1,8 @@
package com.safeqr.app.gmail.controller; package com.safeqr.app.gmail.controller;
import com.google.api.services.gmail.model.*; import com.safeqr.app.gmail.dto.MessageRequestDto;
import com.safeqr.app.gmail.dto.ScannedGmailResponseDto; import com.safeqr.app.gmail.dto.ScannedGmailResponseDto;
import org.apache.commons.codec.binary.Base64; import com.safeqr.app.gmail.dto.BaseResponse;
import org.json.JSONObject; import org.json.JSONObject;
import com.google.api.client.auth.oauth2.AuthorizationCodeRequestUrl; import com.google.api.client.auth.oauth2.AuthorizationCodeRequestUrl;
import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.auth.oauth2.Credential;
@@ -26,11 +26,11 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.view.RedirectView; import org.springframework.web.servlet.view.RedirectView;
import static com.safeqr.app.constants.APIConstants.*; import static com.safeqr.app.constants.APIConstants.*;
import java.io.IOException; import static com.safeqr.app.constants.CommonConstants.HEADER_USER_ID;
import java.lang.Thread;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
@RestController @RestController
@@ -129,5 +129,17 @@ public class GmailController {
return new ResponseEntity<>("Scan Gmail Request is being processed", HttpStatus.ACCEPTED); return new ResponseEntity<>("Scan Gmail Request is being processed", HttpStatus.ACCEPTED);
} }
@PutMapping(value = API_URL_GMAIL_DELETE_MESSAGE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<BaseResponse> deleteMessage(@RequestHeader(name = HEADER_USER_ID) String userId, @RequestBody MessageRequestDto messageRequestDto) {
logger.info("User Id Invoking PUT Delete Single Email endpoint: {}", userId);
return ResponseEntity.ok(gmailService.deleteMessage(userId, messageRequestDto.getMessageId()));
}
@PutMapping(value = API_URL_GMAIL_DELETE_ALL_MESSAGES, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<BaseResponse> deleteAllMessages(@RequestHeader(name = HEADER_USER_ID) String userId) {
logger.info("User Id Invoking PUT Delete All Emails endpoint: {}", userId);
return ResponseEntity.ok(gmailService.deleteAllMessages(userId));
}
} }

View File

@@ -0,0 +1,12 @@
package com.safeqr.app.gmail.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
@AllArgsConstructor
public class BaseResponse {
private String message;
}

View File

@@ -0,0 +1,10 @@
package com.safeqr.app.gmail.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class MessageRequestDto {
private String messageId;
}

View File

@@ -44,6 +44,9 @@ public class GmailEmailEntity {
@Column(name = "date_created") @Column(name = "date_created")
private OffsetDateTime dateCreated; private OffsetDateTime dateCreated;
@Column(name = "active")
private Integer active = 1;
@PrePersist @PrePersist
public void prePersist() { public void prePersist() {
dateCreated = OffsetDateTime.now(); dateCreated = OffsetDateTime.now();

View File

@@ -3,10 +3,26 @@ package com.safeqr.app.gmail.repository;
import com.safeqr.app.gmail.entity.GmailEmailEntity; import com.safeqr.app.gmail.entity.GmailEmailEntity;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
public interface GmailEmailRespository extends JpaRepository<GmailEmailEntity, UUID> { public interface GmailEmailRespository extends JpaRepository<GmailEmailEntity, UUID> {
List<GmailEmailEntity> findByUserId(String userId); // Method to find by userId and active status
List<GmailEmailEntity> findByUserIdAndActive(String userId, Integer active);
// Method to update active status to 0 for a specific userId
@Modifying
@Transactional
@Query("UPDATE GmailEmailEntity e SET e.active = 0 WHERE e.userId = :userId")
int deactivateEmailsByUserId(String userId);
// Method to update active status to 0 for a specific userId and messageId
@Modifying
@Transactional
@Query("UPDATE GmailEmailEntity e SET e.active = 0 WHERE e.userId = :userId AND e.messageId = :messageId")
int deactivateEmailByUserIdAndMessageId(String userId, String messageId);
} }

View File

@@ -18,7 +18,9 @@ import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer; import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.multi.qrcode.QRCodeMultiReader; import com.google.zxing.multi.qrcode.QRCodeMultiReader;
import com.google.zxing.qrcode.encoder.QRCode;
import com.safeqr.app.exceptions.ResourceNotFoundExceptions;
import com.safeqr.app.gmail.dto.BaseResponse;
import com.safeqr.app.gmail.dto.ScannedGmailResponseDto; import com.safeqr.app.gmail.dto.ScannedGmailResponseDto;
import com.safeqr.app.gmail.entity.GmailCidEntity; import com.safeqr.app.gmail.entity.GmailCidEntity;
import com.safeqr.app.gmail.entity.GmailEmailEntity; import com.safeqr.app.gmail.entity.GmailEmailEntity;
@@ -43,6 +45,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
@@ -64,6 +67,7 @@ import java.util.stream.Stream;
import static com.google.api.client.googleapis.auth.oauth2.GoogleOAuthConstants.TOKEN_SERVER_URL; import static com.google.api.client.googleapis.auth.oauth2.GoogleOAuthConstants.TOKEN_SERVER_URL;
import static com.safeqr.app.constants.APIConstants.APPLICATION_NAME; import static com.safeqr.app.constants.APIConstants.APPLICATION_NAME;
import static com.safeqr.app.constants.CommonConstants.GMAIL_ACTIVE;
@Service @Service
public class GmailService { public class GmailService {
@@ -263,7 +267,7 @@ public class GmailService {
// Fetching Scanned Gmail from database // Fetching Scanned Gmail from database
public ScannedGmailResponseDto fetchScannedGmail(String userId){ public ScannedGmailResponseDto fetchScannedGmail(String userId){
// Fetching all emails from gmail_email table // Fetching all emails from gmail_email table
List<GmailEmailEntity> userEmailsList = gmailEmailRespository.findByUserId(userId); List<GmailEmailEntity> userEmailsList = gmailEmailRespository.findByUserIdAndActive(userId, GMAIL_ACTIVE);
List<EmailMessage> emailMessageList = new ArrayList<>(); List<EmailMessage> emailMessageList = new ArrayList<>();
if (userEmailsList != null && !userEmailsList.isEmpty()) { if (userEmailsList != null && !userEmailsList.isEmpty()) {
@@ -549,4 +553,21 @@ public class GmailService {
String lowerUrl = url.toLowerCase(); String lowerUrl = url.toLowerCase();
return lowerUrl.endsWith(".jpg") || lowerUrl.endsWith(".jpeg") || lowerUrl.endsWith(".png") || lowerUrl.endsWith(".gif") || lowerUrl.endsWith(".bmp"); return lowerUrl.endsWith(".jpg") || lowerUrl.endsWith(".jpeg") || lowerUrl.endsWith(".png") || lowerUrl.endsWith(".gif") || lowerUrl.endsWith(".bmp");
} }
@Transactional
public BaseResponse deleteMessage(String userId, String messageId) {
int updatedCount = gmailEmailRespository.deactivateEmailByUserIdAndMessageId(userId, messageId);
// throw exception if email message not found
if (updatedCount < 1)
throw new ResourceNotFoundExceptions("Email message not found");
return BaseResponse.builder().message("Email deleted successfully").build();
}
@Transactional
public BaseResponse deleteAllMessages(String userId) {
int updatedCount = gmailEmailRespository.deactivateEmailsByUserId(userId);
return (updatedCount < 1) ?
BaseResponse.builder().message("No Email found").build() :
BaseResponse.builder().message("All Emails deleted successfully").build();
}
} }

View File

@@ -52,4 +52,9 @@ public class ScanHistoryEntity {
dateCreated = now; dateCreated = now;
dateUpdated = now; dateUpdated = now;
} }
@PreUpdate
public void preUpdate() {
dateUpdated = OffsetDateTime.now();
}
} }

View File

@@ -111,7 +111,7 @@ public class QRCodeTypeService {
// Create the QR Code Instance based on the QR Code Type & insert into the respective table // Create the QR Code Instance based on the QR Code Type & insert into the respective table
QRCodeModel<?> qrCodeModel = qrCodeFactoryProvider.createQRCodeInstance(scannedQR); QRCodeModel<?> qrCodeModel = qrCodeFactoryProvider.createQRCodeInstance(scannedQR);
qrCodeModel.setDetails(); qrCodeModel.setDetails();
// Get classifications based on verificationsv // Get classifications based on verifications
scannedQR.setResult(qrCodeModel.retrieveClassification()); scannedQR.setResult(qrCodeModel.retrieveClassification());
// update result category in qrcode table // update result category in qrcode table
qrCodeRepository.save(scannedQR); qrCodeRepository.save(scannedQR);

View File

@@ -428,6 +428,19 @@ public class URLVerificationService {
// Get Classification using ML Model // Get Classification using ML Model
public String getClassification(URLModel urlModel){ public String getClassification(URLModel urlModel){
return predictionService.predict(urlModel); // Call ML model
String category = predictionService.predict(urlModel);
//update in category in url table
// return classification results
if (category.equals(CAT_BENIGN)) {
if (!urlModel.getDetails().getTrackingDescriptions().isEmpty()) {
return CLASSIFY_WARNING;
}
return CLASSIFY_SAFE;
}
return CLASSIFY_UNSAFE;
} }
} }

View File

@@ -0,0 +1,30 @@
package com.safeqr.app.qrcodetips.controller;
import com.safeqr.app.qrcodetips.entity.QrCodeTipEntity;
import com.safeqr.app.qrcodetips.service.QrCodeTipsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import static com.safeqr.app.constants.APIConstants.*;
@RestController
@RequestMapping(API_VERSION)
public class QRCodeTipsController {
private static final Logger logger = LoggerFactory.getLogger(QRCodeTipsController.class);
QrCodeTipsService qrCodeTipsService;
@Autowired
public QRCodeTipsController (QrCodeTipsService qrCodeTipsService) { this.qrCodeTipsService = qrCodeTipsService;}
@GetMapping(value = API_URL_TIPS_GET)
public ResponseEntity<QrCodeTipEntity> getRandomTips() {
logger.info("Invoking GET QR Code tips endpoint");
return ResponseEntity.ok(qrCodeTipsService.getTips());
}
}

View File

@@ -0,0 +1,24 @@
package com.safeqr.app.qrcodetips.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "qr_code_tips", schema = "safeqr")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class QrCodeTipEntity {
@Id
@JsonIgnore
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String tips;
}

View File

@@ -0,0 +1,13 @@
package com.safeqr.app.qrcodetips.repository;
import com.safeqr.app.qrcodetips.entity.QrCodeTipEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
@Repository
public interface QrCodeTipRepository extends JpaRepository<QrCodeTipEntity, Long> {
@Query(value = "SELECT * FROM safeqr.qr_code_tips ORDER BY RANDOM() LIMIT 1", nativeQuery = true)
QrCodeTipEntity findRandomTip();
}

View File

@@ -0,0 +1,14 @@
package com.safeqr.app.qrcodetips.service;
import com.safeqr.app.qrcodetips.entity.QrCodeTipEntity;
import com.safeqr.app.qrcodetips.repository.QrCodeTipRepository;
import org.springframework.stereotype.Service;
@Service
public class QrCodeTipsService {
QrCodeTipRepository qrCodeTipRepository;
public QrCodeTipsService (QrCodeTipRepository qrCodeTipRepository) { this.qrCodeTipRepository = qrCodeTipRepository; }
public QrCodeTipEntity getTips() {
return qrCodeTipRepository.findRandomTip();
}
}