diff --git a/src/main/Config/AppConfig.java b/src/main/Config/AppConfig.java index 9c80f26c..a20256ab 100644 --- a/src/main/Config/AppConfig.java +++ b/src/main/Config/AppConfig.java @@ -34,10 +34,9 @@ import com.mongodb.client.MongoDatabase; import io.javalin.Javalin; import io.javalin.http.HttpResponseException; -import org.bson.types.ObjectId; - import java.util.HashMap; import java.util.Optional; +import org.bson.types.ObjectId; public class AppConfig { public static Long ASYNC_TIME_OUT = 10L; @@ -103,6 +102,8 @@ public static Javalin appFactory(DeploymentLevel deploymentLevel) { app.post("/get-documents", pdfController.pdfGetFilesInformation); app.post("/get-application-questions", pdfController.getApplicationQuestions); app.post("/fill-application", pdfController.fillPDFForm); + app.post("/mail-file", fileController.fileMail); + app.post("/get-mail-info", fileController.getMailInformation); /* -------------- FILE MANAGEMENT v2 --------------------- */ app.post("/upload-file", fileController.fileUpload); diff --git a/src/main/File/File.java b/src/main/File/File.java index bce7ad78..4bab274c 100644 --- a/src/main/File/File.java +++ b/src/main/File/File.java @@ -8,6 +8,7 @@ import org.bson.types.ObjectId; import java.io.InputStream; +import java.time.LocalDateTime; import java.util.Date; import java.util.Objects; @@ -21,6 +22,7 @@ public class File { @Getter @Setter private Date uploadedAt; @Getter @Setter private String username; @Getter @Setter private String organizationName; + @Getter @Setter private LocalDateTime lastMailedAt; // not used yet while mail form uses GridFS @Getter @Setter diff --git a/src/main/File/FileController.java b/src/main/File/FileController.java index 1b17415f..857c9f2e 100644 --- a/src/main/File/FileController.java +++ b/src/main/File/FileController.java @@ -23,6 +23,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.pdfbox.Loader; import org.apache.pdfbox.pdmodel.PDDocument; +import org.bson.types.ObjectId; import org.json.JSONException; import org.json.JSONObject; @@ -32,9 +33,13 @@ public class FileController { private FileDao fileDao; private EncryptionController encryptionController; + // need to include while viewDocuments used PDF controller (for mailing) + private MongoDatabase db; + public FileController(MongoDatabase db, UserDao userDao, FileDao fileDao) { this.userDao = userDao; this.fileDao = fileDao; + this.db = db; try { this.encryptionController = new EncryptionController(db); } catch (Exception e) { @@ -466,6 +471,49 @@ public FileController(MongoDatabase db, UserDao userDao, FileDao fileDao) { } }; + public Handler fileMail = + ctx -> { + String username = ctx.sessionAttribute("username"); + UserType userType = ctx.sessionAttribute("privilegeLevel"); + JSONObject req = new JSONObject(ctx.body()); + String fileIDStr = req.getString("fileId"); + String price = req.getString("price"); + String mailAddress = req.getString("mailAddress"); + String returnAddress = req.getString("returnAddress"); + ObjectId fileId = new ObjectId(fileIDStr); + String description = req.getString("description"); + + MailFileService mailFileService = + new MailFileService( + db, + fileId, + username, + userType, + description, + price, + mailAddress, + returnAddress, + encryptionController); + + Message response = mailFileService.executeAndGetResponse(); + ctx.result(response.toResponseString()); + }; + public Handler getMailInformation = + ctx -> { + log.error("hello"); + String username = ctx.sessionAttribute("username"); + String organization = ctx.sessionAttribute("organization"); + String applicationType = ctx.sessionAttribute("applicationType"); + + GetMailInformationService getMailInformationService = + new GetMailInformationService(username, organization, applicationType); + + Message response = getMailInformationService.executeAndGetResponse(); + if (response == FileMessage.SUCCESS) { + ctx.result(getMailInformationService.getMailInformation().toString()); + } + }; + public static String getPDFTitle(String fileName, PDDocument pdfDocument) { String title = fileName; pdfDocument.setAllSecurityToBeRemoved(true); diff --git a/src/main/File/FileMessage.java b/src/main/File/FileMessage.java index bde7acbd..9c9e99c7 100644 --- a/src/main/File/FileMessage.java +++ b/src/main/File/FileMessage.java @@ -13,7 +13,8 @@ public enum FileMessage implements Message { SUCCESS("SUCCESS:Success."), NO_SUCH_FILE("NO_SUCH_FILE:PDF does not exist"), ENCRYPTION_ERROR("ENCRYPTION_ERROR:Error encrypting/decrypting"), - FILE_EXISTS("ERROR: File already exists!"); + FILE_EXISTS("ERROR: File already exists!"), + ALREADY_MAILED_RECENTLY("ALREADY_MAILED_RECENTLY:The form has been mailed recently and cannot be mailed again so soon."); private String errorMessage; private String fileId; // optional diff --git a/src/main/File/Services/GetMailInformationService.java b/src/main/File/Services/GetMailInformationService.java new file mode 100644 index 00000000..bf47a96f --- /dev/null +++ b/src/main/File/Services/GetMailInformationService.java @@ -0,0 +1,46 @@ +package File.Services; + +import static io.javalin.Javalin.log; + +import Config.Message; +import Config.Service; +import File.FileMessage; +import kong.unirest.json.JSONObject; + +public class GetMailInformationService implements Service { + private String username; + private String organization; + private String applicationType; + private String price; + private String mailAddress; + private String returnAddress; + + public GetMailInformationService(String applicationType, String username, String organization) { + this.applicationType = applicationType; + this.username = username; + this.organization = organization; + } + + @Override + public Message executeAndGetResponse() { + try { + this.mailAddress = "example street"; + this.returnAddress = "return street"; + this.price = "0.10"; + // Assuming Message is a type that can encapsulate a JSON response. + return FileMessage.SUCCESS; + } catch (Exception e) { + log.error("Error in executeAndGetResponse: " + e.getMessage(), e); + return FileMessage.SERVER_ERROR; + } + } + + public JSONObject getMailInformation() { + JSONObject jsonResponse = new JSONObject(); + jsonResponse.put("price", "0.10"); + jsonResponse.put("mailAddress", "123 example street"); + jsonResponse.put("returnAddress", "456 return street"); + jsonResponse.put("status", "SUCCESS"); + return jsonResponse; + } +} diff --git a/src/main/File/Services/MailFileService.java b/src/main/File/Services/MailFileService.java new file mode 100644 index 00000000..285b5fc0 --- /dev/null +++ b/src/main/File/Services/MailFileService.java @@ -0,0 +1,168 @@ +package File.Services; + +import static Issue.IssueController.issueReportActualURL; +import static io.javalin.Javalin.log; + +import Config.Message; +import Config.Service; +import File.FileMessage; +import Issue.IssueReportMessage; +import Security.EncryptionController; +import User.UserType; +import com.mongodb.MongoException; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.UpdateOptions; +import com.mongodb.client.model.Updates; +import java.time.LocalDateTime; +import kong.unirest.HttpResponse; +import kong.unirest.Unirest; +import org.bson.Document; +import org.bson.conversions.Bson; +import org.bson.types.ObjectId; +import org.json.JSONArray; +import org.json.JSONObject; + +public class MailFileService implements Service { + + private ObjectId fileId; + private String username; + private UserType privilegeLevel; + private MongoDatabase db; + private EncryptionController encryptionController; + private String description; + private String mailAddress; + private String returnAddress; + private String price; + private String applicationTitle; + + public MailFileService( + MongoDatabase db, + ObjectId fileId, + String username, + UserType privilegeLevel, + String description, + String price, + String mailAddress, + String returnAddress, + EncryptionController encryptionController) { + this.db = db; + this.fileId = fileId; + this.username = username; + this.privilegeLevel = privilegeLevel; + this.description = description; + this.applicationTitle = this.findApplicationTitle(fileId); + this.mailAddress = mailAddress; + this.returnAddress = returnAddress; + this.price = price; + this.encryptionController = encryptionController; + } + + @Override + public Message executeAndGetResponse() { + try { + MongoCollection mailCollection = db.getCollection("mail"); + + // if (shouldMail(mailCollection, fileId)) { + if (true) { + Message slackResponse = sendSlackNotification("File Mailing Request", this.description); + if (slackResponse != IssueReportMessage.SUCCESS) { + return slackResponse; + } + + updateLastMailedTime(mailCollection, fileId); + return FileMessage.SUCCESS; + } else { + return FileMessage.ALREADY_MAILED_RECENTLY; + } + } catch (Exception e) { + log.error("Error in executeAndGetResponse: " + e.getMessage(), e); + return FileMessage.SERVER_ERROR; + } + } + + private String findApplicationTitle(ObjectId fileId) { + try { + MongoCollection completedApplicationsCollection = + db.getCollection("COMPLETED_APPLICATION.files"); + + // Find the document in the collection with the matching fileId + Document applicationDocument = + completedApplicationsCollection.find(Filters.eq("_id", fileId)).first(); + log.error(String.valueOf(applicationDocument)); + + if (applicationDocument != null) { + // Extract the applicationTitle field from the document + String applicationTitle = applicationDocument.getString("filename"); + if (applicationTitle != null) { + return applicationTitle; + } + } + } catch (MongoException e) { + log.error("MongoDB error in findApplicationTitle: " + e.getMessage(), e); + } catch (Exception e) { + log.error("Error in findApplicationTitle: " + e.getMessage(), e); + } + + // Return a default value or handle the case when the title is not found + return "No Title found"; + } + + private void updateLastMailedTime(MongoCollection mailCollection, ObjectId fileId) { + Bson filter = Filters.eq("fileId", fileId); + Bson updateOperation = + Updates.combine( + Updates.set("lastMailedAt", LocalDateTime.now().toString()), + Updates.set("applicationTitle", applicationTitle), + Updates.set("price", price), + Updates.set("mailAddress", mailAddress), + Updates.set("returnAddress", returnAddress)); + mailCollection.updateOne(filter, updateOperation, new UpdateOptions().upsert(true)); + } + + // want to remove this for the future + private Message sendSlackNotification(String title, String description) { + JSONArray blocks = new JSONArray(); + JSONObject titleJson = new JSONObject(); + titleJson.put("type", "section"); + titleJson.put( + "text", new JSONObject().put("type", "mrkdwn").put("text", "*Issue Title: * " + title)); + blocks.put(titleJson); + + JSONObject desJson = new JSONObject(); + desJson.put("type", "section"); + desJson.put( + "text", + new JSONObject().put("type", "mrkdwn").put("text", "*Issue Description: * " + description)); + blocks.put(desJson); + + JSONObject input = new JSONObject(); + input.put("blocks", blocks); + + HttpResponse posted = + Unirest.post(issueReportActualURL) + .header("accept", "application/json") + .body(input.toString()) + .asEmpty(); + + if (!posted.isSuccess()) { + return IssueReportMessage.SLACK_FAILED; + } + return IssueReportMessage.SUCCESS; + } + + private boolean shouldMail(MongoCollection mailCollection, ObjectId fileId) { + Document mailData = mailCollection.find(Filters.eq("fileId", fileId)).first(); + + if (mailData == null) { + // If no record exists, it means it hasn't been mailed before + return true; + } + + String lastMailedAtStr = mailData.getString("lastMailedAt"); + LocalDateTime lastMailedAt = + lastMailedAtStr != null ? LocalDateTime.parse(lastMailedAtStr) : null; + return lastMailedAt == null || LocalDateTime.now().isAfter(lastMailedAt.plusDays(1)); + } +} diff --git a/src/main/Form/Form.java b/src/main/Form/Form.java index a2fbb6f4..c1ac0d2f 100644 --- a/src/main/Form/Form.java +++ b/src/main/Form/Form.java @@ -110,7 +110,6 @@ public String getUploaderUsername() { public boolean isTemplate() { return isTemplate; } - public FormMetadata getMetadata() { return metadata; } diff --git a/src/main/Form/FormController.java b/src/main/Form/FormController.java index 80859e69..52697aa7 100644 --- a/src/main/Form/FormController.java +++ b/src/main/Form/FormController.java @@ -177,7 +177,7 @@ public FormController(MongoDatabase db, FormDao formDao) { ctx.result(response.toResponseString()); }; - public User userCheck(String req) { + public User userCheck(String req) { log.info("userCheck Helper started"); String username; User user = null;