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
andremind
.-
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:
-
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:
-
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:
-
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
.
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:
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 fromCensor
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 theJavaMail
library.The email will contain the Name
,BikeId
,LoanStartTime
andLoanRate
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:
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:
-
The app then checks if
EMAIL
equals to the user email that has been already set to the app. If so, then aCommandException
is thrown, to warn the user that they are setting the same email as last time. -
Otherwise,
SetEmailCommand#isValidGmail(EMAIL)
is called to check ifEMAIL
is a valid gmail. If not, aCommandException
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:
-
Execute
Model#getLoanById()
and return an optional<Loan> object calledtargetLoan
. -
Check if
targetLoan.isPresent()
returns a non-nullloan
, then check if itsLoanStatus
isONGOING
. -
If its
LoanStatus
isONGOING
, create aSendReminder(model, EMAILPASSWORD, loan)
object and executeSendReminder#send()
to send email.
TheSendReminder#send()
method callsSendReminder#createReminderEmail(session, userEmail)
to create the content of the email, connects user’s email usingEMAILPASSWORD
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 theLess 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.