This portfolio highlights my contributions to the project when studying in School of Computing, National University of Singapore.

PROJECT: Bibliotek


Bibliotek is a free book cataloguing application that is simple, fast and easy to use. You can use Bibliotek to search for books, manage your reading list and track the availability of your books.

Overview

Bibliotek is a desktop book management application used for teaching Software Engineering principles. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC.

Summary of contributions

  • Encrypt data with a password (major)

    • Add two class cipherEngine and LockManagement to help encrypt/decrypt the data/password and keep the data safe.

    • Add an ecrypt data function to let bookshelf.xml to be encrypted when user set a non-default password.

    • Add one check of isProtect value in LockManagement to decide whether encrypt the bookshelf.xml before saving the data.

    • Add lock, unlock and setpw command to do lock management. If password is not default(""), everytime user open the application, he should unlock the bookshelf using password before he can do further instructions.

    • This allows users to keep their data private and safe.

  • Mark a book as read, change the priority of a book and rate books (minor)

    • Added attributes rating, (status and priority by others).

    • Added edit command that allows user to rating, set status and change priority of some books.

    • Added parser for three attributes.

    • This allows the user to keep track of what to read and what have been read and give recommendations to others.

  • Set command to be case insensitive(minor)

    • Added case insensitive to the command.

    • This allows the user to type in command without worry about the case, and make user easy to use our application.

  • Code contributed: [Functional code] [Test code] {give links to collated code files}

  • Other contributions:

    • Project management:

    • Enhancements to existing features:

      • Added the ratingbook command.

      • Added in Edit book command. (Pull requests #111)

      • Added in lock command.

      • Added in unlock and setpw command.

      • Added in data file encryption and decryption features.

      • Added in the data file encryption enhancement. (Pull requests #134)

      • Added one case insensitive feature. (Pull requests #179)

    • Documentation:

      • Added my major and minor feature into UserGuide and DeveloperGuide, adding my Project Portfolio. (#193)

    • Community:

Contributions to the User Guide

Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users.

Editing a book : edit (since v1.4)

After reading a book, you may want to give the book a rating or set the book as read. Or, you may want to change the priority of books to remind yourself what you should read next. These can be done using edit.
Format: edit INDEX [s/STATUS] [p/PRIORITY] [r/RATING]

  • Edits the book at the specified INDEX. The index refers to the index number shown in the most recent listing. The index must be a positive integer 1, 2, 3, …​

  • At least one of the optional fields must be provided.

  • Existing values will be updated to the input values.

  • STATUS must be one of the following (items in parenthesis are aliases): read (r), unread (u), or reading (rd).

  • PRIORITY must be one of the following (items in parenthesis are aliases): none (n), low (l), medium (m), or high (h).

  • RATING must be a valid rating from 0 to 5, or -1 to remove rating.

You can only edit books from your book shelf.

Suppose you have a few unread books in your book shelf.

EditCommandStart

You may want to differentiate them based on how eager you are to read each book. This helps you to better keep track of what you plan to read next, and also allows you to view the books in a more useful order.
For example, if you feel that reading Gel Electrophoresis of Proteins is more urgent than reading the other books, you can change its priority to high using edit 3 p/high.

Bibliotek shows Edited Book: TITLE - Authors: AUTHORS to indicate that the edit was successful. In the left panel, you can see that the priority label of Gel Electrophoresis of Proteins is changed to High.

EditCommandMid

Other examples:

  • edit 3 p/low
    Changes the priority of the 3rd book to LOW.

  • edit 2 s/read r/5
    Marks the 2nd book as READ and changes its rating to 5.

Changing/Setting a password : setpw (since v1.5)

If you want to keep your data secure, you can opt to set a password for Bibliotek. This password will be used to encrypt your data. After starting up Bibliotek, you will have to unlock it using your password before being able to perform any commands.
Format: setpw [old/OLD_PASSWORD] [new/NEW_PASSWORD]

  • Changes the password from OLD_PASSWORD to NEW_PASSWORD.

  • OLD_PASSWORD and NEW_PASSWORD are case sensitive.

  • At least one of the 2 fields must be provided.

  • By default, there is no password.

To set a password, use setpw new/NEW_PASSWORD.
Similarly, to delete the password, use setpw old/OLD_PASSWORD.

If the OLD_PASSWORD that you provided is correct, Bibliotek shows Successfully changed your password to indicate that your password is changed.

setpassword1

On the other hand, if the OLD_PASSWORD that you provided is incorrect, Bibliotek shows Incorrect old password. Please try again. to indicate that your password is not changed.

setpassword2
If you provide a OLD_PASSWORD when you in fact have no password, it is considered to be incorrect.
You should remember your password after setting a new one.

Locking the app : lock (since v1.5)

If you are going away for a moment and want to prevent others from messing with the application, you can perform lock.
Format: lock

  • Locks the app. No commands can be performed other than help and unlock.

  • The app is locked upon start up if you have a password.

If you perform lock without a password, anyone can unlock your application.

When you perform lock, Bibliotek responds with Successfully locked the app. to indicate that your lock is successful. All your displayed books will be hidden and the welcome panel will be shown on the right panel.

LockCommand

If your application is locked, you cannot perform any commands other than help and unlock. Performing any other valid commands, for example list, will be responded with The app is locked, please unlock it first!.

LockCommandMessage

Unlocking the app : unlock (since v1.5)

If you previously performed lock, use unlock to unlock the app.
Format: unlock PASSWORD

  • Unlocks the app.

  • PASSWORD is case sensitive. Leading and trailing spaces are ignored.

If you did not set a password, simply type unlock to unlock the app.

When you perform unlock with your password, Bibliotek responds with Succesfully unlocked the app. to indicate that your unlock is successful. All the books in your book shelf will be displayed.

UnlockCommand
If you really forgot your password and cannot unlock the system, you can reset Bibliotek by deleting all your data files.

Contributions to the Developer Guide

Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project.

Edit status, priority, and rating of books

The edit command allows the user to change the priority, status and rating of books in his/her book shelf to facilitate organization and management of books.

Current implementation

When edit command is entered,

  1. EditCommandParser will extract the index and the parameters from the user input.

  2. EditCommandParser checks that at least one parameter is present, and that the parameter(s) are valid.

  3. EditCommandParser creates an EditCommand with the index and parameter(s).

  4. EditCommand is preprocessed to check that ActiveListType is correct and index is valid.

  5. The Book to edit (bookToEdit) is identified by the index. Another Book (editedBook) is created based on the specified parameters.

  6. editedBook replaces bookToEdit in BookShelf.

Sequence Diagram

editseq

Design considerations

Aspect: Presentation of rating
  • Alternative 1: Show users the rating as a number.

    • Pros: Easy to implement.

    • Cons: Not aesthetically appealing.

  • Alternative 2 (current choice): Show users the rating as stars.

    • Pros: Difficult to implement.

    • Cons: Improves the aesthetic appeal and clarity.

Aspect: Interpretation of unspecified parameters
  • Alternative 1 (current choice): Unspecified parameters are left unchanged.

    • Pros: Users can omit parameters that they do not wish to change.

    • Cons: More difficult to implement.

  • Alternative 2: Unspecified parameters are set to default value.

    • Pros: Easy to implement.

    • Cons: Users need to specify all parameters to change one.

Encrypt data

This allows the user to protect his book shelf data with a password so that others cannot gain access to these data.

Current implementation

Encrypt the Bookshelf.xml

An addition class CipherEngine is added to the Bookshelf class. This class contatins some methods to encrypt or decrypt file(Bookshelf.xml)and password.
Note that when 'CipherEngine' encrypt the file, it will use the (encryped)password.

  • Every time user make change in Bookshelf

    1. The model manager will post an BookshelfChangedEvent.

    2. Before saving the data into Bookshelf.xml, the system will check whether Bookshelf is protected by the password(checking whether the password is defaultpassword: "").

    3. When the password is not default, the Bookshelf.xml will be encrypted.

  • Every time user set the new password

    1. The Setpwcommand will check the password.

    2. If the new password is equal to "", the Lockmanager will set isProtected to be false.

    3. The isProtect will be checked by xmlBookshelfstorage whether to encrypt the "Bookshelf.xml" and save the data into Bookshelf.xml.

  • When the system need to be encrypt

    1. The password will be encode, and set it to be a key to encrypt the file(Bookshelf.xml).

Lock the book shelf

An addition class LockManager is added to save the password and the situation of the locking system.
The default password provided for the new user is defaultpassword(""), which means that the Bookshelf is not locked.

  • When Lock command is entered

    1. LockCommand is processed to set isLock(LockManager) to be true.

. The Bookshelf cannot be run any command except unlock and help command.
  • When the Bookshelf is locked and unlock command is entered

    1. UnlockCommandParser will extract password from the user input.

    2. UnlockCommandParser creates an UnlockCommand for the password.

    3. UnlockCommand is preprocessed to execute `LockManager’s unlock(password).

    4. If the password is corrct, the unlock will be run successfully, otherwise it will send a WRONG_PASSWORD commandresult.

    5. UnlockCommand is processed to set isLock(LockManager) to be false.

  • When setpw command is entered

    1. setpasswordCommandParser will extract the old key and new key from the user input.

    2. setpwParser checks that two parameters are valid.

    3. setpasswordCommandParser creates an setpwCommand with the parameters.

    4. setpwCommand is preprocessed to check that oldKey is correct using LockManager.

    5. If the oldKey is correct, setpwCommand will post a passwordChangedevent.

    6. MainApp will handle it, and set UserPrefs.password to be new encoded password(using cipherEngine).

  • The encode key are implement in this way: [source,java]

    public static String encrypKey(String mykey) throws Exception {
        byte[] byarray = encrypt(mykey.getBytes(ENCODE), defaultKey.getBytes(ENCODE));
        String encryptkey = new BASE64Encoder().encode(byarray);
        return encryptkey;
    }

    public static byte[] encrypt(byte[] mykey, byte[] key) throws Exception {
        SecureRandom secureRandom = new SecureRandom();

        DESKeySpec desKeySpec = new DESKeySpec(key);

        SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(DES);
        SecretKey securekey = secretKeyFactory.generateSecret(desKeySpec);

        Cipher cipher = Cipher.getInstance(DES);

        cipher.init(Cipher.ENCRYPT_MODE, securekey, secureRandom);

        return cipher.doFinal(mykey);
    }
  • The encode key are implement in this way:

    public static String decryptKey(String yourkey) throws IOException, Exception {
        if (yourkey == null) {
            return null;
        }
        BASE64Decoder base64Decoder = new BASE64Decoder();
        byte[] decodeBuffer = base64Decoder.decodeBuffer(yourkey);
        byte[] bytes = decrypt(decodeBuffer, defaultKey.getBytes(ENCODE));
        return new String(bytes, ENCODE);
    }

    private static byte[] decrypt(byte[] yourkey, byte[] key) throws Exception {

        SecureRandom secureRandom = new SecureRandom();

        DESKeySpec desKeySpec = new DESKeySpec(key);

        SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(DES);
        SecretKey securekey = secretKeyFactory.generateSecret(desKeySpec);

        Cipher cipher = Cipher.getInstance(DES);

        cipher.init(Cipher.DECRYPT_MODE, securekey, secureRandom);

        return cipher.doFinal(yourkey);
    }