Merge remote-tracking branch 'origin/feature-ml-integration' into dev

This commit is contained in:
heyethereum
2024-08-13 21:03:45 +08:00
16 changed files with 206 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_DELETE_BOOKMARK = "/user/deleteBookmark";
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_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_UNSAFE = "UNSAFE";
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;
import com.google.api.services.gmail.model.*;
import com.safeqr.app.gmail.dto.MessageRequestDto;
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 com.google.api.client.auth.oauth2.AuthorizationCodeRequestUrl;
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.servlet.view.RedirectView;
import static com.safeqr.app.constants.APIConstants.*;
import java.io.IOException;
import java.lang.Thread;
import static com.safeqr.app.constants.CommonConstants.HEADER_USER_ID;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
@RestController
@@ -129,5 +129,17 @@ public class GmailController {
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")
private OffsetDateTime dateCreated;
@Column(name = "active")
private Integer active = 1;
@PrePersist
public void prePersist() {
dateCreated = OffsetDateTime.now();

View File

@@ -3,10 +3,26 @@ package com.safeqr.app.gmail.repository;
import com.safeqr.app.gmail.entity.GmailEmailEntity;
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.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.common.HybridBinarizer;
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.entity.GmailCidEntity;
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.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.imageio.ImageIO;
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.safeqr.app.constants.APIConstants.APPLICATION_NAME;
import static com.safeqr.app.constants.CommonConstants.GMAIL_ACTIVE;
@Service
public class GmailService {
@@ -263,7 +267,7 @@ public class GmailService {
// Fetching Scanned Gmail from database
public ScannedGmailResponseDto fetchScannedGmail(String userId){
// 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<>();
if (userEmailsList != null && !userEmailsList.isEmpty()) {
@@ -549,4 +553,21 @@ public class GmailService {
String lowerUrl = url.toLowerCase();
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;
dateUpdated = now;
}
@PreUpdate
public void preUpdate() {
dateUpdated = OffsetDateTime.now();
}
}

View File

@@ -23,6 +23,9 @@ import java.util.UUID;
@NoArgsConstructor
@AllArgsConstructor
public class URLEntity {
@Column(name="classifications")
private String classifications;
@Id
@JsonIgnore
@GeneratedValue(generator = "UUID")

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
QRCodeModel<?> qrCodeModel = qrCodeFactoryProvider.createQRCodeInstance(scannedQR);
qrCodeModel.setDetails();
// Get classifications based on verificationsv
// Get classifications based on verifications
scannedQR.setResult(qrCodeModel.retrieveClassification());
// update result category in qrcode table
qrCodeRepository.save(scannedQR);

View File

@@ -428,6 +428,27 @@ public class URLVerificationService {
// Get Classification using ML Model
public String getClassification(URLModel urlModel){
return predictionService.predict(urlModel);
// Call ML model
String category = predictionService.predict(urlModel);
//update in category in url table
urlModel.getDetails().setClassifications(category);
// return classification results
if (category.equals(CAT_BENIGN)) {
if (!urlModel.getDetails().getTrackingDescriptions().isEmpty() || // contains tracking
urlModel.getData().getInfo().getPrefix().equalsIgnoreCase("http://") || // uses http
urlModel.getDetails().getSslStripping().contains(true) || // has SSL stripping
urlModel.getDetails().getHasExecutable().equalsIgnoreCase("yes") || // contains executable
!urlModel.getDetails().getJavascriptCheck().isEmpty() || // contains javascript
!urlModel.getDetails().getHasIpAddress().isEmpty() || // contains IP address
urlModel.getDetails().getHostnameEmbedding() != null // contains hostname embedding
) {
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();
}
}