diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 09c95cacf..0d4199419 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -946,41 +946,76 @@ image::UndoRedoActivityDiagram.png[width="650"] //** Cons: Requires dealing with commands that have already been undone: We must remember to skip these commands. Violates Single Responsibility Principle and Separation of Concerns as `HistoryManager` now needs to do two different things. // end::undoredo[] -=== Data Encryption / Decryption feature +=== Data Exporting / Exporting feature -The storage file "PlanMySem.txt" is encrypted to prevent easy access of the user's calendar. -We are encrypting and decrypting the data using the Java Cypher class. -This feature is implemented through creating a Encryptor that contains encrypt and decrypt methods. The encrypt method takes a String object as an argument and returns a encrypted String object. The decrypt method takes in a String object as an argument and returns the decrypted message as a String object. +This feature exports the Planner into a .ics file. This section will detail how this feature is implemented. +{zwsp} -The encryption is done using AES/CBC/PKCS5Padding. The key used for encryption/decryption is generated randomly and stored in a file named "KeyStorage.jceks". No password is required from the user to retrieve this key, but a password input can be added in the KeyStorage.java class to improve security. + +{zwsp} -A initialization vector (IV) is required for the Cipher Block Chain (CBC) mode of encryption. A random IV is generated and appended at the beginning of the data before being stored. The IV is then retrieved from the same file to decrypt the data. +==== Current Implementation + +Upon entering the `export` command with valid parameters (refer to <> for `export` usage), the +following sequence of events is executed: + +1. The `ParserManager` parses the `export` command and calls the `parse` method in `ExportCommandParser`. +2. The `ExportCommandParser` then constructs a `ExportCommand` object with a filename. +3. The Command object is returned and execution will get the current `Semester` from `Model` +4. The `IcsSemester` is then constructed using `Semester` and converted to a `String`. +5. The `String` is then written to a file with the filename parsed. +5. The result of the command execution, `CommandResult`, will then returned to `Ui`. + +Given below is the Sequence Diagram upon executing the `export` command. + +.Sequence of implementation for the `export` Command +image::ExportCommandSequenceDiagram.PNG[width="800"] -Encryption of the data is done automatically before the file is saved. In the implementation, the AdaptedPlanner object is first marshaled into a StringWriter before being encrypted and written into the file. This is to ensure that the data is JAXB formatted and the save algorithm is unaffected. -Similarly, decryption of the data is done automatically before it is loaded. In the implementation, the file is read and decrypted and parsed into a StringReader object. The StringReader object is then un-marshaled and loaded. This is to ensure that the file is converted back into a JAXB object before being loaded and the load algorithm is unaffected. {zwsp} +The `ExportCommandParser` will check whether the optional filename parameter was input. If this parameter is included, the input filename is used. Else, if no other characters have been input (e.g. "export"), the default "PlanMySem" is used as the filename. +This process can be seen from the activity diagram in the figure below. + +.Activity diagram showing the workflows for `export` Command +image::ExportCommandActivityDiagram.PNG[width="800"] {zwsp} -=== Data Exporting / Exporting feature +==== Design Considerations + +This portion explains alternative implementations as well as the rationale behind my chosen method. + +===== Aspect: Using a .ics library + +* **Alternative 1 (current choice):** Writing my own .ics file. +** Pros: No need to include and understand how to use the external library. +** Cons: Difficult to read and work with .ics formatting. +* **Alternative 2:** Using iCal4j library to read and write .ics files. +** Pros: No need to manually format data into .ics format. +** Cons: Difficult to translate our recursion system to the .ics RRULE system. -The user can export the current planner into a .ics file to use in external calendar applications. The .ics file will contain the names of the slots in the SUMMARY field and the descriptions in the DESCRIPTION field. This command automatically exports into the main directory and names the file “PlanMySem.ics”. Future updates can include user input to allow saving the file in another directory and naming the file. -We have chosen to use the iCalendar format due to its popularity and its use in applications such as Google Calendar, Microsoft Outlook and NUSmods. +Reason for current choice: Using the library will allow `PlanMySem` to easily import non-native .ics files. However, this would require changes to `Model` as currently the recurrence for slots is not saved. + -In our implementation, we have chosen not to export the tags into the .ics file. This is because iCalendar does not have in-built tag fields. This means that other applications that import .ics will not be able to use the tags. +In addition, as our application is a specially designed planner for NUS matters, I felt that it was unnecessary to have the same slots on multiple applications. + + +Hence, I chose to code the reading and writing of .ics files and add a disclaimer that importing of non-native .ics files is likely to cause errors. {zwsp} {zwsp} -===== Aspect: Exporting tags into .ics file. +=== Data Encryption / Decryption feature -* **Alternative 1 (current choice):** Ignore tags when exporting. -** Pros: Easier to implement as iCalendar does not have in-built tag fields. -** Cons: Not all the information about the slots will be retained. -** Reason for choice: We do not have much control over other applications, and importing and exporting .ics within *PlanMySem* can be done using the storage .txt file. -* **Alternative 2:** Use the notes field and a tag identifier to save the tags. -** Pros: All the information from the semester will be exported. -** Cons: Requires other applications to be coded to read these tag identifiers and also to store and use the tags in their functions. +The storage file "PlanMySem.txt" is encrypted to prevent easy access of the user's calendar. + +==== Current Implementation + +We are encrypting and decrypting the data using the Java `Cipher`. +This feature is implemented through the `Encryptor` that contains the encrypt and decrypt methods. The encrypt method takes a `String` as an argument and returns a encrypted String object. The decrypt method takes in a String object as an argument and returns the decrypted message as a String object. + +The encryption is done using AES/CBC/PKCS5Padding. The key used for encryption/decryption is generated through various device parameters such as username, operating system (OS) and java runtime version. The secret key generated is stored in a file named "KeyStorage.jceks". No password is required from the user to retrieve this key, but a password input can be added to `KeyStorage` to improve security. + + +A initialization vector (IV) is required for the Cipher Block Chain (CBC) mode of encryption. A random IV is generated and appended at the beginning of the data before being stored. The IV is then retrieved from the same file to decrypt the data. + +Encryption of the data is done automatically before the file is saved. In the implementation, the AdaptedPlanner is first marshaled into a `StringWriter` before being encrypted and written into the file. This is to ensure that the data is JAXB formatted and the save algorithm is unaffected. +Similarly, decryption of the data is done automatically before it is loaded. In the implementation, the file is read and decrypted and parsed into a `StringReader`. The `StringReader` is then un-marshaled and loaded. This is to ensure that the file is converted back into a JAXB object before being loaded and the load algorithm is unaffected. {zwsp} {zwsp} @@ -988,8 +1023,8 @@ In our implementation, we have chosen not to export the tags into the .ics file. [[Implementation-Configuration]] === Configuration -// TODO: Julian please fill this section -//Certain properties of the application can be controlled (e.g user prefs file location, logging level) through the configuration file (default: `config.json`). +==== User Preferences [COMING IN 2.0] +The files generated by *PlanMySem* are also named "PlanMySem" and are saved in user's PlanMySem folder by default. This default filename and file path can be changed via the the configuration file (default: `config.json`). + There is no need for manual configuration of the `Semester` as it is initialized dynamically as mentioned in <>. {zwsp} @@ -1569,8 +1604,8 @@ Priorities: High (must have) - `* * \*`, Medium (nice to have) - `* \*`, Low (un [appendix] == Use Cases - -For all use cases below, the *System* is `PlanMySem` and the *Actor* is the `user`, unless specified otherwise. +This section describes the Use Cases for some of our implemented features. +(For all use cases below, the *System* is `PlanMySem` and the *Actor* is the `user`, unless specified otherwise) {zwsp} {zwsp} @@ -1684,7 +1719,18 @@ Use case ends. ** 4. System displays confirmation message. + Use case ends. - +* Extensions: +:: 1a. A filename is included in the command. +::: 1ai. The filename is valid. +:::: 1ai.1. System converts planner to .ics format. +:::: 1ai.2. System saves .ics file in the respective directory. +:::: 1ai.3. System displays confirmation message. ++ +Use case ends. +::: 1aii. The filename is invalid +:::: 1aii.1 System outputs error message. ++ +Use case ends. //=== Use Case: Add a Category //. User inputs command to add a new category along with the name of the new category. //. System reflects the addition made to the list of Categories. diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 3a3adbb54..132a63ccc 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -450,26 +450,10 @@ Planner data is automatically encrypted before saving and decrypted before loadi {zwsp} -[[import]] -=== Importing .ics formatted files `import` -You can import an .ics file into the planner. -Format: `import filename` -[NOTE] -==== -The .ics file can be imported into other calendar apps that support .ics files such as Google Calendar. The file to be imported has to be located in the PlanMySem main directory.+ -{zwsp} -==== -[WARNING] -For .ics files that are created from other calendar applications, events with recurrence will not be recursed in our -application. Events that are outside of the current school semester will also not be imported. - -{zwsp} - -{zwsp} - [[export]] === Exporting .ics formatted files: `export` You can export the planner as a .ics file. +Format: `export [fn/FILE_NAME]` [#img-export] .[.underline]#Output after entering `export`# @@ -477,16 +461,13 @@ image::Export_Command_Output_1.png[width="420"] [NOTE] ==== -The exported file is named "PlanMySem.ics" and is saved in the main directory. +The default name of the exported file is "PlanMySem.ics" and is saved in the main directory. The .ics file can be imported into other calendar apps that support .ics files such as Google Calendar. + [#img-exportFile] .[.underline]#Location of PlanMySem.ics file# image::Export_Command_Directory_1.png[width="800"] ==== -[WARNING] -Exporting will REMOVE all tags in the planner. - [TIP] A file with the ICS file extension is an iCalendar file. These are plain text files that include calendar event details like a description, beginning and ending times, location, etc. @@ -494,6 +475,17 @@ These are plain text files that include calendar event details like a descriptio {zwsp} +[[import]] +=== Importing native .ics files `import` +You can import a .ics file generated by *PlanMySem* into the current planner. +Format: `import [fn/FILE_NAME]/` + +[WARNING] +==== +This feature is to allow transfer of data between *PlanMySem* on different devices. This feature is NOT for importing non-native .ics files. Hence, only .ics files generated by *PlanMySem* should be imported. +==== +{zwsp} + [[clear]] === Clear all data : `clear` Clear all data stored on the planner. + @@ -627,8 +619,8 @@ Commands: |_<>_ |Export all your slots into a .ics file| `export` | `export` -|_<>_ |Import into your planner from a .ics file | -`import` | `import PlanMySem.ics` +|_<>_ |Import a native .ics file into your planner from a .ics file | +`import` | `import fn/PlanMySem` |======================================================================= {zwsp} diff --git a/docs/diagrams/ExportActivityDiagram.pptx b/docs/diagrams/ExportActivityDiagram.pptx new file mode 100644 index 000000000..eebad793b Binary files /dev/null and b/docs/diagrams/ExportActivityDiagram.pptx differ diff --git a/docs/diagrams/ExportSequenceDiagram.pptx b/docs/diagrams/ExportSequenceDiagram.pptx new file mode 100644 index 000000000..32436b91c Binary files /dev/null and b/docs/diagrams/ExportSequenceDiagram.pptx differ diff --git a/docs/diagrams/UndoRedoSequenceDiagram.pptx b/docs/diagrams/UndoRedoSequenceDiagram.pptx index 1811bc6a8..247958d0d 100644 Binary files a/docs/diagrams/UndoRedoSequenceDiagram.pptx and b/docs/diagrams/UndoRedoSequenceDiagram.pptx differ diff --git a/docs/images/ExportCommandActivityDiagram.PNG b/docs/images/ExportCommandActivityDiagram.PNG new file mode 100644 index 000000000..2c65c72fb Binary files /dev/null and b/docs/images/ExportCommandActivityDiagram.PNG differ diff --git a/docs/images/ExportCommandSequenceDiagram.PNG b/docs/images/ExportCommandSequenceDiagram.PNG new file mode 100644 index 000000000..e5ed89bd8 Binary files /dev/null and b/docs/images/ExportCommandSequenceDiagram.PNG differ diff --git a/docs/team/macchazuki.adoc b/docs/team/macchazuki.adoc index faa91e499..a6e3567db 100644 --- a/docs/team/macchazuki.adoc +++ b/docs/team/macchazuki.adoc @@ -2,33 +2,62 @@ :site-section: AboutUs :imagesDir: ../images :stylesDir: ../stylesheets +ifdef::env-github[] +:tip-caption: :bulb: +:note-caption: :information_source: +:important-caption: :heavy_exclamation_mark: +:caution-caption: :fire: +:experimental: +endif::[] +:repoURL: https://github.com/CS2113-AY1819S2-T08-3/main/blob/master + -== PROJECT: PlanMySem ---- +== PROJECT: PlanMySem -== About the project +My team and I were tasked with enhancing a basic command line interface addressbook application, https://github.com/CS2113-AY1819S2-T08-3/main[AddressBook Level 3], for our Software Engineering project. + -My team and I were tasked with enhancing a basic command line interface addressbook for our -Software Engineering project. We chose to morph it into a student planner for NUS students. This planner is automatically synchronised according to the NUS academic calendar for the current semester and enables easy creation, editing and deleting of items. +We chose to morph it into a student planner called *PlanMySem*. This planner is made specially for NUS students and staff, containing features that will help them manage their school schedules more easily. + +*PlanMySem* is automatically synchronised according to the current semester of the NUS academic calendar. Special weeks such as recess week and reading week are taken into account within our unique recursion system. -This allows NUS students to easily keep track of school related matters such as classes, deadlines and examinations. -Items can also be efficiently managed via the intuitive tagging system. + +This allows students and staff to easily keep track of school related matters such as classes, deadlines and examinations. +These activities can also be efficiently managed via the intuitive tagging system. The user can then view his schedule for the day or week (shown in the figure below), or view the current semester. + +[#img-view] +.[.underline]#Example of viewing the current week# +image::Ui.png[width="790"] {zwsp} {zwsp} +== Overview + +The next sections will illustrate my enhancements in more detail as well as my various contributions to the project. + +Kindly take note that throughout this portfolio, there will be various icons used as described as such. + +[TIP] +This is a tip. Follow these suggested tips to make your life much simpler when using *PlanMySem*! + +[NOTE] +This is a note. These are things for you to take note of when using *PlanMySem*. + +[CAUTION] +This is a sign-post informing caution. Please take note of these items and exercise some care. + == Summary of contributions +This section shows a summary of the features I have implemented in *PlanMySem* as well as some details regarding the implementation. * *Major enhancement 1*: I added the ability to *import .ics files* ** What it does: allows the user to import .ics files obtained from this or other applications. -[NOTE] +[TIP] .ics stands for a iCalendar file format. .ics files are one of the most commonly used calendar formats in applications such as Google Calendar and Outlook. ** Justification: This feature improves the product significantly because the user can import existing appointments on other calendar applications into PlanMySem, allowing him to combine external appointments with his school schedule. ** Highlights: This enhancement works with existing as well as future commands. In particular, this enhancement works hand-in-hand with 2 features that I will go into detail later: exporting and data and encryption. An in-depth analysis of the add command was necessary to understand how slots are added into our planner as I had to add multiple slots into the planner at once. -* *Code contributed*: [https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/src/planmysem/logic/commands/ImportCommand.java] +** Code available https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/src/planmysem/logic/commands/ImportCommand.java[here] {zwsp} * *Major enhancement 2*: I added the ability to *export .ics files* @@ -37,101 +66,188 @@ An in-depth analysis of the add command was necessary to understand how slots ar ** Highlights: This enhancement works with existing as well as future commands. In particular, this enhancement works hand-in-hand with the import feature described above. This allows the user to export a file that can be imported into PlanMySem on another device. This enhancement also allows the user to obtain a readable file as the data will be encrypted (discussed later). + An in-depth analysis of how the planner stores slots was necessary in order to extract their details to be exported. -* *Code contributed*: [https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/src/planmysem/logic/commands/ExportCommand.java] +** Code available https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/src/planmysem/logic/commands/ExportCommand.java[here] {zwsp} -* *Major enhancement 3*: I added data encryption of the storage file. +* *Minor enhancement*: I added data encryption of the storage file. ** What it does: the planner automatically encrypts the data before saving it into a .txt file. This data is then decrypted before being loaded by the application. ** Justification: This feature improves the product because the user's schedule data will not be able to easily obtained by others. ** Highlights: This enhancement works with existing as well as future commands. In particular, this enhancement works hand-in-hand with the import and export functions. As we have decided to encrypt the raw data file, the user will not be able to obtain the raw data of his planner. + As a result, the export function allows the user to obtain a read-able text file when he wishes to. + This enhancement also allows the user to obtain a readable file as the data will be encrypted (discussed later). + An in-depth analysis of how the planner data is stored was necessary to identify where encryption and decryption should be done on the data. Also, a general understanding of ciphers and data encryption was necessary in implementation of this enhancement. +** Code available https://github.com/CS2113-AY1819S2-T08-3/main/tree/master/src/planmysem/storage[here] -* *Code contributed*: [https://github.com/CS2113-AY1819S2-T08-3/main/tree/master/src/planmysem/storage] - +* *Code contributed*: + ** View my RepoSense contribution analysis: https://nuscs2113-ay1819s2.github.io/dashboard-beta/#=undefined&search=macchazuki[here] * *Other contributions*: ** Documentation: -*** Wrote Use Cases on the Developer Guide: [https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/docs/DeveloperGuide.adoc] +*** Wrote Use Cases on the Developer Guide: https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/docs/DeveloperGuide.adoc[here] == 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._ + -- https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/docs/UserGuide.adoc#encrypt + -- https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/docs/UserGuide.adoc#import + -- https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/docs/UserGuide.adoc#export + - -Below is an example of my contributions for the import and export features. + +- https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/docs/UserGuide.adoc#encrypt[Data Encryption] + +- https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/docs/UserGuide.adoc#import[Importing files] + +- https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/docs/UserGuide.adoc#export[Exporting files] + -{zwsp} -[[import]] -Importing .ics formatted files 'import filename' + -You can import an .ics file into the planner. -Format: `import filename` + -[NOTE] + -The .ics file can be imported into other calendar apps that support .ics files such as Google Calendar. The file to be imported has to be located in the PlanMySem main directory. + +|=== +[[encrypt]] +=== Encrypting/decrypting data files +Planner data is automatically encrypted before saving and decrypted before loading. You do not need to encrypt or decrypt the data manually. {zwsp} -[WARNING] + -For .ics files that are created from other calendar applications, events with recurrence will not be recursed in our -application. Events that are outside of the current school semester will also not be imported. {zwsp} [[export]] -Exporting .ics formatted files: `export` + -You can export the planner as a .ics file. + +=== Exporting .ics formatted files: `export` +You can export the planner as a .ics file. +Format: `export [fn/FILE_NAME]/` + +[#img-export] +.[.underline]#Output after entering `export`# +image::Export_Command_Output_1.png[width="420"] -[NOTE] + -The exported file is named "PlanMySem.ics" and is saved in the main directory. +[NOTE] +==== +The default name of the exported file is "PlanMySem.ics" and is saved in the main directory. The .ics file can be imported into other calendar apps that support .ics files such as Google Calendar. + +[#img-exportFile] +.[.underline]#Location of PlanMySem.ics file# +image::Export_Command_Directory_1.png[width="790"] +==== + +[TIP] +A file with the ICS file extension is an iCalendar file. +These are plain text files that include calendar event details like a description, beginning and ending times, location, etc. +{zwsp} -[WARNING] + -Exporting will REMOVE all tags in the planner. +{zwsp} +[[import]] +=== Importing native .ics files `import` +You can import a .ics file generated by *PlanMySem* into the current planner. +Format: `import [fn/FILE_NAME]/` + +[CAUTION] +==== +This feature is to allow transfer of data between *PlanMySem* on different devices. This feature is NOT for importing non-native .ics files. +==== +{zwsp} -|=== == 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._ + -- https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/docs/DeveloperGuide.adoc#data-encryption-decryption-feature + -- https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/docs/DeveloperGuide.adoc#data-exporting-exporting-feature + -- https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/docs/DeveloperGuide.adoc#use-cases + +- https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/docs/DeveloperGuide.adoc#data-exporting-exporting-feature[Exporting files] + +- https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/docs/DeveloperGuide.adoc#data-encryption-decryption-feature[Data Encryption] + +- https://github.com/CS2113-AY1819S2-T08-3/main/blob/master/docs/DeveloperGuide.adoc#use-cases[Use cases] + +|=== +=== Data Exporting / Exporting feature -Below is an example of my contributions in design considerations. +This feature exports the Planner into a .ics file. This section will detail how this feature is implemented. +{zwsp} + +{zwsp} + +==== Current Implementation -Data Exporting / Exporting feature +Upon entering the `export` command with valid parameters (refer to <> for `export` usage), the +following sequence of events is executed: -The user can export the current planner into a .ics file to use in external calendar applications. The .ics file will contain the names of the slots in the SUMMARY field and the descriptions in the DESCRIPTION field. This command automatically exports into the main directory and names the file “PlanMySem.ics”. Future updates can include user input to allow saving the file in another directory and naming the file. +1. The `ParserManager` parses the `export` command and calls the `parse` method in `ExportCommandParser`. +2. The `ExportCommandParser` then constructs a `ExportCommand` object with a filename. +3. The Command object is returned and execution will get the current `Semester` from `Model` +4. The `IcsSemester` is then constructed using `Semester` and converted to a `String`. +5. The `String` is then written to a file with the filename parsed. +5. The result of the command execution, `CommandResult`, will then returned to `Ui`. -We have chosen to use the iCalendar format due to its popularity and it’s use in applications such as Google Calendar, Microsoft Outlook and NUSmods. +Given below is the Sequence Diagram upon executing the `export` command. + +.Sequence of implementation for the `export` Command +image::ExportCommandSequenceDiagram.PNG[width="800"] -In our implementation, we have chosen not to export the tags into the .ics file. This is because iCalendar does not have in-built tag fields. This means that other applications that import .ics will not be able to use the tags. {zwsp} +The `ExportCommandParser` will check whether the optional filename parameter was input. If this parameter is included, the input filename is used. Else, if no other characters have been input (e.g. "export"), the default "PlanMySem" is used as the filename. +This process can be seen from the activity diagram in the figure below. + +.Activity diagram showing the workflows for `export` Command +image::ExportCommandActivityDiagram.PNG[width="800"] {zwsp} -**Aspect: Exporting tags into .ics file.** +==== Design Considerations -**Alternative 1 (current choice):** Ignore tags when exporting. +This portion explains alternative implementations as well as the rationale behind my chosen method. -** Pros: Easier to implement as iCalendar does not have in-built tag fields.** +===== Aspect: Using a .ics library -Cons: Not all the information about the slots will be retained. +* **Alternative 1 (current choice):** Writing my own .ics file. +** Pros: No need to include and understand how to use the external library. +** Cons: Difficult to read and work with .ics formatting. +* **Alternative 2:** Using iCal4j library to read and write .ics files. +** Pros: No need to manually format data into .ics format. +** Cons: Difficult to translate our recursion system to the .ics RRULE system. -**Reason for choice: We do not have much control over other applications, and importing and exporting .ics within *PlanMySem* can be done using the storageFile .txt file.** +Reason for current choice: Using the library will allow `PlanMySem` to easily import non-native .ics files. However, this would require changes to `Model` as currently the recurrence for slots is not saved. + -**Alternative 2:** Use the notes field and a tag identifier to save the tags. +In addition, as our application is a specially designed planner for NUS matters, I felt that it was unnecessary to have the same slots on multiple applications. + -** Pros: All the information from the semester will be exported.** +Hence, I chose to code the reading and writing of .ics files and add a disclaimer that importing of non-native .ics files is likely to cause errors. +{zwsp} -Cons: Requires other applications to be coded to read these tag identifiers and also to store and use the tags in their functions. -|=== +{zwsp} + +=== Data Encryption / Decryption feature + +The storage file "PlanMySem.txt" is encrypted to prevent easy access of the user's calendar. + +==== Current Implementation + +We are encrypting and decrypting the data using the Java `Cipher`. +This feature is implemented through the `Encryptor` that contains the encrypt and decrypt methods. The encrypt method takes a `String` as an argument and returns a encrypted String object. The decrypt method takes in a String object as an argument and returns the decrypted message as a String object. + +The encryption is done using AES/CBC/PKCS5Padding. The key used for encryption/decryption is generated through various device parameters such as username, operating system (OS) and java runtime version. The secret key generated is stored in a file named "KeyStorage.jceks". No password is required from the user to retrieve this key, but a password input can be added to `KeyStorage` to improve security. + + +A initialization vector (IV) is required for the Cipher Block Chain (CBC) mode of encryption. A random IV is generated and appended at the beginning of the data before being stored. The IV is then retrieved from the same file to decrypt the data. + +Encryption of the data is done automatically before the file is saved. In the implementation, the AdaptedPlanner is first marshaled into a `StringWriter` before being encrypted and written into the file. This is to ensure that the data is JAXB formatted and the save algorithm is unaffected. +Similarly, decryption of the data is done automatically before it is loaded. In the implementation, the file is read and decrypted and parsed into a `StringReader`. The `StringReader` is then un-marshaled and loaded. This is to ensure that the file is converted back into a JAXB object before being loaded and the load algorithm is unaffected. +{zwsp} + +{zwsp} + +[[Implementation-Configuration]] +=== Configuration + +==== User Preferences [COMING IN 2.0] +The files generated by *PlanMySem* are also named "PlanMySem" and are saved in user's PlanMySem folder by default. This default filename and file path can be changed via the the configuration file (default: `config.json`). + +There is no need for manual configuration of the `Semester` as it is initialized dynamically as mentioned in +<>. +{zwsp} + +{zwsp} + + +=== Use Case: Export planner +* MSS: +** 1. User inputs command to export the planner. +** 2. System converts planner to .ics format. +** 3. System saves .ics file in the main directory as "PlanMySem.ics". +** 4. System displays confirmation message. ++ +Use case ends. +* Extensions: +:: 1a. A filename is included in the command +:: 2a. System converts planner to .ics format. +:: 3a. System saves .ics file in the respective directory w. +:: 4a. System displays confirmation message. ++ +Use case ends. == PROJECT: PlanMySem diff --git a/docs/team/seanieyap.adoc b/docs/team/seanieyap.adoc index cc276bc5c..7a7b46bf9 100644 --- a/docs/team/seanieyap.adoc +++ b/docs/team/seanieyap.adoc @@ -26,7 +26,7 @@ In summary, *PlanMySem* offers the following features: //* Optimized for you if you prefer to work with a Command Line Interface (CLI) and/or are learning to work more efficiently with CLI tools. //* Utilizes minimal resources on your machine while still allowing you to view your schedules swiftly. -This application was developed as part of CS2113T, a software engineering module in the National University of Singapore (NUS), and consisted of 4 partners, <>, <>, <> +This application was developed as part of CS2113T, a software engineering module in the National University of Singapore (NUS), and consisted of 4 partners, <>, <>, <> and myself; in which I served as the team lead. I was responsible for the slot management feature (add, edit and delete commands) and the structure of the codebase. == Overview diff --git a/src/planmysem/logic/commands/ExportCommand.java b/src/planmysem/logic/commands/ExportCommand.java index 4f9c883ea..e83d23109 100644 --- a/src/planmysem/logic/commands/ExportCommand.java +++ b/src/planmysem/logic/commands/ExportCommand.java @@ -7,7 +7,9 @@ import planmysem.logic.CommandHistory; import planmysem.logic.commands.exceptions.CommandException; import planmysem.model.Model; +import planmysem.model.Planner; import planmysem.model.semester.IcsSemester; +import planmysem.model.semester.Semester; /** * Exports the calendar into a .ics file. @@ -29,10 +31,12 @@ public ExportCommand(String fileName) { @Override public CommandResult execute(Model model, CommandHistory commandHistory) throws CommandException { - IcsSemester semester = new IcsSemester(model.getPlanner().getSemester()); + Planner planner = model.getPlanner(); + Semester semester = planner.getSemester(); + IcsSemester icsSemester = new IcsSemester(semester); try { BufferedWriter writer = new BufferedWriter(new FileWriter(fileName + ".ics")); - writer.write(semester.toString()); + writer.write(icsSemester.toString()); writer.close(); } catch (IOException e) { throw new CommandException(MESSAGE_FAILED); diff --git a/src/planmysem/model/semester/IcsSemester.java b/src/planmysem/model/semester/IcsSemester.java index 87d782747..b7d1bfb44 100644 --- a/src/planmysem/model/semester/IcsSemester.java +++ b/src/planmysem/model/semester/IcsSemester.java @@ -15,9 +15,9 @@ public class IcsSemester { private String icsCalendar; /** - * Converts a given Slot into this class for .ics use. + * Converts the semester into this class for .ics use. * - * @param source Slot object to be converted into .ics format. + * @param source Semester object to be converted into .ics format. */ public IcsSemester(Semester source) { DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss"); diff --git a/src/planmysem/storage/Encryptor.java b/src/planmysem/storage/Encryptor.java index 6ef2a191a..3009f50d6 100644 --- a/src/planmysem/storage/Encryptor.java +++ b/src/planmysem/storage/Encryptor.java @@ -11,22 +11,30 @@ import planmysem.common.exceptions.IllegalValueException; /** - * Encrypts and decrypts a string using AES + * Contains methods to encrypt and decrypt strings */ public class Encryptor { private static int ivSize = 16; + public static String encrypt(String toEncrypt, String keyStorage) { + return executeEncrypt(toEncrypt, keyStorage); + } + + public static String encrypt(String toEncrypt) { + return executeEncrypt(toEncrypt, "KeyStorage.jceks"); + } + /** * Encrypts string using the AES algorithm - * * @param toEncrypt string to be encrypted + * @param keyStorage string .jceks file to load from. * @return encrypted string */ - public static String encrypt(String toEncrypt) { + private static String executeEncrypt(String toEncrypt, String keyStorage) { try { //Load key from KeyStore. - SecretKey key = KeyStorage.load(); + SecretKey key = KeyStorage.load(keyStorage); SecretKeySpec skeySpec = new SecretKeySpec(key.getEncoded(), "AES"); // Generating IV. @@ -49,18 +57,27 @@ public static String encrypt(String toEncrypt) { } catch (Exception ex) { return null; } + + } + + public static String decrypt(String toDecrypt, String keyStorage) throws IllegalValueException { + return executeDecrypt(toDecrypt, keyStorage); } + public static String decrypt(String toDecrypt) throws IllegalValueException { + return executeDecrypt(toDecrypt, "KeyStorage.jceks"); + } /** * Decrypts a string using the AES algorithm * * @param toDecrypt string to be decrypted + * @param keyStorage string .jceks file to load from. * @return decrypted string */ - public static String decrypt(String toDecrypt) throws IllegalValueException { + private static String executeDecrypt(String toDecrypt, String keyStorage) throws IllegalValueException { try { //Load key from KeyStore. - SecretKey key = KeyStorage.load(); + SecretKey key = KeyStorage.load(keyStorage); SecretKeySpec skeySpec = new SecretKeySpec(key.getEncoded(), "AES"); //Decode to bytes. @@ -85,4 +102,5 @@ public static String decrypt(String toDecrypt) throws IllegalValueException { throw new IllegalValueException("Error decrypting file. Reinitializing semester."); } } + } diff --git a/src/planmysem/storage/KeyStorage.java b/src/planmysem/storage/KeyStorage.java index c5b609cf1..ad0343703 100644 --- a/src/planmysem/storage/KeyStorage.java +++ b/src/planmysem/storage/KeyStorage.java @@ -27,27 +27,29 @@ public class KeyStorage { + System.getProperty("java.compiler")).hashCode()).toCharArray(); /** - * Loads the secret key from the key store. + * Loads the secret key from the specified key store. + * @param fileName String .jceks file to load from. */ - public static SecretKey load () throws Exception { + public static SecretKey load (String fileName) throws Exception { //Initialize keystore. KeyStore ks = KeyStore.getInstance("JCEKS"); SecretKey secretKey; try { - ks.load(new FileInputStream("KeyStorage.jceks"), password); + ks.load(new FileInputStream(fileName), password); secretKey = (SecretKey) ks.getKey("secret-key", password); } catch (IOException | CertificateException | UnrecoverableKeyException ex) { - secretKey = generateSecretKey(); + secretKey = generateSecretKey(fileName); } return secretKey; } /** - * Generates a SecretKey and saves it into a KeyStorage.jceks file. + * Generates a SecretKey and saves it in the specified file. + * @param fileName String .jceks file to save to. */ - private static SecretKey generateSecretKey() throws Exception { + private static SecretKey generateSecretKey(String fileName) throws Exception { //Initialize keystore. KeyStore ks = KeyStore.getInstance("JCEKS"); @@ -62,7 +64,7 @@ private static SecretKey generateSecretKey() throws Exception { ks.load(null, null); ks.setEntry("secret-key", secret, passwordParam); - FileOutputStream fos = new FileOutputStream("KeyStorage.jceks"); + FileOutputStream fos = new FileOutputStream(fileName); ks.store(fos, password); return secretKey; diff --git a/src/planmysem/storage/StorageFile.java b/src/planmysem/storage/StorageFile.java index a9bf7828a..fead89b3b 100644 --- a/src/planmysem/storage/StorageFile.java +++ b/src/planmysem/storage/StorageFile.java @@ -103,7 +103,8 @@ public Planner load() throws StorageOperationException { final AdaptedPlanner loaded; //decrypts if (isEncrypted) { - StringReader decryptedData = new StringReader(Encryptor.decrypt(fileReader.readLine())); + StringReader decryptedData; + decryptedData = new StringReader(Encryptor.decrypt(fileReader.readLine())); loaded = (AdaptedPlanner) unmarshaller.unmarshal(decryptedData); } else { loaded = (AdaptedPlanner) unmarshaller.unmarshal(fileReader); diff --git a/test/java/planmysem/logic/Commands/ExportCommandTest.java b/test/java/planmysem/logic/Commands/ExportCommandTest.java index a4be3b02b..2adb2e526 100644 --- a/test/java/planmysem/logic/Commands/ExportCommandTest.java +++ b/test/java/planmysem/logic/Commands/ExportCommandTest.java @@ -27,7 +27,6 @@ public class ExportCommandTest { @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); - private String tempFolderPath; private Model model; private Model expectedModel; diff --git a/test/java/planmysem/storage/EncryptorTest.java b/test/java/planmysem/storage/EncryptorTest.java index 487b3471d..e0ed3b6c2 100644 --- a/test/java/planmysem/storage/EncryptorTest.java +++ b/test/java/planmysem/storage/EncryptorTest.java @@ -3,20 +3,32 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; + import planmysem.common.exceptions.IllegalValueException; public class EncryptorTest { + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + private String tempFolderPath; + + @Before + public void setup() { + tempFolderPath = tempFolder.getRoot().getPath() + "Test.jceks"; + } @Test public void encrypt_valid() { - String testString = Encryptor.encrypt("Hello World!"); + String testString = Encryptor.encrypt("Hello World!", tempFolderPath); assertNotEquals(testString, "HellO World!"); } @Test public void decrypt_valid() throws IllegalValueException { - String testString = Encryptor.encrypt("Hello World!"); - assertEquals(Encryptor.decrypt(testString), "Hello World!"); + String testString = Encryptor.encrypt("Hello World!", tempFolderPath); + assertEquals(Encryptor.decrypt(testString, tempFolderPath), "Hello World!"); } } diff --git a/test/java/planmysem/storage/KeyStorageTest.java b/test/java/planmysem/storage/KeyStorageTest.java index 943ca502b..4d7888cd2 100644 --- a/test/java/planmysem/storage/KeyStorageTest.java +++ b/test/java/planmysem/storage/KeyStorageTest.java @@ -3,17 +3,27 @@ import static org.junit.Assert.assertTrue; import java.io.File; -import java.nio.file.Files; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; public class KeyStorageTest { + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + private String tempFolderPath; + + @Before + public void setup() { + tempFolderPath = tempFolder.getRoot().getPath() + "Test.jceks"; + } + @Test public void load_keyStore_fileInvalid() throws Exception { - Files.deleteIfExists(new File("KeyStorage.jceks").toPath()); - KeyStorage.load(); + KeyStorage.load(tempFolderPath); - assertTrue(new File("KeyStorage.jceks").exists()); + assertTrue(new File(tempFolderPath).exists()); } }