PROJECT: LoanBook

This portfolio aims to document the contributions made by Liu Xiaohang to the LoanBook. The source code is available here: Loanbook source code.

Overview

LoanBook is a desktop loan book application targeted for bicycle rental shop owners to manage and keep track of their loans.

The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 20 kLoC.

LoanBook is a CS2103T project and it is morphed from AddressBook-Level4.

The main features of Loanbook are:

  • Edit the details of the bikes or loans after added them.

  • Set and change the app password for information security.

  • Delete unwanted bikes or loans using the app’s password.

  • View all the bikes or loans.

  • Set and change the user’s email.

  • Use the user’s email to send e-reminder to the customer of the targeted loan.

Summary of contributions

This section shows my contribution to the LoanBook’s development.

  • Major enhancements: added the send email functionality to set and check user’s email and send reminder email, which contains three commands: checkemail, setemail and remind.

    • What it does: allows the user to set the user email for the app and check this email if the user forget which user email was set for the app, and use this email to send reminder emails to the customers.

    • Justification: This feature improves the product significantly because users are able to send reminder emails by typing in only one command instead of typing the whole emails. This can save a lot of efforts and time for the user.

    • Highlights:

      • Show censored user email address if the user wanted to check which email was set to the app, which ensures the privacy and security of the user’s information.

      • The user is required to type in the correct app password if they want to change the user email for the app, which prevents malicious operations.

      • This functionality can automatically generate the reminder email with all the necessary information of the target loan and send it.

    • Credits: The send reminder email command is supported by JavaMail library. Email connection and content generating codes are reused from sendEmail.

    • Pull request #151

  • Minor enhancement:

    • added LoanRate class to store non-nagative numbers with at most two decimal places. (Pull request #29)

    • added censoring function in Nric, Phone and Email class to enable hiding sensitive information feature in LoanCard UI. (Pull request #125)

  • Code Contributed: Reposense

  • Other contributions:

    • Project management:

      • Add config.json file to fix the problem that repoSense not correctly detecting teammates' contributions.

    • Enhancements to existing features:

      • Refactored "address" to "loan". (Pull request #115)

      • Added data fields(Nric, Bike, LoanRate, LoanTime) to Loan class and wrote tests for the new data fields. (Pull request #124)

      • Added data fields in LoanCard and changed its UI. (Pull request #125)

    • Documentation:

      • Updated README to change the app’s name and its introduction. (Pull request #21)

      • Added JavaMail jar into the lib folder and changed build.gradle file to ensure the JavaMail library can be imported successfully. (Pull request #151)

      • Contributed to update User Guide and Developer Guide: (Pull requests #5, #18, #106, #132, #134, #149, #172)

    • Community:

      • PRs reviewed (with non-trivial review comments): (Pull request #95)

      • Reported bugs and suggestions for other teams in the class (examples: #140, #137, #134, #132, #124)

      • Contributed to forum discussions (example: #121)

    • Tools:

      • Integrated a third party library (JavaMail) to the project (#151)

Contributions to the User Guide

This section shows the contributions I made to the User Guide. The following instructions show how to use the send email functionality.

Check your email: checkemail

Checks whether you have set your email or not, and displays the censored email address if you have set it before.
Format: checkemail

Set your email: setemail

Sets the email address to send reminder emails from.
Format: setemail e/NEWEMAIL x/PASSWORDFORAPP

List of Parameters:

e/NEWEMAIL: The new user email that you want to set to the app.
x/PASSWORDFORAPP: The password you set for the app. Not your email password.

Some things to take note of for first time users:

  • NEWEMAIL cannot the same as the user email you have already set to the app.

  • NEWEMAIL must be a valid Gmail address.

Only Gmail is accepted!

Examples:

  • setemail e/new.email@gmail.com x/a12345

Send reminder email: remind

Sends a reminder email to the customer.
Format: remind pw/EMAILPASSWORD id/LOAN_ID

List of Parameters:

pw/PASSWORD: Password of the email address you are sending the messages from.
id/LOAN_ID: LoanID of the loan you want to remind

  • LOANID is the ID of the loan, not the index.

  • EMAILPASSWORD must be correct.

[IMPORTANT] Before using this command, please go to Less Secure Apps , enable it and restart the app! However! If your help page does not respond when enabling, please copy this link: https://www.google.com/settings/security/lesssecureapps and access it in your browser. Then enable the less secure app setting and refresh the setting page!
[IMPORTANT] Please do not connect to eduroam network when using this functionality!

Examples:

  • remind pw/samplepassword id/0

Contributions to the Developer Guide

This section shows the contributions I made to the Developer Guide. The following instructions show how to the send email functionality is implemented.

Hide private information

Users must provide some important and personal information when adding a loan, e.g. Nric, so it is our responsibility to protect their privacy.

As a result, we have added a new feature to hide the private information from the Window.
Example: The customer’s Nric as stored in the database is Nric: T0248272F, but our LoanCard will only show Nric: Txxxxx72F.

LoanListPanelView

Current implementation

Hidden private information is facilitated by an interface called Censor. It is implemented by classes Nric, Phone and Email.

When showing a new loan, it will do the following operations:

  • LoanCard#LoanCard() — the constructor will assign values to each of the labels shown in the LoanCard.

  • Nric#getCensored() — censor the Nric value and hide the first five digital numbers. Then it returns the censored String.

  • Nric#doCensoring(int length) — Take in the length of the Nric String and return the censored part ("x" part) according to the length.

  • Phone#getCensored() — censor the phone number and hide the first five digital numbers. Then it returns the censored String.

  • Phone#doCensoring(int length) — Take in the length of the Phone String and return the censored part ("x" part) according to the length.

  • Email#getCensored() — censor the email address and hide every characters except the last two characters in the local-part and the domain.

  • Email#doCensoring(int length) — Take in the length of the Email String and return the censored part ("x" part) according to the length.

Given below is an example usage scenario and how this mechanism behaves at each step.

Step1. The user adds a new loan to the LoanBook. A new LoanCard object will be created.
The LoanCard object will contain information on the loan: LoanID, BikeID, Name, Nric, Phone, Email, LoanRate and LoanTime.

Step2. Assign the value of each of the components to their corresponding labels.
For example: name.setText(loan.getName().value); will directly assign the name String of this loan to the name label.

However, the values of Nric, Phone and Email need censoring before assigning their values, so they will call their own getCensored() method in their class.
getCensored() in each of these class will call their corresponding doCensoring(int) method. Then combine the censored part and remain part and return.
For example: phone.setText(loan.getPhone().getCensored().value); will censor the value of the phone String of this loan and then assign the censored value to the phone label.

The following sequence diagram shows how this operation works:

HideInfoSequenceDiagrams

Design Considerations

Aspect: How to execute getCensored() and doCensoring(int)

  • Alternative 1 (current choice): each class implements from Censor interface.

    • Pros: Easy to implement.

  • Alternative 2: Loan class implements from Censor interface.

    • Cons: The method might be bulky.

Send Reminder Email feature

Current Implementation

The email sending mechanism is supported by the JavaMail library. This feature is composed of three commands: checkemail, setemail and remind.

  • checkemail command: display the email address that the user has set to send emails from. The app will censor the email address.

    If user has not set an email, the email address will be an invalid email and the app show a "You have not set your email yet!" message.
  • setemail command: set the email address used for sending reminders to the customers.

    Only gmail is accepted by the app.
  • remind command: automatically generate an email containing some core information about the loan, and send it to the corresponding customer from user’s email. This command will use the JavaMail library.

    The email will contain the Name, BikeId, LoanStartTime and LoanRate of the loan.

Given below is an example usage scenario and how the reminder email mechanism behaves at each step.

Step 1. The user launches the application for the first time. The user’s email address is invalid by default.

Step 2. The user executes checkemail. The following sequence diagram shows how checkemail works:

CheckEmailSequenceDiagram

The command executes Model#getMyEmail(), which calls UserPrefs#getDefaultEmail() and returns user’s email stored in UserPref. The app checks if user’s email equals to "default". In this case, they are equal, so it throws a CommandException.

Step 3. The user executes setemail e/EMAIL x/PASSWORDFORAPP. This command does a few checks first:

  1. The app then checks if EMAIL equals to the user email that has been already set to the app. If so, then a CommandException is thrown, to warn the user that they are setting the same email as last time.

  2. Otherwise, SetEmailCommand#isValidGmail(EMAIL) is called to check if EMAIL is a valid gmail. If not, a CommandException is thrown to warn the user that they are setting invalid email address.

Step 4. The user forgets what email has been set before, so the user executes checkemail again. The procedure is the same as in Step 2. However, the app detects that user’s email is not the default invalid string this time, so it creates an Email(userEmail) object and executes Email#getCensored(). Then, the function returns a CommandResult with a success message and the censored user email.

Step 5. The user sends a reminder email to a customer by executing remind pw/EMAILPASSWORD id/LOAN_ID. This command implements the following operations:

  1. Execute Model#getLoanById() and return an optional<Loan> object called targetLoan.

  2. Check if targetLoan.isPresent() returns a non-null loan, then check if its LoanStatus is ONGOING.

  3. If its LoanStatus is ONGOING, create a SendReminder(model, EMAILPASSWORD, loan) object and execute SendReminder#send() to send email.
    The SendReminder#send() method calls SendReminder#createReminderEmail(session, userEmail) to create the content of the email, connects user’s email using EMAILPASSWORD and finally send the email.

    For Steps (b), if the next step cannot be executed, a CommandException with corresponding failure message will be thrown.
    If it throws a CommandException with authentication failed message in step (c), please check if user’s email and password are correct. If they are, please make sure that the Less secure apps setting of user’s email is enabled. If it is not, enable it and refresh the page.

Design considerations

Aspect: use user’s personal email vs share an immutable common email

  • Alternative 1 (current choice): Use a user-specified email.

    • Pros:

      • The user has a choice of what email address to use.

      • The user needs to type in the correct password if they want to send a reminder email, which ensures the security and privacy of the email.

    • Cons:

      • The user needs to enable the Less secure apps setting, which could be a security concern.

  • Alternative 2: Use a common email provided by the app.

    • Pros:

      • The user does not need to set their own email when sending reminder emails, reducing hassle when setting up.

      • The user does not need to type in a password when sending a reminder email.

    • Cons:

      • The common email is less secure, as its password can be found within the program.

      • The password of the common email can be changed by malicious users.

      • The email might get overloaded.

      • Customers might receive spam emails, as the remind command does not require a password.

Future considerations

We plan to add a feature that can automatically send an e-receipt to the customer after return ing a loan.

The e-receipt will contain the Name, BikeID, LoanStartTime, LoanEndTime and TotalCost of the loan.