diff --git a/app_backend/app/routers/user.py b/app_backend/app/routers/user.py
index 2c8b632..acc3ea8 100644
--- a/app_backend/app/routers/user.py
+++ b/app_backend/app/routers/user.py
@@ -5,6 +5,7 @@
import json
from bson import BSON
from bson import json_util, ObjectId
+import bcrypt
from app.auth_handler import signJWT
from database import db
@@ -35,20 +36,34 @@ async def login(login: UserLogin, resp: Response):
email = login.email
password = login.password
- user = {
- "email": email,
- "password": password
- }
+ # get user with email
+ user = db.get_user_by_email(email, display_password=True)
- db_user: dict = db.get_user(user)
-
- if db_user is None:
+ # check if user exists
+ if user is None:
+ resp.status_code = status.HTTP_400_BAD_REQUEST
+ return {"err": "Invalid email or password."}
+
+ # check if password is correct
+ try:
+ if user['password'] != password and not bcrypt.checkpw(password.encode('utf-8'), user['password']):
+ resp.status_code = status.HTTP_400_BAD_REQUEST
+ return {"err": "Invalid email or password."}
+ except TypeError:
resp.status_code = status.HTTP_400_BAD_REQUEST
- return {"err": "This user does not exist. Please try different credentials."}, {}, None
+ return {"err": "Invalid email or password."}
- db_user["_id"] = str(db_user['_id'])
+ # if db_user is None:
+ # resp.status_code = status.HTTP_400_BAD_REQUEST
+ # return {"err": "This user does not exist. Please try different credentials."}, {}, None
- return {"msg": "Successfully logged in"}, signJWT(db_user['_id'], email), json.dumps(db_user, sort_keys=True, indent=4, default=json_util.default)
+ user["_id"] = str(user['_id'])
+
+ # drop password from user
+ user.pop("password")
+
+ return {"msg": "Successfully logged in"}, signJWT(user['_id'], email), \
+ json.dumps(user, sort_keys=True, indent=4, default=json_util.default)
"""
register implements the /register/ route
@@ -91,11 +106,14 @@ async def register(login: UserRegister, resp: Response):
resp.status_code = status.HTTP_400_BAD_REQUEST
return {"err": "Invalid password. It must be 8 to 20 characters and have at least one upper case letter, one lower case letter, and one digit."}
+ # hash the password
+ hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
+
# adds user to the database
new_user = {
"name": name,
"email": email,
- "password": password
+ "password": hashed_password
}
msg = db.save_user_in_db(new_user)
diff --git a/app_backend/database.py b/app_backend/database.py
index 5d81e2c..14cf5a4 100644
--- a/app_backend/database.py
+++ b/app_backend/database.py
@@ -59,10 +59,12 @@ def get_user_by_uuid(self, uuid):
users = self.db["users"]
return users.find_one({"_id": ObjectId(uuid)}, {"password": 0})
- def get_user_by_email(self, email):
+ def get_user_by_email(self, email, display_password=False):
users = self.db["users"]
- return users.find_one({'email': email}, {"password": 0})
-
+ if display_password:
+ return users.find_one({"email": email})
+ else:
+ return users.find_one({'email': email}, {"password": 0})
def get_user(self, login_info: dict):
users = self.db["users"]
diff --git a/app_backend/requirements.txt b/app_backend/requirements.txt
index d91a11b..6d6a7bc 100644
--- a/app_backend/requirements.txt
+++ b/app_backend/requirements.txt
@@ -34,3 +34,4 @@ uvicorn==0.15.0
wrapt==1.12.1
firebase_admin
pyjwt
+bcrypt
\ No newline at end of file
diff --git a/app_backend/tests/user_test.py b/app_backend/tests/user_test.py
index 8c27272..a12d5d2 100644
--- a/app_backend/tests/user_test.py
+++ b/app_backend/tests/user_test.py
@@ -26,7 +26,8 @@ def to_json(self):
for test_case in test_cases:
response = client.post("user/login", json=test_case.to_json())
- msg, _, _ = response.json()
+ msg = response.json()
+ print(msg)
assert response.status_code == test_case.expects_code
assert ("err" in msg) == test_case.expects_err
diff --git a/quack_app/ios/Flutter/AppFrameworkInfo.plist b/quack_app/ios/Flutter/AppFrameworkInfo.plist
index 8d4492f..658d8c4 100644
--- a/quack_app/ios/Flutter/AppFrameworkInfo.plist
+++ b/quack_app/ios/Flutter/AppFrameworkInfo.plist
@@ -2,25 +2,25 @@
- CFBundleDevelopmentRegion
- en
- CFBundleExecutable
- App
- CFBundleIdentifier
- io.flutter.flutter.app
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- App
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleSignature
- ????
- CFBundleVersion
- 1.0
- MinimumOSVersion
- 9.0
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ App
+ CFBundleIdentifier
+ io.flutter.flutter.app
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ App
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1.0
+ MinimumOSVersion
+ 12.0
diff --git a/quack_app/ios/Runner.xcodeproj/project.pbxproj b/quack_app/ios/Runner.xcodeproj/project.pbxproj
index 1659361..adf4e25 100644
--- a/quack_app/ios/Runner.xcodeproj/project.pbxproj
+++ b/quack_app/ios/Runner.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
@@ -121,7 +121,6 @@
5230E246B24F0BE2311519A2 /* Pods-Runner.release.xcconfig */,
0131A6EFB3849AFCEB303739 /* Pods-Runner.profile.xcconfig */,
);
- name = Pods;
path = Pods;
sourceTree = "";
};
@@ -156,7 +155,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1020;
+ LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -322,6 +321,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -340,7 +340,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -353,13 +353,17 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_APPICON_NAME = quack_icon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ CURRENT_PROJECT_VERSION = 133;
+ DEVELOPMENT_TEAM = HWH6G9P2V2;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = com.example.quackApp;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = works.dd.quack;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@@ -390,6 +394,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -414,7 +419,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -445,6 +450,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -463,11 +469,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
- SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
@@ -477,13 +484,17 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_APPICON_NAME = quack_icon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ CURRENT_PROJECT_VERSION = 133;
+ DEVELOPMENT_TEAM = HWH6G9P2V2;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = com.example.quackApp;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = works.dd.quack;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -496,13 +507,17 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_APPICON_NAME = quack_icon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ CURRENT_PROJECT_VERSION = 133;
+ DEVELOPMENT_TEAM = HWH6G9P2V2;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = com.example.quackApp;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = works.dd.quack;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
diff --git a/quack_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/quack_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index a28140c..c87d15a 100644
--- a/quack_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/quack_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
-
-
-
-
+
+
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- quack_app
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- $(FLUTTER_BUILD_NAME)
- CFBundleSignature
- ????
- CFBundleVersion
- $(FLUTTER_BUILD_NUMBER)
- LSRequiresIPhoneOS
-
- UILaunchStoryboardName
- LaunchScreen
- UIMainStoryboardFile
- Main
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UIViewControllerBasedStatusBarAppearance
-
- UIStatusBarHidden
-
-
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ Quack
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ quack_app
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ $(CURRENT_PROJECT_VERSION)
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UIStatusBarHidden
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIViewControllerBasedStatusBarAppearance
+
+
diff --git a/quack_app/lib/components/station_list.dart b/quack_app/lib/components/station_list.dart
index bc24e06..1741b6f 100644
--- a/quack_app/lib/components/station_list.dart
+++ b/quack_app/lib/components/station_list.dart
@@ -80,7 +80,9 @@ class _StationListState extends State {
.menuFilteredBy((item) => mainFilter(item) && widget.filter(item));
// Set all FoodItems that has name in favorites to be favorited
+ // debugPrint(favorites.toString());
for (FoodItem item in stationCurrentItems) {
+ // debugPrint(item.getName());
item.setIsFavorite(favorites.contains(item.getName()));
}
diff --git a/quack_app/lib/core/food/food_item.dart b/quack_app/lib/core/food/food_item.dart
index 7b24630..3b00474 100644
--- a/quack_app/lib/core/food/food_item.dart
+++ b/quack_app/lib/core/food/food_item.dart
@@ -31,6 +31,7 @@ class FoodItem {
Future toggleFavorite() async {
await User().userData.toggleFavorite(getName(), !_isFavorite).then((response) => {
if (response) {
+
this._isFavorite = !this._isFavorite
}
});
diff --git a/quack_app/lib/core/user/user_data.dart b/quack_app/lib/core/user/user_data.dart
index 78714ad..356fd88 100644
--- a/quack_app/lib/core/user/user_data.dart
+++ b/quack_app/lib/core/user/user_data.dart
@@ -47,9 +47,8 @@ class UserData {
_friends = await loadFriends();
// If the type of data["favorites"] is List, then assign it to _favorites
// Otherwise, if it is List, then convert it to List
- if (data["favorites"] is List) {
- _favorites = data["favorites"];
- }
+ // debugPrint(data["favorites"].runtimeType.toString());
+ _favorites = List.from(data["favorites"]);
return Future.value(true);
}
@@ -82,6 +81,11 @@ class UserData {
// If the response code is 200, return true
if (response.statusCode == 200) {
+ if (!_favorites.contains(name) && state) {
+ _favorites.add(name);
+ } else if (_favorites.contains(name) && !state) {
+ _favorites.remove(name);
+ }
return Future.value(true);
} else {
return Future.value(false);
diff --git a/quack_app/pubspec.yaml b/quack_app/pubspec.yaml
index c1444b1..d44f82b 100644
--- a/quack_app/pubspec.yaml
+++ b/quack_app/pubspec.yaml
@@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
-version: 1.0.0+1
+version: 1.0.0+133
environment:
sdk: ">=2.12.0 <3.0.0"