diff --git a/.github/workflows/main2.yml b/.github/workflows/main2.yml
index d5b541c9..f438854f 100644
--- a/.github/workflows/main2.yml
+++ b/.github/workflows/main2.yml
@@ -53,6 +53,12 @@ jobs:
run: flutter test
working-directory: client
+ - name: Decode keystore file
+ env:
+ KEYSTORE: ${{ secrets.KEYSTORE }}
+ run: |
+ echo $KEYSTORE | base64 --decode > /home/runner/work/Koja/Koja/client/android/app/mykey.jks
+
- name: Build Flutter app
run: flutter build apk
working-directory: client
diff --git a/README.md b/README.md
index 6886541f..079011c2 100644
--- a/README.md
+++ b/README.md
@@ -5,33 +5,39 @@
[![Repo Size](https://img.shields.io/github/repo-size/COS301-SE-2023/Koja.svg)](https://github.com/COS301-SE-2023/Koja)
[![Koja Build Status](https://github.com/COS301-SE-2023/Koja/actions/workflows/main2.yml/badge.svg)](https://github.com/COS301-SE-2023/Koja/actions/workflows/main2.yml)
+
+
+
+
+
## Project Description:
Koja is a system that enables more efficient time utilisation through dynamic and fixed time allocation for specific tasks a user wants to complete. Koja's aim is to minimise solve the burden of schedule management while requiring minimal effort from the user.
+# Advertisement
+https://github.com/COS301-SE-2023/Koja/assets/105129419/1d39ca2c-c081-4534-94d4-7558d399c484
+
# Documentation
* [SRSv4](https://www.canva.com/design/DAFm6EdVuUo/d1PDPN7l5k5e_cx3V7UT1A/edit?utm_content=DAFm6EdVuUo&utm_campaign=designshare&utm_medium=link2&utm_source=sharebutton)
* [Project Board](https://github.com/orgs/COS301-SE-2023/projects/37)
-## Demo Videos
-* [Team Caffeine-Demo1](https://drive.google.com/file/d/165ckgDKdO0YbYHQ_8qtw9sJ56FZ6jSGC/view?usp=sharing)
+## Demo Slide & Video
+* [Team Caffeine - Demo Slide](https://www.canva.com/design/DAFuI_vIphg/Ux_tSd2K-evrvKIDnCR8PA/edit?utm_content=DAFuI_vIphg&utm_campaign=designshare&utm_medium=link2&utm_source=sharebutton)
-* [Team Caffeine-Demo2](https://www.canva.com/design/DAFmn-ECx6w/1bhJhvtIjHPHMSG7kXUJhA/edit?utmcontent=DAFmn-ECx6w&utm_campaign=designshare&utm_medium=link2&utm_source=sharebutton)
+* [Team Caffeine - Demo Video](https://drive.google.com/file/d/1HWAUgzdQUKvIi33rHqagadPkk6OxEqA-/view?usp=drive_link)
-* [Team Caffeine-Demo3](https://www.canva.com/design/DAFoP47g3sw/_QjN9Yd8liAkDbpPl9SBhg/edit?utm_content=DAFoP47g3sw&utm_campaign=designshare&utm_medium=link2&utm_source=sharebutton)
-
-* [Team Caffeine-Demo4](https://www.canva.com/design/DAFuI_vIphg/Ux_tSd2K-evrvKIDnCR8PA/edit?utm_content=DAFuI_vIphg&utm_campaign=designshare&utm_medium=link2&utm_source=sharebutton)
## Additional Documentations
* [Technical Installation Manual](https://docs.google.com/document/d/1pdzUM2YM_lkqxtvTfs2MToCcu3zSB6QwQbP5pfhyjHk/edit?usp=sharing)
* [User Manual](https://docs.google.com/presentation/d/1cPbn8JxNLQUwRQt_2Euw9KsLvmQ2d15Y-28ukS4Yh1A/edit?usp=drive_link)
-* [Contributions](https://docs.google.com/document/d/1OVnDnd-1888-pUsX0dXAO_8Iy7R1oDDPmhMQqGZD8TI/edit?usp=sharing)
-
* [Coding Standards](https://docs.google.com/document/d/1jZFns50dd7gQlAGJpq--38faijdhuxrOiWK_JtvKXQI/edit?usp=sharing)
* [Architectural Design](https://docs.google.com/document/d/1hVQcrOcnCRzHyd9Y-aXYuAfyRZxVVZTiJyluJbr_0RY/edit?usp=sharing)
+* [Testing Policy Document](https://docs.google.com/document/d/10JTOApaAbRHdl4zoTkm39UPMgZYwPrVCrqgX5lBN5EA/edit?usp=sharing)
+# Technologies
+* Flutter, SpringBoot, Kotlin, Amazon RDS, Amazon DynamoDB
# Team
📧 Team email: [teamcaffeine23@gmail.com](mailto:teamcaffeine23@gmail.com)
diff --git a/client/analysis_options.yaml b/client/analysis_options.yaml
index e8c38882..954f5df4 100644
--- a/client/analysis_options.yaml
+++ b/client/analysis_options.yaml
@@ -1,6 +1,3 @@
-
-include: package:lints/recommended.yaml
-
linter:
rules:
avoid_print: true
\ No newline at end of file
diff --git a/client/android/app/build.gradle b/client/android/app/build.gradle
index f72e47c1..fdb93a67 100644
--- a/client/android/app/build.gradle
+++ b/client/android/app/build.gradle
@@ -45,7 +45,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
- applicationId "com.example.client"
+ applicationId "com.teamcaffeine.koja"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion 21
@@ -67,7 +67,7 @@ android {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
- // signingConfig signingConfigs.debug
+ signingConfig signingConfigs.debug
}
debug{
diff --git a/client/android/app/src/main/AndroidManifest.xml b/client/android/app/src/main/AndroidManifest.xml
index 19a809b6..5618cba7 100644
--- a/client/android/app/src/main/AndroidManifest.xml
+++ b/client/android/app/src/main/AndroidManifest.xml
@@ -1,6 +1,6 @@
-
+
+
+
+
diff --git a/client/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png b/client/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..4f932767
Binary files /dev/null and b/client/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png differ
diff --git a/client/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png b/client/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..175f821b
Binary files /dev/null and b/client/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png differ
diff --git a/client/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png b/client/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..6486158e
Binary files /dev/null and b/client/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png differ
diff --git a/client/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png b/client/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..6d58a66e
Binary files /dev/null and b/client/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png differ
diff --git a/client/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png b/client/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 00000000..ab698e2f
Binary files /dev/null and b/client/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/client/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/client/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 00000000..5f349f7f
--- /dev/null
+++ b/client/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/client/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/client/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
index db77bb4b..2ad368a9 100644
Binary files a/client/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/client/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/client/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/client/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
index 17987b79..de8d8066 100644
Binary files a/client/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/client/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/client/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/client/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
index 09d43914..99eeb4c3 100644
Binary files a/client/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/client/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/client/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/client/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
index d5f1c8d3..f70219ff 100644
Binary files a/client/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/client/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/client/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/client/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
index 4d6372ee..c115aeab 100644
Binary files a/client/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/client/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/client/android/app/src/main/res/values/colors.xml b/client/android/app/src/main/res/values/colors.xml
new file mode 100644
index 00000000..a26c650a
--- /dev/null
+++ b/client/android/app/src/main/res/values/colors.xml
@@ -0,0 +1,4 @@
+
+
+ #6B1DE2
+
\ No newline at end of file
diff --git a/client/assets/icons/coffee.png b/client/assets/icons/coffee.png
deleted file mode 100644
index 14cd46a0..00000000
Binary files a/client/assets/icons/coffee.png and /dev/null differ
diff --git a/client/assets/icons/google.png b/client/assets/icons/google.png
deleted file mode 100644
index e7d106c4..00000000
Binary files a/client/assets/icons/google.png and /dev/null differ
diff --git a/client/assets/icons/google1.png b/client/assets/icons/google1.png
deleted file mode 100644
index 894ca6aa..00000000
Binary files a/client/assets/icons/google1.png and /dev/null differ
diff --git a/client/assets/icons/koja1.png b/client/assets/icons/koja1.png
deleted file mode 100644
index 2e3ad29c..00000000
Binary files a/client/assets/icons/koja1.png and /dev/null differ
diff --git a/client/assets/icons/koja_foreground.png b/client/assets/icons/koja_foreground.png
new file mode 100644
index 00000000..16051c07
Binary files /dev/null and b/client/assets/icons/koja_foreground.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
index dc9ada47..957b0a48 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
index 7353c41e..b8e78cd8 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
index 797d452e..d2d8468c 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
index 6ed2d933..ae7de895 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
index 4cd7b009..4b40c2c6 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
index fe730945..b4b24258 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
index 321773cd..ff60d05f 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
index 797d452e..d2d8468c 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
index 502f463a..92648387 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
index 0ec30343..2f17ab10 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png
new file mode 100644
index 00000000..8c0b6b08
Binary files /dev/null and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png
new file mode 100644
index 00000000..f3c60d3a
Binary files /dev/null and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png
new file mode 100644
index 00000000..cf45c28c
Binary files /dev/null and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png
new file mode 100644
index 00000000..724cb0b1
Binary files /dev/null and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
index 0ec30343..2f17ab10 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
index e9f5fea2..7a07b72e 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png
new file mode 100644
index 00000000..7494288a
Binary files /dev/null and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png
new file mode 100644
index 00000000..aa8d4116
Binary files /dev/null and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
index 84ac32ae..fad9bff3 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
index 8953cba0..5e9b1b06 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ
diff --git a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
index 0467bf12..2d794120 100644
Binary files a/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/client/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ
diff --git a/client/ios/Runner/Info.plist b/client/ios/Runner/Info.plist
index daa8eafc..5abf9f6d 100644
--- a/client/ios/Runner/Info.plist
+++ b/client/ios/Runner/Info.plist
@@ -7,7 +7,7 @@
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleDisplayName
- Client
+ Koja
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
@@ -15,7 +15,7 @@
CFBundleInfoDictionaryVersion
6.0
CFBundleName
- client
+ Koja
CFBundlePackageType
APPL
CFBundleShortVersionString
diff --git a/client/lib/Utils/environment_variable_constants.dart b/client/lib/Utils/environment_variable_constants.dart
index b81de094..3989a20d 100644
--- a/client/lib/Utils/environment_variable_constants.dart
+++ b/client/lib/Utils/environment_variable_constants.dart
@@ -1,20 +1,5 @@
class EnvironmentVariableConstant {
- static const String kojaAwsRdsDatabaseUrl = "KOJA_AWS_RDS_DATABASE_URL";
- static const String kojaAwsRdsDatabaseAdminUsername = "KOJA_AWS_RDS_DATABASE_ADMIN_USERNAME";
- static const String kojaAwsRdsDatabaseAdminPassword = "KOJA_AWS_RDS_DATABASE_ADMIN_PASSWORD";
- static const String kojaAwsDynamodbAccessKeyId = "KOJA_AWS_DYNAMODB_ACCESS_KEY_ID";
- static const String kojaAwsDynamodbAccessKeySecret = "KOJA_AWS_DYNAMODB_ACCESS_KEY_SECRET";
- static const String googleClientId = "GOOGLE_CLIENT_ID";
- static const String googleClientSecret = "GOOGLE_CLIENT_SECRET";
- static const String googleMapsApiKey = "GOOGLE_MAPS_API_KEY";
- static const String kojaJwtSecret = "KOJA_JWT_SECRET";
- static const String openaiApiKey = "OPENAI_API_KEY";
- static const String kojaIdSecret = "KOJA_ID_SECRET";
- static const String coverallsRepoToken = "COVERALLS_REPO_TOKEN";
- static const String kojaPrivateKeyPass = "KOJA_PRIVATE_KEY_PASS";
- static const String kojaPrivateKeySalt = "KOJA_PRIVATE_KEY_SALT";
- static const String aiPrivateKeyPass = "AI_PRIVATE_KEY_PASS";
- static const String aiPrivateKeySalt = "AI_PRIVATE_KEY_SALT";
- static const String serverAddress = "SERVER_ADDRESS";
- static const String serverPort = "SERVER_PORT";
+ static const String googleMapsApiKey = "koja_google_maps_api_key";
+ static const String serverAddress = "koja_server_address";
+ static const String serverPort = "koja_server_port";
}
\ No newline at end of file
diff --git a/client/lib/assets/icons/artificial-intelligence.png b/client/lib/assets/icons/artificial-intelligence.png
deleted file mode 100644
index 79192193..00000000
Binary files a/client/lib/assets/icons/artificial-intelligence.png and /dev/null differ
diff --git a/client/lib/assets/icons/computer.png b/client/lib/assets/icons/computer.png
deleted file mode 100644
index 6dc55cb0..00000000
Binary files a/client/lib/assets/icons/computer.png and /dev/null differ
diff --git a/client/lib/assets/icons/destination.png b/client/lib/assets/icons/destination.png
deleted file mode 100644
index 4e92fba1..00000000
Binary files a/client/lib/assets/icons/destination.png and /dev/null differ
diff --git a/client/lib/assets/icons/google-calendar.png b/client/lib/assets/icons/google-calendar.png
deleted file mode 100644
index 3ed934f0..00000000
Binary files a/client/lib/assets/icons/google-calendar.png and /dev/null differ
diff --git a/client/lib/assets/icons/home.png b/client/lib/assets/icons/home.png
deleted file mode 100644
index d59b92cc..00000000
Binary files a/client/lib/assets/icons/home.png and /dev/null differ
diff --git a/client/lib/assets/icons/schedule-time.png b/client/lib/assets/icons/schedule-time.png
deleted file mode 100644
index 9697a390..00000000
Binary files a/client/lib/assets/icons/schedule-time.png and /dev/null differ
diff --git a/client/lib/assets/icons/schedule.png b/client/lib/assets/icons/schedule.png
deleted file mode 100644
index 05ac6724..00000000
Binary files a/client/lib/assets/icons/schedule.png and /dev/null differ
diff --git a/client/lib/assets/icons/stress.png b/client/lib/assets/icons/stress.png
deleted file mode 100644
index 126c3e98..00000000
Binary files a/client/lib/assets/icons/stress.png and /dev/null differ
diff --git a/client/lib/assets/icons/user.png b/client/lib/assets/icons/user.png
deleted file mode 100644
index 39ce13b7..00000000
Binary files a/client/lib/assets/icons/user.png and /dev/null differ
diff --git a/client/lib/providers/service_provider.dart b/client/lib/providers/service_provider.dart
index b750bb54..50129f07 100644
--- a/client/lib/providers/service_provider.dart
+++ b/client/lib/providers/service_provider.dart
@@ -158,7 +158,7 @@ class ServiceProvider with ChangeNotifier {
}
/// This function will attempt to add another email using UserAccountController
- Future addEmail({required ContextProvider eventProvider}) async {
+ Future addEmail({required ContextProvider eventProvider}) async {
final String authUrl =
'$_serverAddress:$_serverPort/api/v1/user/auth/add-email/google?token=$_accessToken';
@@ -169,11 +169,16 @@ class ServiceProvider with ChangeNotifier {
callbackUrlScheme: callbackUrlScheme,
);
- response = Uri.parse(response).queryParameters['token'];
+ final parsedResponse = Uri.parse(response).queryParameters;
- setAccessToken(response, eventProvider);
-
- return accessToken != null;
+ if(parsedResponse.containsKey("token")) {
+ setAccessToken(parsedResponse["token"], eventProvider);
+ return true;
+ }
+ else if(parsedResponse.containsKey("error"))
+ {
+ return null;
+ } else return false;
}
/// This function will attempt to delete an email from the user's account
diff --git a/client/lib/screens/suggestions_screens.dart b/client/lib/screens/suggestions_screens.dart
index a82bf9b1..de540c6d 100644
--- a/client/lib/screens/suggestions_screens.dart
+++ b/client/lib/screens/suggestions_screens.dart
@@ -3,6 +3,7 @@ import 'package:koja/Utils/event_util.dart';
import 'package:koja/providers/context_provider.dart';
import 'package:provider/provider.dart';
import 'package:syncfusion_flutter_calendar/calendar.dart';
+import 'package:lottie/lottie.dart';
import '../providers/service_provider.dart';
import '../widgets/calendar_widget.dart';
@@ -125,8 +126,34 @@ class _SuggestionsTasksScreenState extends State {
}
else
{
+ // return Center(
+ // child: Text('Koja\'s suggestion engine is still learning.\nPlease try again soon.'),
+ // );
return Center(
- child: Text('Koja\'s suggestion engine is still learning.\nPlease try again soon.'),
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Container(
+ alignment: Alignment.center,
+ child: Lottie.asset(
+ 'assets/animations/ai.json',
+ height: 200,
+ width: 300,
+ repeat: false,
+ ),
+ ),
+ Center(
+ child: Text(
+ 'Koja\'s suggestion engine is still learning.\nPlease try again soon.',
+ style: TextStyle(
+ fontSize: 16,
+ fontWeight: FontWeight.w500,
+ fontFamily: 'Raleway'),
+ textAlign: TextAlign.center,
+ ),
+ ),
+ ],
+ ),
);
}
}
diff --git a/client/lib/widgets/about_us_widget.dart b/client/lib/widgets/about_us_widget.dart
index 74a8a37a..6b2bf56c 100644
--- a/client/lib/widgets/about_us_widget.dart
+++ b/client/lib/widgets/about_us_widget.dart
@@ -53,7 +53,7 @@ class AboutUsWidget extends StatelessWidget {
],
),
),
- Text("Version 0.0.4",
+ Text("Version 1.0.0",
style: GoogleFonts.ubuntu(
fontSize: 14,
fontWeight: FontWeight.w400,
diff --git a/client/lib/widgets/add_email_widget.dart b/client/lib/widgets/add_email_widget.dart
index aaca83fd..b553273b 100644
--- a/client/lib/widgets/add_email_widget.dart
+++ b/client/lib/widgets/add_email_widget.dart
@@ -27,15 +27,17 @@ class _AddEmailModalState extends State {
children: [
ElevatedButton(
onPressed: () async {
- if (await serviceProvider.addEmail(
- eventProvider: eventProvider)) {
+ final addResult = await serviceProvider.addEmail(
+ eventProvider: eventProvider
+ );
+ if (addResult != null && addResult) {
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Email was added'),
),
);
- } else {
+ } else if(addResult != null && !addResult) {
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
@@ -43,6 +45,15 @@ class _AddEmailModalState extends State {
),
);
}
+ else
+ {
+ Navigator.pop(context);
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(
+ content: Text('Not added - User email already added'),
+ ),
+ );
+ }
},
child: const SizedBox(
height: 30,
diff --git a/client/lib/widgets/event_editing_widget.dart b/client/lib/widgets/event_editing_widget.dart
index 09240425..4367a481 100644
--- a/client/lib/widgets/event_editing_widget.dart
+++ b/client/lib/widgets/event_editing_widget.dart
@@ -582,7 +582,7 @@ class EventEditingState extends State {
final date = await showDatePicker(
context: context,
initialDate: initialDate,
- firstDate: DateTime(initialDate.year - 5),
+ firstDate: DateTime.now(),
lastDate: DateTime(initialDate.year + 10),
);
diff --git a/client/lib/widgets/tasks_widget.dart b/client/lib/widgets/tasks_widget.dart
index 26f23e16..d4b057e3 100644
--- a/client/lib/widgets/tasks_widget.dart
+++ b/client/lib/widgets/tasks_widget.dart
@@ -63,6 +63,7 @@ class TasksWidgetState extends State {
'assets/animations/empty.json',
height: 200,
width: 300,
+ repeat: false,
),
),
],
diff --git a/client/pubspec.lock b/client/pubspec.lock
index c429c7e5..2643bd8f 100644
--- a/client/pubspec.lock
+++ b/client/pubspec.lock
@@ -81,46 +81,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.4.1"
- build_config:
- dependency: transitive
- description:
- name: build_config
- sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
- url: "https://pub.dev"
- source: hosted
- version: "1.1.1"
- build_daemon:
- dependency: transitive
- description:
- name: build_daemon
- sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65"
- url: "https://pub.dev"
- source: hosted
- version: "4.0.0"
- build_resolvers:
- dependency: transitive
- description:
- name: build_resolvers
- sha256: "6c4dd11d05d056e76320b828a1db0fc01ccd376922526f8e9d6c796a5adbac20"
- url: "https://pub.dev"
- source: hosted
- version: "2.2.1"
- build_runner:
- dependency: "direct dev"
- description:
- name: build_runner
- sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b"
- url: "https://pub.dev"
- source: hosted
- version: "2.4.6"
- build_runner_core:
- dependency: transitive
- description:
- name: build_runner_core
- sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41"
- url: "https://pub.dev"
- source: hosted
- version: "7.2.10"
built_collection:
dependency: transitive
description:
@@ -133,10 +93,10 @@ packages:
dependency: transitive
description:
name: built_value
- sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166"
+ sha256: a8de5955205b4d1dbbbc267daddf2178bd737e4bab8987c04a500478c9651e74
url: "https://pub.dev"
source: hosted
- version: "8.6.1"
+ version: "8.6.3"
characters:
dependency: transitive
description:
@@ -153,6 +113,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.3"
+ cli_util:
+ dependency: transitive
+ description:
+ name: cli_util
+ sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.4.0"
clock:
dependency: transitive
description:
@@ -165,10 +133,10 @@ packages:
dependency: transitive
description:
name: code_builder
- sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189"
+ sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677"
url: "https://pub.dev"
source: hosted
- version: "4.5.0"
+ version: "4.7.0"
collection:
dependency: transitive
description:
@@ -355,14 +323,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.7.2+3"
- flutter_lints:
- dependency: "direct dev"
+ flutter_launcher_icons:
+ dependency: "direct main"
description:
- name: flutter_lints
- sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c
+ name: flutter_launcher_icons
+ sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea"
url: "https://pub.dev"
source: hosted
- version: "2.0.1"
+ version: "0.13.1"
flutter_pdfview:
dependency: transitive
description:
@@ -413,14 +381,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
- frontend_server_client:
- dependency: transitive
- description:
- name: frontend_server_client
- sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
- url: "https://pub.dev"
- source: hosted
- version: "3.2.0"
fuchsia_remote_debug_protocol:
dependency: transitive
description: flutter
@@ -578,14 +538,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.4.1"
- graphs:
- dependency: transitive
- description:
- name: graphs
- sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19
- url: "https://pub.dev"
- source: hosted
- version: "2.3.1"
http:
dependency: "direct main"
description:
@@ -594,14 +546,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.13.6"
- http_multi_server:
- dependency: transitive
- description:
- name: http_multi_server
- sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
- url: "https://pub.dev"
- source: hosted
- version: "3.2.1"
http_parser:
dependency: transitive
description:
@@ -618,6 +562,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.0"
+ image:
+ dependency: transitive
+ description:
+ name: image
+ sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.17"
infinite_listview:
dependency: transitive
description:
@@ -639,14 +591,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.18.1"
- io:
- dependency: transitive
- description:
- name: io
- sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
- url: "https://pub.dev"
- source: hosted
- version: "1.0.4"
js:
dependency: transitive
description:
@@ -679,14 +623,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
- lints:
- dependency: transitive
- description:
- name: lints
- sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
- url: "https://pub.dev"
- source: hosted
- version: "2.1.1"
logging:
dependency: transitive
description:
@@ -727,16 +663,8 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.9.1"
- mime:
- dependency: transitive
- description:
- name: mime
- sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
- url: "https://pub.dev"
- source: hosted
- version: "1.0.4"
mockito:
- dependency: "direct dev"
+ dependency: "direct main"
description:
name: mockito
sha256: "7d5b53bcd556c1bc7ffbe4e4d5a19c3e112b7e925e9e172dd7c6ad0630812616"
@@ -903,14 +831,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.7.3"
- pool:
- dependency: transitive
- description:
- name: pool
- sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
- url: "https://pub.dev"
- source: hosted
- version: "1.5.1"
process:
dependency: transitive
description:
@@ -959,14 +879,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.0"
- pubspec_parse:
- dependency: transitive
- description:
- name: pubspec_parse
- sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367
- url: "https://pub.dev"
- source: hosted
- version: "1.2.3"
quiver:
dependency: transitive
description:
@@ -983,22 +895,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.27.7"
- shelf:
- dependency: transitive
- description:
- name: shelf
- sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
- url: "https://pub.dev"
- source: hosted
- version: "1.4.1"
- shelf_web_socket:
- dependency: transitive
- description:
- name: shelf_web_socket
- sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
- url: "https://pub.dev"
- source: hosted
- version: "1.0.4"
sky_engine:
dependency: transitive
description: flutter
@@ -1052,14 +948,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.1"
- stream_transform:
- dependency: transitive
- description:
- name: stream_transform
- sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
- url: "https://pub.dev"
- source: hosted
- version: "2.1.0"
string_scanner:
dependency: transitive
description:
@@ -1148,14 +1036,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.9.2"
- timing:
- dependency: transitive
- description:
- name: timing
- sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
- url: "https://pub.dev"
- source: hosted
- version: "1.0.1"
typed_data:
dependency: transitive
description:
@@ -1332,14 +1212,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.1.4-beta"
- web_socket_channel:
- dependency: transitive
- description:
- name: web_socket_channel
- sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
- url: "https://pub.dev"
- source: hosted
- version: "2.4.0"
webdriver:
dependency: transitive
description:
diff --git a/client/pubspec.yaml b/client/pubspec.yaml
index 401642c2..5f9c29f1 100644
--- a/client/pubspec.yaml
+++ b/client/pubspec.yaml
@@ -74,6 +74,9 @@ dependencies:
# flutter_pdfview: ^1.3.1
pdfx: ^2.4.0
flutter_cached_pdfview: ^0.4.2
+ flutter_launcher_icons: ^0.13.1
+ mockito: ^5.4.2
+
dev_dependencies:
flutter_test:
@@ -82,6 +85,15 @@ dev_dependencies:
integration_test:
sdk: flutter
+
+flutter_icons:
+ android: true
+ ios: true
+ remove_alpha_ios: true
+ image_path: "assets/icons/koja_foreground.png"
+ adaptive_icon_foreground: "assets/icons/koja_foreground.png"
+ adaptive_icon_background: "#6B1DE2"
+
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
diff --git a/src/main/kotlin/com/teamcaffeine/koja/constants/ResponseConstant.kt b/src/main/kotlin/com/teamcaffeine/koja/constants/ResponseConstant.kt
index ce4987e7..c13d1938 100644
--- a/src/main/kotlin/com/teamcaffeine/koja/constants/ResponseConstant.kt
+++ b/src/main/kotlin/com/teamcaffeine/koja/constants/ResponseConstant.kt
@@ -8,9 +8,14 @@ object ResponseConstant {
const val EVENT_CREATION_FAILED_INTERNAL_ERROR = "Internal Server Error - Event could no be created."
const val EVENT_UPDATE_FAILED_INTERNAL_ERROR = "Internal Server Error - Event could not be updated."
const val EVENT_DELETION_FAILED_INTERNAL_ERROR = "Internal Server Error - Event could not be deleted."
+ const val SET_USER_CALENDAR_FAILED_INTERNAL_ERROR = "Internal Server Error - User calendar could not be set."
const val INVALID_PARAMETERS = "Provided parameters invalid."
const val GENERIC_INTERNAL_ERROR = "Internal Server Error - Something went wrong."
const val UNAUTHORIZED = "Unauthorized request."
+ const val INVALID_TOKEN = "Invalid token."
+ const val NO_FUTURE_LOCATIONS_FOUND = "No future locations found."
+ const val SET_TIME_BOUNDARY_FAILED_INTERNAL_ERROR = "Internal Server Error - Time boundary could not be set."
+ const val USER_ALREADY_EXISTS = "User already exists."
// Response messages where system succeeded
const val EVENT_CREATED = "Event successfully created."
@@ -20,4 +25,7 @@ object ResponseConstant {
const val ACCOUNT_DELETED = "Account successfully deleted."
const val HOME_LOCATION_SET = "Home location successfully set."
const val WORK_LOCATION_SET = "Work location successfully set."
+ const val USER_CALENDAR_SET = "User calendar successfully set."
+ const val SUCCESSFULLY_ADDED_TIME_BOUNDARY = "Successfully added time boundary."
+ const val SUCCESSFULLY_REMOVED_TIME_BOUNDARY = "Successfully removed time boundary."
}
diff --git a/src/main/kotlin/com/teamcaffeine/koja/controller/AIDataController.kt b/src/main/kotlin/com/teamcaffeine/koja/controller/AIDataController.kt
index cdf28a76..5ca1aa8e 100644
--- a/src/main/kotlin/com/teamcaffeine/koja/controller/AIDataController.kt
+++ b/src/main/kotlin/com/teamcaffeine/koja/controller/AIDataController.kt
@@ -12,6 +12,7 @@ import com.teamcaffeine.koja.dto.AIRequestBodyDTO
import com.teamcaffeine.koja.service.AIUserDataService
import com.teamcaffeine.koja.service.CryptoService
import com.teamcaffeine.koja.service.UserCalendarService
+import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestHeader
@@ -27,42 +28,54 @@ class AIDataController(private val aiUserDataService: AIUserDataService, private
@GetMapping("/get-emails")
fun getUserEmail(@RequestHeader(HeaderConstant.AUTHORISATION) token: String?): ResponseEntity {
- return if (token == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- val returnableMap = mapOf(
- "502" to "u19012366@tuks.co.za",
- "552" to "u21566382@tuks.co.za",
- "553" to "lesibasetsiba02@gmail.com",
- "602" to "u20505656@tuks.co.za",
- "603" to "uunarineleo@gmail.com",
- "652" to "u21609633@tuks.co.za",
- )
- val gson = Gson()
- val jsonObject = gson.toJson(returnableMap)
- ResponseEntity.ok(jsonObject)
+ return when {
+ token == null -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ val returnableMap = mapOf(
+ "502" to "u19012366@tuks.co.za",
+ "552" to "u21566382@tuks.co.za",
+ "553" to "lesibasetsiba02@gmail.com",
+ "602" to "u20505656@tuks.co.za",
+ "603" to "uunarineleo@gmail.com",
+ "652" to "u21609633@tuks.co.za",
+ )
+ val gson = Gson()
+ val jsonObject = gson.toJson(returnableMap)
+ ResponseEntity.ok(jsonObject)
+ }
}
}
@GetMapping("/get-user-events")
fun getUsersSuggestions(@RequestHeader(HeaderConstant.AUTHORISATION) token: String?, @RequestParam("userID") userID: String?): ResponseEntity {
- return if (token == null || userID == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- val gsonBuilder = GsonBuilder()
- gsonBuilder.registerTypeAdapter(
- OffsetDateTime::class.java,
- OffsetDateTimeAdapter(),
- )
- gsonBuilder.registerTypeAdapter(OffsetDateTime::class.java, OffsetDateTimeAdapter())
- val gson: Gson = gsonBuilder.setPrettyPrinting().create()
- var userIDRequest = userID
- if (userIDRequest.toIntOrNull() == null) {
- userIDRequest = TokenManagerController.getUserJWTTokenData(token).userID.toString()
+ return when {
+ token == null || userID == null -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ val gsonBuilder = GsonBuilder()
+ gsonBuilder.registerTypeAdapter(
+ OffsetDateTime::class.java,
+ OffsetDateTimeAdapter(),
+ )
+ gsonBuilder.registerTypeAdapter(OffsetDateTime::class.java, OffsetDateTimeAdapter())
+ val gson: Gson = gsonBuilder.setPrettyPrinting().create()
+ var userIDRequest = userID
+ if (userIDRequest.toIntOrNull() == null) {
+ userIDRequest = TokenManagerController.getUserJWTTokenData(token).userID.toString()
+ }
+ val userEvents = userCalendarService.getUserSuggestions(userIDRequest)
+ val jsonObject = gson.toJson(userEvents)
+ ResponseEntity.ok(jsonObject)
}
- val userEvents = userCalendarService.getUserSuggestions(userIDRequest)
- val jsonObject = gson.toJson(userEvents)
- ResponseEntity.ok(jsonObject)
}
}
diff --git a/src/main/kotlin/com/teamcaffeine/koja/controller/CalendarController.kt b/src/main/kotlin/com/teamcaffeine/koja/controller/CalendarController.kt
index fe2477d5..54ed9a31 100644
--- a/src/main/kotlin/com/teamcaffeine/koja/controller/CalendarController.kt
+++ b/src/main/kotlin/com/teamcaffeine/koja/controller/CalendarController.kt
@@ -25,28 +25,40 @@ class CalendarController(private val userCalendar: UserCalendarService) {
@RequestHeader(HeaderConstant.AUTHORISATION) token: String?,
@RequestBody event: UserEventDTO?,
): ResponseEntity {
- return if (token == null || event == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- try {
- userCalendar.createEvent(token, event)
- } catch (e: Exception) {
- if (e.message.equals(ExceptionMessageConstant.UNABLE_TO_FIT_EVENT)) {
- ResponseEntity.badRequest()
- .body(ResponseConstant.EVENT_CREATION_FAILED_COULD_NOT_FIT)
+ return when {
+ token == null || event == null -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ try {
+ userCalendar.createEvent(token, event)
+ } catch (e: Exception) {
+ if (e.message.equals(ExceptionMessageConstant.UNABLE_TO_FIT_EVENT)) {
+ ResponseEntity.badRequest()
+ .body(ResponseConstant.EVENT_CREATION_FAILED_COULD_NOT_FIT)
+ }
+ return ResponseEntity.internalServerError().body(e.message)
}
- return ResponseEntity.internalServerError().body(e.message)
+ ResponseEntity.ok(ResponseConstant.EVENT_CREATED)
}
- ResponseEntity.ok(ResponseConstant.EVENT_CREATED)
}
}
@GetMapping("/userEvents")
fun getAllUserEvents(@RequestHeader(HeaderConstant.AUTHORISATION) token: String?): ResponseEntity {
- return if (token == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- ResponseEntity.ok(userCalendar.getAllUserEvents(token))
+ return when {
+ token == null -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ ResponseEntity.ok(userCalendar.getAllUserEvents(token))
+ }
}
}
@@ -55,17 +67,23 @@ class CalendarController(private val userCalendar: UserCalendarService) {
@RequestHeader(HeaderConstant.AUTHORISATION) token: String?,
@RequestBody updatedEvent: UserEventDTO?,
): ResponseEntity {
- return if (token == null || updatedEvent == null) {
- return ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- try {
- deleteEvent(token, updatedEvent)
- addEvent(token, updatedEvent)
-// userCalendar.updateEvent(token, updatedEvent)
- } catch (e: Exception) {
- ResponseEntity.badRequest().body(ResponseConstant.EVENT_UPDATE_FAILED_INTERNAL_ERROR)
- }
- ResponseEntity.ok(ResponseConstant.EVENT_UPDATED)
+ return when {
+ token == null || updatedEvent == null -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ try {
+ deleteEvent(token, updatedEvent)
+ addEvent(token, updatedEvent)
+// userCalendar.updateEvent(token, updatedEvent)
+ } catch (e: Exception) {
+ ResponseEntity.badRequest().body(ResponseConstant.EVENT_UPDATE_FAILED_INTERNAL_ERROR)
+ }
+ ResponseEntity.ok(ResponseConstant.EVENT_UPDATED)
+ }
}
}
@@ -74,17 +92,22 @@ class CalendarController(private val userCalendar: UserCalendarService) {
@RequestHeader(HeaderConstant.AUTHORISATION) token: String?,
@RequestBody event: UserEventDTO?,
): ResponseEntity {
- if (event == null || token == null) {
- return ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- }
-
- try {
- userCalendar.deleteEvent(token, event.getId())
- } catch (e: Exception) {
- return ResponseEntity.badRequest().body(ResponseConstant.EVENT_DELETION_FAILED_INTERNAL_ERROR)
+ return when {
+ token == null || event == null -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ try {
+ userCalendar.deleteEvent(token, event.getId())
+ } catch (e: Exception) {
+ ResponseEntity.badRequest().body(ResponseConstant.EVENT_DELETION_FAILED_INTERNAL_ERROR)
+ }
+ ResponseEntity.ok(ResponseConstant.EVENT_DELETED)
+ }
}
-
- return ResponseEntity.ok(ResponseConstant.EVENT_DELETED)
}
@PostMapping("/rescheduleEvent")
@@ -92,25 +115,32 @@ class CalendarController(private val userCalendar: UserCalendarService) {
@RequestHeader(HeaderConstant.AUTHORISATION) token: String?,
@RequestBody event: UserEventDTO?,
): ResponseEntity {
- if (event == null || token == null) {
- return ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- }
- try {
- // val timeZoneId = ZoneId.of(TimezoneUtility(userRepository, googleCalendarAdapterService).getTimeOfTimeZone(token))
- val timeZoneId = ZoneId.of("Africa/Johannesburg")
- val currentTime = OffsetDateTime.now(timeZoneId)
- userCalendar.deleteEvent(token, event.getId())
- event.setStartTime(currentTime)
- event.setEndTime(currentTime.plusSeconds(event.getDurationInSeconds()))
- val events = userCalendar.getAllUserEvents(token)
- if (checkAvailability(events)) {
- userCalendar.createEvent(token, event)
- return ResponseEntity.ok(ResponseConstant.EVENT_UPDATED)
- }
- } catch (e: Exception) {
- return ResponseEntity.badRequest().body(e.stackTraceToString())
+ return when {
+ token == null || event == null -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ try {
+ // val timeZoneId = ZoneId.of(TimezoneUtility(userRepository, googleCalendarAdapterService).getTimeOfTimeZone(token))
+ val timeZoneId = ZoneId.of("Africa/Johannesburg")
+ val currentTime = OffsetDateTime.now(timeZoneId)
+ userCalendar.deleteEvent(token, event.getId())
+ event.setStartTime(currentTime)
+ event.setEndTime(currentTime.plusSeconds(event.getDurationInSeconds()))
+ val events = userCalendar.getAllUserEvents(token)
+ if (checkAvailability(events)) {
+ userCalendar.createEvent(token, event)
+ return ResponseEntity.ok(ResponseConstant.EVENT_UPDATED)
+ }
+ } catch (e: Exception) {
+ ResponseEntity.badRequest().body(ResponseConstant.EVENT_UPDATE_FAILED_INTERNAL_ERROR)
+ }
+ ResponseEntity.ok(ResponseConstant.EVENT_UPDATED)
+ }
}
- return ResponseEntity.badRequest().body(ResponseConstant.EVENT_UPDATE_FAILED_INTERNAL_ERROR)
}
@PostMapping("/rescheduleTimeSlot")
@@ -118,24 +148,31 @@ class CalendarController(private val userCalendar: UserCalendarService) {
@RequestHeader(HeaderConstant.AUTHORISATION) token: String?,
@RequestBody event: UserEventDTO?,
): ResponseEntity {
- if (event == null || token == null) {
- return ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- }
- try {
- // val timeZoneId = ZoneId.of(TimezoneUtility(userRepository, googleCalendarAdapterService).getTimeOfTimeZone(token))
- val timeZoneId = ZoneId.of("Africa/Johannesburg")
- val currentTime = OffsetDateTime.now(timeZoneId)
- userCalendar.deleteEvent(token, event.getId())
- val events = userCalendar.getAllUserEvents(token)
- val timeslot = userCalendar.findEarliestTimeSlot(events, event)
- event.setStartTime(timeslot.first)
- event.setEndTime(timeslot.second)
- userCalendar.createEvent(token, event)
- return ResponseEntity.ok(ResponseConstant.EVENT_UPDATED)
- } catch (e: Exception) {
- return ResponseEntity.badRequest().body(e.stackTraceToString())
+ return when {
+ event == null || token == null -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ try {
+ // val timeZoneId = ZoneId.of(TimezoneUtility(userRepository, googleCalendarAdapterService).getTimeOfTimeZone(token))
+ val timeZoneId = ZoneId.of("Africa/Johannesburg")
+ val currentTime = OffsetDateTime.now(timeZoneId)
+ userCalendar.deleteEvent(token, event.getId())
+ val events = userCalendar.getAllUserEvents(token)
+ val timeslot = userCalendar.findEarliestTimeSlot(events, event)
+ event.setStartTime(timeslot.first)
+ event.setEndTime(timeslot.second)
+ userCalendar.createEvent(token, event)
+ ResponseEntity.ok(ResponseConstant.EVENT_UPDATED)
+ } catch (e: Exception) {
+ ResponseEntity.badRequest().body(ResponseConstant.EVENT_UPDATE_FAILED_INTERNAL_ERROR)
+ }
+ ResponseEntity.ok(ResponseConstant.EVENT_UPDATED)
+ }
}
- return ResponseEntity.badRequest().body(ResponseConstant.EVENT_UPDATE_FAILED_INTERNAL_ERROR)
}
fun checkAvailability(events: List): Boolean {
@@ -150,26 +187,38 @@ class CalendarController(private val userCalendar: UserCalendarService) {
@PostMapping("/setSuggestedCalendar")
fun setSuggestedCalendar(
@RequestHeader(HeaderConstant.AUTHORISATION) token: String?,
- @RequestBody eventList: List,
+ @RequestBody eventList: List?,
): ResponseEntity {
- if (eventList == null || token == null) {
- return ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- try {
- userCalendar.createNewCalendar(token, eventList)
- } catch (e: Exception) {
- return ResponseEntity.badRequest().body(e.printStackTrace())
- }
- return ResponseEntity.ok("New calendar successfully created.")
+ return when {
+ eventList == null || token == null -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ try {
+ userCalendar.createNewCalendar(token, eventList)
+ } catch (e: Exception) {
+ return ResponseEntity.badRequest().body(ResponseConstant.SET_USER_CALENDAR_FAILED_INTERNAL_ERROR)
+ }
+ ResponseEntity.ok(ResponseConstant.USER_CALENDAR_SET)
+ }
}
}
@GetMapping("/userEventsKojaSuggestions")
fun getAllUserEventsKojaSuggestions(@RequestHeader(HeaderConstant.AUTHORISATION) token: String?): ResponseEntity {
- return if (token == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- ResponseEntity.ok(userCalendar.getAllUserEventsKojaSuggestions(token))
+ return when {
+ token == null -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ ResponseEntity.ok(userCalendar.getAllUserEventsKojaSuggestions(token))
+ }
}
}
}
diff --git a/src/main/kotlin/com/teamcaffeine/koja/controller/LocationController.kt b/src/main/kotlin/com/teamcaffeine/koja/controller/LocationController.kt
index a147afce..d9f2d570 100644
--- a/src/main/kotlin/com/teamcaffeine/koja/controller/LocationController.kt
+++ b/src/main/kotlin/com/teamcaffeine/koja/controller/LocationController.kt
@@ -43,33 +43,45 @@ LocationController(private val locationService: LocationService) {
@PostMapping("/HomeLocationUpdater")
fun updateUserHomeLocation(@RequestHeader(HeaderConstant.AUTHORISATION) token: String?, @RequestParam("placeId") placeId: String?): ResponseEntity {
- return if (token == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- try {
- locationService.setHomeLocation(token, placeId)
- } catch (e: IllegalArgumentException) {
- ResponseEntity.badRequest().body(ResponseConstant.INVALID_PARAMETERS)
- } catch (e: Exception) {
- ResponseEntity.badRequest().body(ResponseConstant.GENERIC_INTERNAL_ERROR)
+ return when {
+ token == null || placeId == null -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ try {
+ locationService.setHomeLocation(token, placeId)
+ } catch (e: IllegalArgumentException) {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_PARAMETERS)
+ } catch (e: Exception) {
+ ResponseEntity.badRequest().body(ResponseConstant.GENERIC_INTERNAL_ERROR)
+ }
+ ResponseEntity.ok(ResponseConstant.HOME_LOCATION_SET)
}
- ResponseEntity.ok(ResponseConstant.HOME_LOCATION_SET)
}
}
@PostMapping("/WorkLocationUpdater")
fun updateUserWorkLocation(@RequestHeader(HeaderConstant.AUTHORISATION) token: String?, @RequestParam("placeId") placeId: String?): ResponseEntity {
- return if (token == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- try {
- locationService.setWorkLocation(token, placeId)
- } catch (e: IllegalArgumentException) {
- ResponseEntity.badRequest().body(ResponseConstant.INVALID_PARAMETERS)
- } catch (e: Exception) {
- ResponseEntity.badRequest().body(ResponseConstant.GENERIC_INTERNAL_ERROR)
+ return when {
+ token == null || placeId == null -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ try {
+ locationService.setWorkLocation(token, placeId)
+ } catch (e: IllegalArgumentException) {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_PARAMETERS)
+ } catch (e: Exception) {
+ ResponseEntity.badRequest().body(ResponseConstant.GENERIC_INTERNAL_ERROR)
+ }
+ ResponseEntity.ok(ResponseConstant.WORK_LOCATION_SET)
}
- ResponseEntity.ok(ResponseConstant.WORK_LOCATION_SET)
}
}
@@ -79,12 +91,24 @@ LocationController(private val locationService: LocationService) {
@RequestParam("origin") origin: String?,
@RequestParam("destination") destination: String?,
): ResponseEntity {
- if (token == null || origin == null || destination == null || origin.isEmpty() || destination.isEmpty()) {
- return ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ return when {
+ token == null || origin.isNullOrEmpty() || destination.isNullOrEmpty() -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ try {
+ val distance = getDistance(origin, destination)
+ ResponseEntity.ok(distance)
+ } catch (e: IllegalArgumentException) {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_PARAMETERS)
+ } catch (e: Exception) {
+ ResponseEntity.badRequest().body(ResponseConstant.GENERIC_INTERNAL_ERROR)
+ }
+ }
}
-
- val distance = getDistance(origin, destination)
- return ResponseEntity.ok(distance)
}
@GetMapping("/listOfLocationTravelTime")
@@ -93,17 +117,29 @@ LocationController(private val locationService: LocationService) {
@RequestParam("originLat") originLat: String?,
@RequestParam("originLng") originLng: String?,
): ResponseEntity {
- return if (token == null || originLng == null || originLat == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- val originLatDouble = originLat.toDouble()
- val originLngDouble = originLng.toDouble()
- val travelTimeList = locationService.getLocationTravelTimes(token, originLatDouble, originLngDouble)
+ return when {
+ token == null || originLat.isNullOrEmpty() || originLng.isNullOrEmpty() -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ try {
+ val originLatDouble = originLat.toDouble()
+ val originLngDouble = originLng.toDouble()
+ val travelTimeList = locationService.getLocationTravelTimes(token, originLatDouble, originLngDouble)
- if (travelTimeList.isNotEmpty()) {
- ResponseEntity.ok(travelTimeList)
- } else {
- ResponseEntity.ok("There are no future locations.")
+ if (travelTimeList.isNotEmpty()) {
+ ResponseEntity.ok(travelTimeList)
+ } else {
+ ResponseEntity.ok(ResponseConstant.NO_FUTURE_LOCATIONS_FOUND)
+ }
+ } catch (e: IllegalArgumentException) {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_PARAMETERS)
+ } catch (e: Exception) {
+ ResponseEntity.badRequest().body(ResponseConstant.GENERIC_INTERNAL_ERROR)
+ }
}
}
}
@@ -129,18 +165,24 @@ LocationController(private val locationService: LocationService) {
@RequestParam("destLat") destLat: String?,
@RequestParam("destLng") destLng: String?,
): ResponseEntity {
- return if (token == null || placeId == null || destLat == null || destLng == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- try {
- val destLatDouble = destLat.toDouble()
- val destLngDouble = destLng.toDouble()
- val result = getTravelTime(placeId, destLatDouble, destLngDouble)
- ResponseEntity.ok().body(result ?: 0L)
- } catch (e: NumberFormatException) {
- ResponseEntity.badRequest().body(ResponseConstant.INVALID_PARAMETERS)
- } catch (e: Exception) {
- ResponseEntity.badRequest().body(ResponseConstant.GENERIC_INTERNAL_ERROR)
+ return when {
+ token.isNullOrEmpty() || placeId.isNullOrEmpty() || destLat.isNullOrEmpty() || destLng.isNullOrEmpty() -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ try {
+ val destLatDouble = destLat.toDouble()
+ val destLngDouble = destLng.toDouble()
+ val result = getTravelTime(placeId, destLatDouble, destLngDouble)
+ ResponseEntity.ok().body(result ?: 0L)
+ } catch (e: NumberFormatException) {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_PARAMETERS)
+ } catch (e: Exception) {
+ ResponseEntity.badRequest().body(ResponseConstant.GENERIC_INTERNAL_ERROR)
+ }
}
}
}
@@ -162,30 +204,44 @@ LocationController(private val locationService: LocationService) {
@PostMapping("/updateLocation")
fun updateCurrentUserLocation(
@RequestHeader(HeaderConstant.AUTHORISATION) token: String?,
- @RequestParam("latitude") latitude: String,
- @RequestParam("longitude") longitude: String,
+ @RequestParam("latitude") latitude: String?,
+ @RequestParam("longitude") longitude: String?,
): ResponseEntity {
- return if (token == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- try {
- val destLatDouble = latitude.toDouble()
- val destLngDouble = longitude.toDouble()
- ResponseEntity.ok(locationService.updateUserLocation(token, destLatDouble, destLngDouble))
- } catch (e: Exception) {
- ResponseEntity.badRequest().body(ResponseConstant.INVALID_PARAMETERS)
- } catch (e: Exception) {
- ResponseEntity.badRequest().body(ResponseConstant.GENERIC_INTERNAL_ERROR)
+ return when {
+ token.isNullOrEmpty() || latitude.isNullOrEmpty() || longitude.isNullOrEmpty() -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ try {
+ val destLatDouble = latitude.toDouble()
+ val destLngDouble = longitude.toDouble()
+ ResponseEntity.ok(locationService.updateUserLocation(token, destLatDouble, destLngDouble))
+ } catch (e: Exception) {
+ ResponseEntity.badRequest().body(ResponseConstant.GENERIC_INTERNAL_ERROR)
+ }
}
}
}
@GetMapping("/savedLocations")
fun getUserSavedLocations(@RequestHeader(HeaderConstant.AUTHORISATION) token: String?): ResponseEntity {
- return if (token == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- ResponseEntity.ok(locationService.getUserSavedLocations(token))
+ return when {
+ token == null -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ try {
+ ResponseEntity.ok(locationService.getUserSavedLocations(token))
+ } catch (e: Exception) {
+ ResponseEntity.badRequest().body(ResponseConstant.GENERIC_INTERNAL_ERROR)
+ }
+ }
}
}
}
diff --git a/src/main/kotlin/com/teamcaffeine/koja/controller/TokenManagerController.kt b/src/main/kotlin/com/teamcaffeine/koja/controller/TokenManagerController.kt
index e027113a..df118211 100644
--- a/src/main/kotlin/com/teamcaffeine/koja/controller/TokenManagerController.kt
+++ b/src/main/kotlin/com/teamcaffeine/koja/controller/TokenManagerController.kt
@@ -5,6 +5,7 @@ import com.auth0.jwt.algorithms.Algorithm
import com.google.gson.Gson
import com.teamcaffeine.koja.constants.EnvironmentVariableConstant
import com.teamcaffeine.koja.constants.HeaderConstant
+import com.teamcaffeine.koja.constants.ResponseConstant
import com.teamcaffeine.koja.dto.JWTAuthDetailsDTO
import com.teamcaffeine.koja.dto.JWTAuthDetailsDTO.Companion.parseJWTFormatString
import com.teamcaffeine.koja.dto.JWTGoogleDTO
@@ -31,20 +32,26 @@ class TokenManagerController {
@PostMapping("/renew")
fun renewToken(@RequestHeader(HeaderConstant.AUTHORISATION) token: String?): Any {
- return if (token == null) {
- ResponseEntity.badRequest().body("ResponseConstant.REQUIRED_PARAMETERS_NOT_SET")
- } else {
- val jwtToken = getUserJWTTokenData(token, false)
- for (t in jwtToken.userAuthDetails) {
- t.renewToken()
+ return when {
+ token.isNullOrEmpty() -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ val jwtToken = getUserJWTTokenData(token, false)
+ for (t in jwtToken.userAuthDetails) {
+ t.renewToken()
+ }
+ val tokenRequest = TokenRequest(
+ tokens = jwtToken.userAuthDetails,
+ authProvider = AuthProviderEnum.NONE,
+ userId = jwtToken.userID,
+ )
+ val newToken = createToken(tokenRequest)
+ ResponseEntity.ok(newToken)
}
- val tokenRequest = TokenRequest(
- tokens = jwtToken.userAuthDetails,
- authProvider = AuthProviderEnum.NONE,
- userId = jwtToken.userID,
- )
- val newToken = createToken(tokenRequest)
- ResponseEntity.ok(newToken)
}
}
@@ -60,6 +67,18 @@ class TokenManagerController {
return String(decrypted, Charsets.UTF_8)
}
+ fun isTokenValid(token: String): Boolean {
+ return try {
+ val jwtSecret: String = System.getProperty(EnvironmentVariableConstant.KOJA_JWT_SECRET)
+ val algorithm = Algorithm.HMAC512(jwtSecret)
+ val verifier = JWT.require(algorithm).build()
+ verifier.verify(token)
+ true
+ } catch (exception: Exception) {
+ false
+ }
+ }
+
fun createToken(tokenRequest: TokenRequest): String {
val soonestExpireTime = getSoonestExpiryTime(tokenRequest)
val expiryTime = soonestExpireTime - (oneMinuteInSeconds * 5)
diff --git a/src/main/kotlin/com/teamcaffeine/koja/controller/UserAccountManagerController.kt b/src/main/kotlin/com/teamcaffeine/koja/controller/UserAccountManagerController.kt
index eef22553..f50117c1 100644
--- a/src/main/kotlin/com/teamcaffeine/koja/controller/UserAccountManagerController.kt
+++ b/src/main/kotlin/com/teamcaffeine/koja/controller/UserAccountManagerController.kt
@@ -25,10 +25,21 @@ class UserAccountManagerController(
@GetMapping("auth/add-email/google")
fun authenticateAnotherGoogleEmail(request: HttpServletRequest, @RequestParam token: String?): Any {
- return if (token == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- return googleCalendarAdapter.setupConnection(request, CallbackConfigEnum.ADD_EMAIL, addAdditionalAccount = true, token = token)
+ return when {
+ token.isNullOrEmpty() -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ googleCalendarAdapter.setupConnection(
+ request,
+ CallbackConfigEnum.ADD_EMAIL,
+ addAdditionalAccount = true,
+ token = token,
+ )
+ }
}
}
@@ -37,11 +48,21 @@ class UserAccountManagerController(
@RequestParam("code") authCode: String?,
@RequestParam state: String?,
): Any {
- return if (state == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- val jwt = googleCalendarAdapter.addAnotherEmailOauth2Callback(authCode, state, false)
- return RedirectView("koja-login-callback://callback?token=$jwt")
+ return when {
+ authCode.isNullOrEmpty() || state.isNullOrEmpty() -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ else -> {
+ try {
+ val jwt = googleCalendarAdapter.addAnotherEmailOauth2Callback(authCode, state, true)
+ return RedirectView("koja-login-callback://callback?token=$jwt")
+ } catch (e: Exception) {
+ if (e.message.equals(ResponseConstant.USER_ALREADY_EXISTS)) {
+ return RedirectView("koja-login-callback://callback?error=${ResponseConstant.USER_ALREADY_EXISTS}")
+ }
+ ResponseEntity.internalServerError().body(ResponseConstant.GENERIC_INTERNAL_ERROR)
+ }
+ }
}
}
@@ -50,10 +71,16 @@ class UserAccountManagerController(
@RequestHeader(HeaderConstant.AUTHORISATION) token: String?,
@RequestBody email: String?,
): Any {
- return if (token == null || email == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- return userAccountManagerService.deleteGoogleAccount(token, email)
+ return when {
+ token.isNullOrEmpty() || email.isNullOrEmpty() -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ userAccountManagerService.deleteGoogleAccount(token, email)
+ }
}
}
}
diff --git a/src/main/kotlin/com/teamcaffeine/koja/controller/UserController.kt b/src/main/kotlin/com/teamcaffeine/koja/controller/UserController.kt
index 37b586cb..9b71c718 100644
--- a/src/main/kotlin/com/teamcaffeine/koja/controller/UserController.kt
+++ b/src/main/kotlin/com/teamcaffeine/koja/controller/UserController.kt
@@ -29,39 +29,51 @@ class UserController(
private val timeBoundaryRepository: TimeBoundaryRepository,
) {
@GetMapping("linked-emails")
- fun getUserEmails(@RequestHeader(HeaderConstant.AUTHORISATION) token: String?): ResponseEntity> {
- return if (token == null) {
- ResponseEntity.badRequest().body(listOf(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET))
- } else {
- val jwtTokenData = getUserJWTTokenData(token)
- val userAccounts = userAccountRepository.findByUserID(jwtTokenData.userID)
+ fun getUserEmails(@RequestHeader(HeaderConstant.AUTHORISATION) token: String?): ResponseEntity {
+ return when {
+ token.isNullOrEmpty() -> {
+ ResponseEntity.badRequest().body(listOf(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET))
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ val jwtTokenData = getUserJWTTokenData(token)
+ val userAccounts = userAccountRepository.findByUserID(jwtTokenData.userID)
- ResponseEntity.ok(userAccounts.map { it.email })
+ ResponseEntity.ok(userAccounts.map { it.email })
+ }
}
}
@PostMapping("delete-account")
fun deleteUserAccount(@RequestHeader(HeaderConstant.AUTHORISATION) token: String?): ResponseEntity {
- return if (token == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- val jwtTokenData = getUserJWTTokenData(token)
- val userAccounts = userAccountRepository.findByUserID(jwtTokenData.userID)
- val users = mutableListOf()
- val timeBoundaries = mutableListOf()
+ return when {
+ token.isNullOrEmpty() -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ val jwtTokenData = getUserJWTTokenData(token)
+ val userAccounts = userAccountRepository.findByUserID(jwtTokenData.userID)
+ val users = mutableListOf()
+ val timeBoundaries = mutableListOf()
- userAccounts.forEach {
- it.user?.let { user ->
- users.add(user)
- timeBoundaries.addAll(user.getUserTimeBoundaries())
+ userAccounts.forEach {
+ it.user?.let { user ->
+ users.add(user)
+ timeBoundaries.addAll(user.getUserTimeBoundaries())
+ }
+ userAccountRepository.delete(it)
}
- userAccountRepository.delete(it)
- }
- timeBoundaries.forEach { timeBoundaryRepository.delete(it) }
- users.forEach { userRepository.delete(it) }
+ timeBoundaries.forEach { timeBoundaryRepository.delete(it) }
+ users.forEach { userRepository.delete(it) }
- ResponseEntity.ok(ResponseConstant.ACCOUNT_DELETED)
+ ResponseEntity.ok(ResponseConstant.ACCOUNT_DELETED)
+ }
}
}
@@ -73,54 +85,79 @@ class UserController(
@RequestParam("endTime")endTime: String?,
@RequestParam("type")type: String = "allowed",
): ResponseEntity {
- return if (token == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- val boundary = TimeBoundary(name, startTime, endTime, TimeBoundaryType.ALLOWED)
- if (userCalendarService.addTimeBoundary(token, boundary)) {
- return ResponseEntity.ok("Time boundary successfully added")
- } else {
- return ResponseEntity.badRequest().body("Something went wrong")
+ return when {
+ token.isNullOrEmpty() -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ val boundary = TimeBoundary(name, startTime, endTime, getTimeBoundaryType(type))
+ if (userCalendarService.addTimeBoundary(token, boundary)) {
+ ResponseEntity.ok(ResponseConstant.SUCCESSFULLY_ADDED_TIME_BOUNDARY)
+ } else {
+ ResponseEntity.badRequest().body(ResponseConstant.SET_TIME_BOUNDARY_FAILED_INTERNAL_ERROR)
+ }
}
}
}
@PostMapping("/removeTimeBoundary")
fun removeTimeBoundary(@RequestHeader(HeaderConstant.AUTHORISATION) token: String?, @RequestParam("name") name: String?): ResponseEntity {
- return if (token == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- if (userCalendarService.removeTimeBoundary(token, name)) {
- return ResponseEntity.ok("Time boundary successfully removed")
- } else {
- return ResponseEntity.badRequest().body("Something went wrong")
+ return when {
+ token.isNullOrEmpty() -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ if (userCalendarService.removeTimeBoundary(token, name)) {
+ ResponseEntity.ok(ResponseConstant.SUCCESSFULLY_REMOVED_TIME_BOUNDARY)
+ } else {
+ ResponseEntity.badRequest().body(ResponseConstant.SET_TIME_BOUNDARY_FAILED_INTERNAL_ERROR)
+ }
}
}
}
@GetMapping("/getAllTimeBoundary")
fun getTimeBoundaries(@RequestHeader(HeaderConstant.AUTHORISATION) token: String?): ResponseEntity {
- return if (token == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- try {
- val gson = GsonBuilder().setLenient().excludeFieldsWithoutExposeAnnotation().create()
- return ResponseEntity.ok(gson.toJson(userCalendarService.getUserTimeBoundaries(token)))
- } catch (e: Exception) {
- return ResponseEntity.badRequest().body("Something went wrong.")
+ return when {
+ token.isNullOrEmpty() -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ try {
+ val gson = GsonBuilder().setLenient().excludeFieldsWithoutExposeAnnotation().create()
+ ResponseEntity.ok(gson.toJson(userCalendarService.getUserTimeBoundaries(token)))
+ } catch (e: Exception) {
+ ResponseEntity.badRequest().body(ResponseConstant.GENERIC_INTERNAL_ERROR)
+ }
}
}
}
@GetMapping("/getTimeBoundaryAndLocation")
fun getTimeBoundaryAndLocation(@RequestHeader(HeaderConstant.AUTHORISATION) token: String?, @RequestParam("location") location: String): ResponseEntity {
- return if (token == null) {
- ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
- } else {
- val gson = Gson()
- return ResponseEntity.ok(gson.toJson(userCalendarService.getUserTimeBoundaryAndLocation(token, location)))
+ return when {
+ token.isNullOrEmpty() -> {
+ ResponseEntity.badRequest().body(ResponseConstant.REQUIRED_PARAMETERS_NOT_SET)
+ }
+ !TokenManagerController.isTokenValid(token) -> {
+ ResponseEntity.badRequest().body(ResponseConstant.INVALID_TOKEN)
+ }
+ else -> {
+ val gson = Gson()
+ ResponseEntity.ok(gson.toJson(userCalendarService.getUserTimeBoundaryAndLocation(token, location)))
+ }
}
}
+
private fun getTimeBoundaryType(timeBoundaryType: String): TimeBoundaryType {
return when (timeBoundaryType) {
"allowed" -> TimeBoundaryType.ALLOWED
diff --git a/src/main/kotlin/com/teamcaffeine/koja/service/GoogleCalendarAdapterService.kt b/src/main/kotlin/com/teamcaffeine/koja/service/GoogleCalendarAdapterService.kt
index 91314cfc..954a8d2c 100644
--- a/src/main/kotlin/com/teamcaffeine/koja/service/GoogleCalendarAdapterService.kt
+++ b/src/main/kotlin/com/teamcaffeine/koja/service/GoogleCalendarAdapterService.kt
@@ -23,6 +23,7 @@ import com.google.maps.GeoApiContext
import com.teamcaffeine.koja.constants.EnvironmentVariableConstant
import com.teamcaffeine.koja.constants.ExceptionMessageConstant
import com.teamcaffeine.koja.constants.Frequency
+import com.teamcaffeine.koja.constants.ResponseConstant
import com.teamcaffeine.koja.controller.TokenManagerController
import com.teamcaffeine.koja.controller.TokenManagerController.Companion.createToken
import com.teamcaffeine.koja.controller.TokenRequest
@@ -292,7 +293,7 @@ class GoogleCalendarAdapterService(
val jwtToken: String
if (existingUser != null) {
- throw Exception("Email already exits.")
+ throw Exception(ResponseConstant.USER_ALREADY_EXISTS)
} else {
if (token == null) {
throw Exception("Token is not set.")
diff --git a/src/test/kotlin/com/teamcaffiene/koja/controller/CalendarControllerUnitTest.kt b/src/test/kotlin/com/teamcaffiene/koja/controller/CalendarControllerUnitTest.kt
index ac3a733f..506aac67 100644
--- a/src/test/kotlin/com/teamcaffiene/koja/controller/CalendarControllerUnitTest.kt
+++ b/src/test/kotlin/com/teamcaffiene/koja/controller/CalendarControllerUnitTest.kt
@@ -3,10 +3,16 @@ package com.teamcaffiene.koja.controller
import com.google.api.client.util.DateTime
import com.google.api.services.calendar.model.Event
import com.google.api.services.calendar.model.EventDateTime
+import com.teamcaffeine.koja.constants.EnvironmentVariableConstant
import com.teamcaffeine.koja.constants.ResponseConstant
import com.teamcaffeine.koja.controller.CalendarController
+import com.teamcaffeine.koja.controller.TokenManagerController
+import com.teamcaffeine.koja.controller.TokenRequest
+import com.teamcaffeine.koja.dto.JWTGoogleDTO
import com.teamcaffeine.koja.dto.UserEventDTO
+import com.teamcaffeine.koja.enums.AuthProviderEnum
import com.teamcaffeine.koja.service.UserCalendarService
+import io.github.cdimascio.dotenv.Dotenv
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@@ -28,20 +34,57 @@ class CalendarControllerUnitTest {
@InjectMocks
private lateinit var calendarController: CalendarController
+ private lateinit var dotenv: Dotenv
+
@BeforeEach
fun setup() {
MockitoAnnotations.openMocks(this)
+ importEnvironmentVariables()
+ }
+
+ private fun importEnvironmentVariables() {
+ dotenv = Dotenv.load()
+
+ dotenv[EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_URL]?.let {
+ System.setProperty(EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_URL, it)
+ }
+ dotenv[EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_ADMIN_USERNAME]?.let {
+ System.setProperty(EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_ADMIN_USERNAME, it)
+ }
+ dotenv[EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_ADMIN_PASSWORD]?.let {
+ System.setProperty(EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_ADMIN_PASSWORD, it)
+ }
+ dotenv[EnvironmentVariableConstant.GOOGLE_CLIENT_ID]?.let {
+ System.setProperty(EnvironmentVariableConstant.GOOGLE_CLIENT_ID, it)
+ }
+ dotenv[EnvironmentVariableConstant.GOOGLE_CLIENT_SECRET]?.let {
+ System.setProperty(EnvironmentVariableConstant.GOOGLE_CLIENT_SECRET, it)
+ }
+ dotenv[EnvironmentVariableConstant.GOOGLE_MAPS_API_KEY]?.let {
+ System.setProperty(EnvironmentVariableConstant.GOOGLE_MAPS_API_KEY, it)
+ }
+ dotenv[EnvironmentVariableConstant.KOJA_JWT_SECRET]?.let {
+ System.setProperty(EnvironmentVariableConstant.KOJA_JWT_SECRET, it)
+ }
}
@Test
fun testGetAllUserEvents() {
// Mock the behavior of the userCalendarService
- val token = "testToken"
+ val mockUserID = Int.MAX_VALUE
+ val authDetails = JWTGoogleDTO("access", "refresh", 60 * 60)
+ val mockToken = TokenManagerController.createToken(
+ TokenRequest(
+ arrayListOf(authDetails),
+ AuthProviderEnum.GOOGLE,
+ mockUserID,
+ ),
+ )
val userEvents = arrayListOf()
- `when`(userCalendarService.getAllUserEvents(token)).thenReturn(userEvents)
+ `when`(userCalendarService.getAllUserEvents(mockToken)).thenReturn(userEvents)
// Invoke the getAllUserEvents method in the calendarController
- val responseEntity: ResponseEntity = calendarController.getAllUserEvents(token)
+ val responseEntity: ResponseEntity = calendarController.getAllUserEvents(mockToken)
// Verify the result
assertEquals(HttpStatus.OK, responseEntity.statusCode)
@@ -50,12 +93,20 @@ class CalendarControllerUnitTest {
@Test
fun test_empty_userEvent_list() {
- val token = "token"
+ val mockUserID = Int.MAX_VALUE
+ val authDetails = JWTGoogleDTO("access", "refresh", 60 * 60)
+ val mockToken = TokenManagerController.createToken(
+ TokenRequest(
+ arrayListOf(authDetails),
+ AuthProviderEnum.GOOGLE,
+ mockUserID,
+ ),
+ )
val userEvents = emptyList()
- `when`(userCalendarService.getAllUserEvents(token)).thenReturn(userEvents)
+ `when`(userCalendarService.getAllUserEvents(mockToken)).thenReturn(userEvents)
- val responseEntity: ResponseEntity = calendarController.getAllUserEvents(token)
+ val responseEntity: ResponseEntity = calendarController.getAllUserEvents(mockToken)
assertEquals(userEvents, responseEntity.body)
}
@@ -63,15 +114,23 @@ class CalendarControllerUnitTest {
@Test
fun `test setSuggestedCalendar with valid input`() {
// Arrange
- val token = "validToken"
+ val mockUserID = Int.MAX_VALUE
+ val authDetails = JWTGoogleDTO("access", "refresh", 60 * 60)
+ val mockToken = TokenManagerController.createToken(
+ TokenRequest(
+ arrayListOf(authDetails),
+ AuthProviderEnum.GOOGLE,
+ mockUserID,
+ ),
+ )
val eventList = arrayListOf()
// Act
- val response = calendarController.setSuggestedCalendar(token, eventList)
+ val response = calendarController.setSuggestedCalendar(mockToken, eventList)
// Assert
assert(response.statusCode == HttpStatus.OK)
- assert(response.body == "New calendar successfully created.")
+ assert(response.body == ResponseConstant.USER_CALENDAR_SET)
}
@Test
@@ -90,7 +149,15 @@ class CalendarControllerUnitTest {
@Test
fun `rescheduleEvent should update event and return OK`() {
- val token = "valid_token"
+ val mockUserID = Int.MAX_VALUE
+ val authDetails = JWTGoogleDTO("access", "refresh", 60 * 60)
+ val mockToken = TokenManagerController.createToken(
+ TokenRequest(
+ arrayListOf(authDetails),
+ AuthProviderEnum.GOOGLE,
+ mockUserID,
+ ),
+ )
val event = UserEventDTO(Event().setId("minimanimo").setStart(EventDateTime().setDate(DateTime("2022-03-15"))).setEnd(EventDateTime().setDate(DateTime("2022-03-16"))))
event.setDuration(60)
val timeZoneId = ZoneId.of("Africa/Johannesburg")
@@ -103,9 +170,9 @@ class CalendarControllerUnitTest {
val endTimeUpdated = currentTime.plusMinutes(60)
// doNothing().`when`(userCalendarService.deleteEvent(token, "", startTime, endTime))
// doNothing().`when`(userCalendarService.createEvent(token, event))
- `when`(userCalendarService.getAllUserEvents(token)).thenReturn(listOf(event))
+ `when`(userCalendarService.getAllUserEvents(mockToken)).thenReturn(listOf(event))
- val response = calendarController.rescheduleEvent(token, event)
+ val response = calendarController.rescheduleEvent(mockToken, event)
assert(response.statusCode == HttpStatus.OK)
assert(response.body == ResponseConstant.EVENT_UPDATED)
diff --git a/src/test/kotlin/com/teamcaffiene/koja/controller/UserControllerUnitTest.kt b/src/test/kotlin/com/teamcaffiene/koja/controller/UserControllerUnitTest.kt
index 19cb352b..4de55ac4 100644
--- a/src/test/kotlin/com/teamcaffiene/koja/controller/UserControllerUnitTest.kt
+++ b/src/test/kotlin/com/teamcaffiene/koja/controller/UserControllerUnitTest.kt
@@ -4,6 +4,7 @@ import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.teamcaffeine.koja.constants.EnvironmentVariableConstant
import com.teamcaffeine.koja.constants.ResponseConstant
+import com.teamcaffeine.koja.controller.TokenManagerController
import com.teamcaffeine.koja.controller.TokenManagerController.Companion.createToken
import com.teamcaffeine.koja.controller.TokenRequest
import com.teamcaffeine.koja.controller.UserController
@@ -161,21 +162,28 @@ class UserControllerUnitTest {
@Test
fun `test addTimeBoundary with valid parameters`() {
// Mock request parameters
- val token = "your_token_here"
+ val mockUserID = Int.MAX_VALUE
+ val authDetails = JWTGoogleDTO("access", "refresh", 60 * 60)
+ val mockToken = TokenManagerController.createToken(
+ TokenRequest(
+ arrayListOf(authDetails),
+ AuthProviderEnum.GOOGLE,
+ mockUserID,
+ ),
+ )
val name = "Play"
val startTime = "2023-07-30T12:00:00Z"
val endTime = "2023-07-30T14:00:00Z"
val timeBoundary = TimeBoundary(name, startTime, endTime)
// Mock the userCalendarService.addTimeBoundary method
- val expectedResult = "Time boundary successfully added"
- whenever(userCalendarService.addTimeBoundary(token, timeBoundary)).thenReturn(true)
+ whenever(userCalendarService.addTimeBoundary(mockToken, timeBoundary)).thenReturn(true)
// Call the function and capture the response
- val response = userController.addTimeBoundary(token, name, startTime, endTime)
+ val response = userController.addTimeBoundary(mockToken, name, startTime, endTime)
// Check the response status and body
assertEquals(HttpStatus.OK, response.statusCode)
- assertEquals(expectedResult, response.body)
+ assertEquals(ResponseConstant.SUCCESSFULLY_ADDED_TIME_BOUNDARY, response.body)
}
@Test
@@ -198,41 +206,57 @@ class UserControllerUnitTest {
@Test
fun `test addTimeBoundary with userCalendarService returning false`() {
// Mock request parameters
- val token = "your_token_here"
+ val mockUserID = Int.MAX_VALUE
+ val authDetails = JWTGoogleDTO("access", "refresh", 60 * 60)
+ val mockToken = TokenManagerController.createToken(
+ TokenRequest(
+ arrayListOf(authDetails),
+ AuthProviderEnum.GOOGLE,
+ mockUserID,
+ ),
+ )
val name = "Play"
val startTime = "2023-07-30T12:00:00Z"
val endTime = "2023-07-30T14:00:00Z"
val timeBoundary = TimeBoundary(name, startTime, endTime)
// Mock the userCalendarService.removeTimeBoundary method to return false
- whenever(userCalendarService.addTimeBoundary(token, timeBoundary)).thenReturn(false)
+ whenever(userCalendarService.addTimeBoundary(mockToken, timeBoundary)).thenReturn(false)
// Call the function and capture the response
- val response = userController.addTimeBoundary(token, name, startTime, endTime)
+ val response = userController.addTimeBoundary(mockToken, name, startTime, endTime)
// Check the response status and body
assertEquals(HttpStatus.BAD_REQUEST, response.statusCode)
- assertEquals("Something went wrong", response.body)
+ assertEquals(ResponseConstant.SET_TIME_BOUNDARY_FAILED_INTERNAL_ERROR, response.body)
}
@Test
fun `test removeTimeBoundary with valid parameters`() {
// Mock request parameters
- val token = "your_token_here"
+ val mockUserID = Int.MAX_VALUE
+ val authDetails = JWTGoogleDTO("access", "refresh", 60 * 60)
+ val mockToken = TokenManagerController.createToken(
+ TokenRequest(
+ arrayListOf(authDetails),
+ AuthProviderEnum.GOOGLE,
+ mockUserID,
+ ),
+ )
val name = "Boundary Name"
// Mock the userCalendarService.removeTimeBoundary method
- whenever(userCalendarService.removeTimeBoundary(eq(token), eq(name))).thenReturn(true)
+ whenever(userCalendarService.removeTimeBoundary(eq(mockToken), eq(name))).thenReturn(true)
// Call the function and capture the response
- val response = userController.removeTimeBoundary(token, name)
+ val response = userController.removeTimeBoundary(mockToken, name)
// Verify the userCalendarService.removeTimeBoundary method was called with the correct parameters
- verify(userCalendarService).removeTimeBoundary(eq(token), eq(name))
+ verify(userCalendarService).removeTimeBoundary(eq(mockToken), eq(name))
// Check the response status and body
assertEquals(HttpStatus.OK, response.statusCode)
- assertEquals("Time boundary successfully removed", response.body)
+ assertEquals(ResponseConstant.SUCCESSFULLY_REMOVED_TIME_BOUNDARY, response.body)
}
@Test
@@ -251,39 +275,55 @@ class UserControllerUnitTest {
@Test
fun `test removeTimeBoundary with userCalendarService returning false`() {
// Mock request parameters
- val token = "your_token_here"
+ val mockUserID = Int.MAX_VALUE
+ val authDetails = JWTGoogleDTO("access", "refresh", 60 * 60)
+ val mockToken = TokenManagerController.createToken(
+ TokenRequest(
+ arrayListOf(authDetails),
+ AuthProviderEnum.GOOGLE,
+ mockUserID,
+ ),
+ )
val name = "Boundary Name"
// Mock the userCalendarService.removeTimeBoundary method to return false
- whenever(userCalendarService.removeTimeBoundary(eq(token), eq(name))).thenReturn(false)
+ whenever(userCalendarService.removeTimeBoundary(eq(mockToken), eq(name))).thenReturn(false)
// Call the function and capture the response
- val response = userController.removeTimeBoundary(token, name)
+ val response = userController.removeTimeBoundary(mockToken, name)
// Verify the userCalendarService.removeTimeBoundary method was called with the correct parameters
- verify(userCalendarService).removeTimeBoundary(eq(token), eq(name))
+ verify(userCalendarService).removeTimeBoundary(eq(mockToken), eq(name))
// Check the response status and body
assertEquals(HttpStatus.BAD_REQUEST, response.statusCode)
- assertEquals("Something went wrong", response.body)
+ assertEquals(ResponseConstant.SET_TIME_BOUNDARY_FAILED_INTERNAL_ERROR, response.body)
}
@Test
fun `test getTimeBoundaries with valid token`() {
// Mock request parameters
- val token = "your_token_here"
+ val mockUserID = Int.MAX_VALUE
+ val authDetails = JWTGoogleDTO("access", "refresh", 60 * 60)
+ val mockToken = TokenManagerController.createToken(
+ TokenRequest(
+ arrayListOf(authDetails),
+ AuthProviderEnum.GOOGLE,
+ mockUserID,
+ ),
+ )
// Mock the userCalendarService.getUserTimeBoundaries method
val boundaries = mutableListOf()
val timeBoundary = TimeBoundary("Boundary1", "2023-07-30T12:00:00Z", "2023-07-30T14:00:00Z")
boundaries.add(0, timeBoundary)
- whenever(userCalendarService.getUserTimeBoundaries(eq(token))).thenReturn(boundaries)
+ whenever(userCalendarService.getUserTimeBoundaries(eq(mockToken))).thenReturn(boundaries)
// Call the function and capture the response
- val response = userController.getTimeBoundaries(token)
+ val response = userController.getTimeBoundaries(mockToken)
// Verify the userCalendarService.getUserTimeBoundaries method was called with the correct token
- verify(userCalendarService).getUserTimeBoundaries(eq(token))
+ verify(userCalendarService).getUserTimeBoundaries(eq(mockToken))
// Check the response status and body
assertEquals(HttpStatus.OK, response.statusCode)
@@ -306,32 +346,48 @@ class UserControllerUnitTest {
@Test
fun `test getTimeBoundaries with userCalendarService throwing an exception`() {
// Mock request parameters
- val token = "your_token_here"
+ val mockUserID = Int.MAX_VALUE
+ val authDetails = JWTGoogleDTO("access", "refresh", 60 * 60)
+ val mockToken = TokenManagerController.createToken(
+ TokenRequest(
+ arrayListOf(authDetails),
+ AuthProviderEnum.GOOGLE,
+ mockUserID,
+ ),
+ )
// Mock the userCalendarService.getUserTimeBoundaries method to throw an exception
- whenever(userCalendarService.getUserTimeBoundaries(eq(token))).thenThrow(RuntimeException("Error fetching boundaries."))
+ whenever(userCalendarService.getUserTimeBoundaries(eq(mockToken))).thenThrow(RuntimeException("Error fetching boundaries."))
// Call the function and capture the response
- val response = userController.getTimeBoundaries(token)
+ val response = userController.getTimeBoundaries(mockToken)
// Verify the userCalendarService.getUserTimeBoundaries method was called with the correct token
- verify(userCalendarService).getUserTimeBoundaries(eq(token))
+ verify(userCalendarService).getUserTimeBoundaries(eq(mockToken))
// Check the response status and body
assertEquals(HttpStatus.BAD_REQUEST, response.statusCode)
- assertEquals("Something went wrong.", response.body)
+ assertEquals(ResponseConstant.GENERIC_INTERNAL_ERROR, response.body)
}
@Test
fun `test getTimeBoundaryAndLocation with valid token and location`() {
// Mock request parameters
- val token = "your_token_here"
+ val mockUserID = Int.MAX_VALUE
+ val authDetails = JWTGoogleDTO("access", "refresh", 60 * 60)
+ val mockToken = TokenManagerController.createToken(
+ TokenRequest(
+ arrayListOf(authDetails),
+ AuthProviderEnum.GOOGLE,
+ mockUserID,
+ ),
+ )
val location = "London"
// Mock the userCalendarService.getUserTimeBoundaryAndLocation method
val boundary = TimeBoundary("Boundary1", "2023-07-30T12:00:00Z", "2023-07-30T14:00:00Z")
- whenever(userCalendarService.getUserTimeBoundaryAndLocation(eq(token), eq(location))).thenReturn(Pair(boundary, location))
+ whenever(userCalendarService.getUserTimeBoundaryAndLocation(eq(mockToken), eq(location))).thenReturn(Pair(boundary, location))
// Call the function and capture the response
- val response = userController.getTimeBoundaryAndLocation(token, location)
+ val response = userController.getTimeBoundaryAndLocation(mockToken, location)
// Verify the userCalendarService.getUserTimeBoundaryAndLocation method was called with the correct parameters
- verify(userCalendarService).getUserTimeBoundaryAndLocation(eq(token), eq(location))
+ verify(userCalendarService).getUserTimeBoundaryAndLocation(eq(mockToken), eq(location))
// Check the response status and body
assertEquals(HttpStatus.OK, response.statusCode)
// Convert the boundaryAndLocation to JSON using Gson and check the response body
diff --git a/src/test/kotlin/com/teamcaffiene/koja/service/UserCalendarServiceTest.kt b/src/test/kotlin/com/teamcaffiene/koja/service/UserCalendarServiceTest.kt
index 877ef612..1fa45ad4 100644
--- a/src/test/kotlin/com/teamcaffiene/koja/service/UserCalendarServiceTest.kt
+++ b/src/test/kotlin/com/teamcaffiene/koja/service/UserCalendarServiceTest.kt
@@ -14,17 +14,22 @@ import com.teamcaffeine.koja.repository.UserAccountRepository
import com.teamcaffeine.koja.repository.UserRepository
import com.teamcaffeine.koja.service.UserCalendarService
import io.github.cdimascio.dotenv.Dotenv
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.unmockkAll
+import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
+import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
import org.mockito.invocation.InvocationOnMock
import org.mockito.kotlin.any
import org.mockito.kotlin.check
-import org.mockito.kotlin.eq
import org.mockito.kotlin.spy
import org.mockito.kotlin.whenever
import java.util.Optional
@@ -43,84 +48,89 @@ class UserCalendarServiceTest {
private lateinit var userCalendarService: UserCalendarService
private lateinit var dotenv: Dotenv
- init {
- importEnvironmentVariables()
+ companion object {
+ @JvmStatic
+ @BeforeAll
+ fun setupOnce() {
+ val dotenv: Dotenv = Dotenv.load()
+ System.setProperty(
+ EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_URL,
+ dotenv[EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_URL]!!,
+ )
+ System.setProperty(
+ EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_ADMIN_USERNAME,
+ dotenv[EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_ADMIN_USERNAME]!!,
+ )
+ System.setProperty(
+ EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_ADMIN_PASSWORD,
+ dotenv[EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_ADMIN_PASSWORD]!!,
+ )
+ System.setProperty(
+ EnvironmentVariableConstant.KOJA_AWS_DYNAMODB_ACCESS_KEY_ID,
+ dotenv[EnvironmentVariableConstant.KOJA_AWS_DYNAMODB_ACCESS_KEY_ID]!!,
+ )
+ System.setProperty(
+ EnvironmentVariableConstant.KOJA_AWS_DYNAMODB_ACCESS_KEY_SECRET,
+ dotenv[EnvironmentVariableConstant.KOJA_AWS_DYNAMODB_ACCESS_KEY_SECRET]!!,
+ )
+ System.setProperty(
+ EnvironmentVariableConstant.OPENAI_API_KEY,
+ dotenv[EnvironmentVariableConstant.OPENAI_API_KEY]!!,
+ )
+ System.setProperty(
+ EnvironmentVariableConstant.SERVER_ADDRESS,
+ dotenv[EnvironmentVariableConstant.SERVER_ADDRESS]!!,
+ )
+ System.setProperty(
+ EnvironmentVariableConstant.SERVER_PORT,
+ dotenv[EnvironmentVariableConstant.SERVER_PORT] ?: "",
+ )
+ // Set Google Sign In client ID and client secret properties
+ System.setProperty(
+ EnvironmentVariableConstant.GOOGLE_CLIENT_ID,
+ dotenv[EnvironmentVariableConstant.GOOGLE_CLIENT_ID]!!,
+ )
+ System.setProperty(
+ EnvironmentVariableConstant.GOOGLE_CLIENT_SECRET,
+ dotenv[EnvironmentVariableConstant.GOOGLE_CLIENT_SECRET]!!,
+ )
+ System.setProperty(
+ EnvironmentVariableConstant.GOOGLE_MAPS_API_KEY,
+ dotenv[EnvironmentVariableConstant.GOOGLE_MAPS_API_KEY]!!,
+ )
+ // Set JWT secret key and other related properties
+ System.setProperty(
+ EnvironmentVariableConstant.KOJA_JWT_SECRET,
+ dotenv[EnvironmentVariableConstant.KOJA_JWT_SECRET]!!,
+ )
+ System.setProperty(
+ EnvironmentVariableConstant.KOJA_ID_SECRET,
+ dotenv[EnvironmentVariableConstant.KOJA_ID_SECRET]!!,
+ )
+ System.setProperty(
+ EnvironmentVariableConstant.KOJA_PRIVATE_KEY_PASS,
+ dotenv[EnvironmentVariableConstant.KOJA_PRIVATE_KEY_PASS]!!,
+ )
+ System.setProperty(
+ EnvironmentVariableConstant.KOJA_PRIVATE_KEY_SALT,
+ dotenv[EnvironmentVariableConstant.KOJA_PRIVATE_KEY_SALT]!!,
+ )
+ }
}
@BeforeEach
fun setup() {
MockitoAnnotations.openMocks(this)
- importEnvironmentVariables()
-
userCalendarService = spy(UserCalendarService(userRepository, jwtFunctionality))
- }
- private fun importEnvironmentVariables() {
- val dotenv: Dotenv = Dotenv.load()
+ val tokenManagerController = mockk()
+ every { tokenManagerController.isTokenValid(anyString()) } returns true
+ }
- System.setProperty(
- EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_URL,
- dotenv[EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_URL]!!,
- )
- System.setProperty(
- EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_ADMIN_USERNAME,
- dotenv[EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_ADMIN_USERNAME]!!,
- )
- System.setProperty(
- EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_ADMIN_PASSWORD,
- dotenv[EnvironmentVariableConstant.KOJA_AWS_RDS_DATABASE_ADMIN_PASSWORD]!!,
- )
- System.setProperty(
- EnvironmentVariableConstant.KOJA_AWS_DYNAMODB_ACCESS_KEY_ID,
- dotenv[EnvironmentVariableConstant.KOJA_AWS_DYNAMODB_ACCESS_KEY_ID]!!,
- )
- System.setProperty(
- EnvironmentVariableConstant.KOJA_AWS_DYNAMODB_ACCESS_KEY_SECRET,
- dotenv[EnvironmentVariableConstant.KOJA_AWS_DYNAMODB_ACCESS_KEY_SECRET]!!,
- )
- System.setProperty(
- EnvironmentVariableConstant.OPENAI_API_KEY,
- dotenv[EnvironmentVariableConstant.OPENAI_API_KEY]!!,
- )
- System.setProperty(
- EnvironmentVariableConstant.SERVER_ADDRESS,
- dotenv[EnvironmentVariableConstant.SERVER_ADDRESS]!!,
- )
- System.setProperty(
- EnvironmentVariableConstant.SERVER_PORT,
- dotenv[EnvironmentVariableConstant.SERVER_PORT] ?: "",
- )
- // Set Google Sign In client ID and client secret properties
- System.setProperty(
- EnvironmentVariableConstant.GOOGLE_CLIENT_ID,
- dotenv[EnvironmentVariableConstant.GOOGLE_CLIENT_ID]!!,
- )
- System.setProperty(
- EnvironmentVariableConstant.GOOGLE_CLIENT_SECRET,
- dotenv[EnvironmentVariableConstant.GOOGLE_CLIENT_SECRET]!!,
- )
- System.setProperty(
- EnvironmentVariableConstant.GOOGLE_MAPS_API_KEY,
- dotenv[EnvironmentVariableConstant.GOOGLE_MAPS_API_KEY]!!,
- )
- // Set JWT secret key and other related properties
- System.setProperty(
- EnvironmentVariableConstant.KOJA_JWT_SECRET,
- dotenv[EnvironmentVariableConstant.KOJA_JWT_SECRET]!!,
- )
- System.setProperty(
- EnvironmentVariableConstant.KOJA_ID_SECRET,
- dotenv[EnvironmentVariableConstant.KOJA_ID_SECRET]!!,
- )
- System.setProperty(
- EnvironmentVariableConstant.KOJA_PRIVATE_KEY_PASS,
- dotenv[EnvironmentVariableConstant.KOJA_PRIVATE_KEY_PASS]!!,
- )
- System.setProperty(
- EnvironmentVariableConstant.KOJA_PRIVATE_KEY_SALT,
- dotenv[EnvironmentVariableConstant.KOJA_PRIVATE_KEY_SALT]!!,
- )
+ @AfterEach
+ fun cleanup() {
+ unmockkAll()
}
// @BeforeEach
@@ -138,7 +148,6 @@ class UserCalendarServiceTest {
@Test
fun getAllUserEvents_with_null_token_throws_exception() {
- // Arrange
val mockUserID = 1
val userAccounts = mutableListOf()
val mockUserJWTData = UserJWTTokenDataDTO(userAccounts, mockUserID)
@@ -151,12 +160,11 @@ class UserCalendarServiceTest {
),
)
val tokenT = "mockToken"
- MockitoAnnotations.openMocks(this)
- whenever(jwtFunctionality.getUserJWTTokenData(eq(jwtToken))).thenReturn(mockUserJWTData)
+ whenever(jwtFunctionality.getUserJWTTokenData(jwtToken)).thenReturn(mockUserJWTData)
whenever(userAccountRepository.findByUserID(mockUserID)).thenReturn(emptyList())
// Assert
- assertThrows { userCalendarService.getAllUserEvents(eq(jwtToken)) }
+ assertThrows { userCalendarService.getAllUserEvents(jwtToken) }
}
@Test
@@ -338,6 +346,7 @@ class UserCalendarServiceTest {
@Test
fun `removeTimeBoundary should return false when the user does not exist`() {
// Arrange
+
val mockUserID = Int.MAX_VALUE
val userAccounts = mutableListOf()
val mockUserJWTData = UserJWTTokenDataDTO(userAccounts, mockUserID)