From 598605ceac5691718981fa1993546015a8956dc7 Mon Sep 17 00:00:00 2001 From: Ion Agorria Date: Mon, 4 Mar 2019 10:00:42 +0100 Subject: [PATCH 1/6] Bump shard_preferences --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 93c7c4254..7eb38c1e9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: http: ^0.12.0 # Utils - shared_preferences: ^0.4.3 + shared_preferences: ^0.5.0 path_provider: ^0.4.1 uuid: ^1.0.3 From 1abb25a886433b8f8d9740bb06d4f92f499a5963 Mon Sep 17 00:00:00 2001 From: Ion Agorria Date: Mon, 4 Mar 2019 10:00:52 +0100 Subject: [PATCH 2/6] Add loginWith --- lib/src/enums/parse_enum_api_rq.dart | 1 + lib/src/objects/parse_user.dart | 40 +++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/lib/src/enums/parse_enum_api_rq.dart b/lib/src/enums/parse_enum_api_rq.dart index 6b6f2b338..ea0b9b15d 100644 --- a/lib/src/enums/parse_enum_api_rq.dart +++ b/lib/src/enums/parse_enum_api_rq.dart @@ -14,6 +14,7 @@ enum ParseApiRQ { login, logout, loginAnonymous, + loginWith, verificationEmailRequest, requestPasswordReset, destroy, diff --git a/lib/src/objects/parse_user.dart b/lib/src/objects/parse_user.dart index 7c7b05e7f..b773431a4 100644 --- a/lib/src/objects/parse_user.dart +++ b/lib/src/objects/parse_user.dart @@ -62,7 +62,7 @@ class ParseUser extends ParseObject implements ParseCloneable { ParseUser.forQuery() : super(keyClassUser); - createUser(String username, String password, [String emailAddress]) { + static createUser([String username, String password, String emailAddress]) { return ParseUser(username, password, emailAddress); } @@ -206,6 +206,44 @@ class ParseUser extends ParseObject implements ParseCloneable { } } + // Logs in a user using a service + static Future loginWith(String provider, Object authData) async { + ParseUser user = ParseUser.createUser(); + var response = await user._loginWith(provider, authData); + if (response.success) { + return user; + } else { + return Future.error(response); + } + } + + Future _loginWith(String provider, Object authData) async { + try { + Uri tempUri = Uri.parse(_client.data.serverUrl); + + Uri url = Uri( + scheme: tempUri.scheme, + host: tempUri.host, + path: "${tempUri.path}$keyEndPointUsers", + ); + + final response = await _client.post(url, + headers: { + keyHeaderRevocableSession: "1", + }, + body: jsonEncode({ + "authData": { + provider: authData + } + })); + + return _handleResponse( + this, response, ParseApiRQ.loginWith, _debug, className); + } on Exception catch (e) { + return _handleException(e, ParseApiRQ.loginWith, _debug, className); + } + } + /// Sends a request to delete the sessions token from the /// server. Will also delete the local user data unless /// deleteLocalUserData is false. From 43bd6130e12f18359ccd6c8a113e9c5baa707e9a Mon Sep 17 00:00:00 2001 From: Ion Agorria Date: Tue, 5 Mar 2019 14:05:51 +0100 Subject: [PATCH 3/6] ParseInstallation implementation --- lib/parse_server_sdk.dart | 4 + lib/src/base/parse_constants.dart | 2 + lib/src/objects/parse_installation.dart | 148 ++++++++++++++++++++++++ pubspec.yaml | 2 + 4 files changed, 156 insertions(+) create mode 100644 lib/src/objects/parse_installation.dart diff --git a/lib/parse_server_sdk.dart b/lib/parse_server_sdk.dart index a6c9ff267..acd4616df 100644 --- a/lib/parse_server_sdk.dart +++ b/lib/parse_server_sdk.dart @@ -13,6 +13,8 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:web_socket_channel/io.dart'; import 'package:uuid/uuid.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:devicelocale/devicelocale.dart'; +import 'package:package_info/package_info.dart'; part 'src/base/parse_constants.dart'; @@ -46,6 +48,8 @@ part 'src/objects/parse_response.dart'; part 'src/objects/parse_user.dart'; +part 'src/objects/parse_installation.dart'; + part 'src/utils/parse_decoder.dart'; part 'src/utils/parse_encoder.dart'; diff --git a/lib/src/base/parse_constants.dart b/lib/src/base/parse_constants.dart index e4f7b094f..1d6037a9e 100644 --- a/lib/src/base/parse_constants.dart +++ b/lib/src/base/parse_constants.dart @@ -28,6 +28,7 @@ const String keyVarAcl = 'ACL'; // Classes const String keyClassMain = 'ParseMain'; const String keyClassUser = '_User'; +const String keyClassInstallation = '_Installation'; const String keyGeoPoint = 'GeoPoint'; const String keyFile = 'File'; @@ -47,3 +48,4 @@ const String keyParamSessionToken = 'sessionToken'; // Storage const String keyParseStoreBase = 'flutter_parse_sdk_'; const String keyParseStoreUser = "${keyParseStoreBase}user"; +const String keyParseStoreInstallation = "${keyParseStoreBase}installation"; diff --git a/lib/src/objects/parse_installation.dart b/lib/src/objects/parse_installation.dart new file mode 100644 index 000000000..32d148f9c --- /dev/null +++ b/lib/src/objects/parse_installation.dart @@ -0,0 +1,148 @@ +part of flutter_parse_sdk; + +class ParseInstallation extends ParseObject { + static final String keyTimeZone = 'timeZone'; + static final String keyLocaleIdentifier = 'localeIdentifier'; + static final String keyDeviceToken = 'deviceToken'; + static final String keyDeviceType = 'deviceType'; + static final String keyInstallationId = 'installationId'; + static final String keyAppName = 'appName'; + static final String keyAppVersion = 'appVersion'; + static final String keyAppIdentifier = 'appIdentifier'; + static final String keyParseVersion = 'parseVersion'; + static final List readOnlyKeys = [ //TODO + keyDeviceToken, keyDeviceType, keyInstallationId, + keyAppName, keyAppVersion, keyAppIdentifier, keyParseVersion + ]; + static String _currentInstallationId; + + //Getters/setters + + Map get acl => super.get(keyVarAcl); + + set acl(Map acl) => set(keyVarAcl, acl); + + String get deviceToken => super.get(keyDeviceToken); + + set deviceToken(String deviceToken) => set(keyDeviceToken, deviceToken); + + String get deviceType => super.get(keyDeviceType); + + String get installationId => super.get(keyInstallationId); + + set _installationId(String installationId) => set(keyInstallationId, installationId); + + String get appName => super.get(keyAppName); + + String get appVersion => super.get(keyAppVersion); + + String get appIdentifier => super.get(keyAppIdentifier); + + String get parseVersion => super.get(keyParseVersion); + + /// Creates an instance of ParseInstallation + ParseInstallation( + {bool debug, + ParseHTTPClient client, + bool autoSendSessionId}) + : super(keyClassInstallation) { + _debug = isDebugEnabled(objectLevelDebug: debug); + _client = client ?? + ParseHTTPClient( + autoSendSessionId: + autoSendSessionId ?? ParseCoreData().autoSendSessionId, + securityContext: ParseCoreData().securityContext); + } + + ParseInstallation.forQuery() : super(keyClassUser); + + static Future isCurrent(ParseInstallation installation) async { + if (_currentInstallationId == null) { + _currentInstallationId = (await _getFromLocalStore()).installationId; + } + return _currentInstallationId != null && installation.installationId == _currentInstallationId; + } + + /// Gets the current installation from storage + static Future currentInstallation() async { + var installation = await _getFromLocalStore(); + if (installation == null) { + installation = await _createInstallation(); + } + return installation; + } + + /// Updates the installation with current device data + _updateInstallation() async { + //Device type + if (Platform.isAndroid) set(keyDeviceType, "android"); + else if (Platform.isIOS) set(keyDeviceType, "ios"); + else throw Exception("Unsupported platform/operating system"); + + //Locale + String locale = await Devicelocale.currentLocale; + if (locale != null && locale.isNotEmpty) { + set(keyLocaleIdentifier, locale); + } + + //Timezone + //TODO set(keyTimeZone, ); + + //App info + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + set(keyAppName, packageInfo.appName); + set(keyAppVersion, packageInfo.version); + set(keyAppIdentifier, packageInfo.packageName); + set(keyParseVersion, keySdkVersion); + } + + Future create() async { + var isCurrent = await ParseInstallation.isCurrent(this); + if (isCurrent) await _updateInstallation(); + ParseResponse parseResponse = await super.create(); + if (parseResponse.success && isCurrent) { + saveInStorage(keyParseStoreInstallation); + } + return parseResponse; + } + + /// Saves the current installation + Future save() async { + var isCurrent = await ParseInstallation.isCurrent(this); + if (isCurrent) await _updateInstallation(); + ParseResponse parseResponse = await super.save(); + if (parseResponse.success && isCurrent) { + saveInStorage(keyParseStoreInstallation); + } + return parseResponse; + } + + /// Gets the locally stored installation + static Future _getFromLocalStore() async { + var installationJson = + (await ParseCoreData().getStore()).getString(keyParseStoreInstallation); + + if (installationJson != null) { + var installationMap = parseDecode(json.decode(installationJson)); + + if (installationMap != null) { + return new ParseInstallation()..fromJson(installationMap); + } + } + + return null; + } + + /// Creates a installation for current device + /// Assumes that this is called because there is no previous installation + /// so it creates and sets the static current installation UUID + static Future _createInstallation() async { + if (_currentInstallationId == null) { + _currentInstallationId = Uuid().v4(); + } + var installation = new ParseInstallation(); + installation._installationId = _currentInstallationId; + await installation._updateInstallation(); + return installation; + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 7f67d35dd..771e1f1d0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,6 +19,8 @@ dependencies: shared_preferences: ^0.4.3 path_provider: ^0.4.1 uuid: ^1.0.3 + package_info: ^0.4.0 + devicelocale: ^0.1.1 dev_dependencies: # Testing From b2b075b916b54663f7ce6fcf5aa26f1eb072bba7 Mon Sep 17 00:00:00 2001 From: rodrigosmarques Date: Wed, 6 Mar 2019 02:26:53 -0300 Subject: [PATCH 4/6] Added support for Geo Queries: Added support for Geo Queries: - whereNear - whereWithinMiles - whereWithinKilometers - whereWithinRadians - whereWithinGeoBox --- lib/src/network/parse_query.dart | 51 ++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/lib/src/network/parse_query.dart b/lib/src/network/parse_query.dart index 3d3813e74..8cdd67623 100644 --- a/lib/src/network/parse_query.dart +++ b/lib/src/network/parse_query.dart @@ -182,6 +182,57 @@ class QueryBuilder { if (orderByScore) orderByDescending('score'); } + /// Returns an objects with key point values near the point given + void whereNear(String column, ParseGeoPoint point) { + var latitude = point.latitude; + var longitude = point.longitude; + queries.add(MapEntry(_SINGLE_QUERY, + '\"$column\":{\"\$nearSphere\":{\"__type\":\"GeoPoint\",\"latitude\":$latitude,\"longitude\":$longitude}}')); + } + + /// Returns an object with key point values near the point given and within the maximum distance given. + void whereWithinMiles( + String column, ParseGeoPoint point, double maxDistance) { + var latitude = point.latitude; + var longitude = point.longitude; + + queries.add(MapEntry(_SINGLE_QUERY, + '\"$column\":{\"\$nearSphere\":{\"__type\":\"GeoPoint\",\"latitude\":$latitude,\"longitude\":$longitude},\"\$maxDistanceInMiles\":$maxDistance}')); + } + + /// Returns an object with key point values near the point given and within the maximum distance given. + void whereWithinKilometers( + String column, ParseGeoPoint point, double maxDistance) { + var latitude = point.latitude; + var longitude = point.longitude; + + queries.add(MapEntry(_SINGLE_QUERY, + '\"$column\":{\"\$nearSphere\":{\"__type\":\"GeoPoint\",\"latitude\":$latitude,\"longitude\":$longitude},\"\$maxDistanceInKilometers\":$maxDistance}')); + } + + /// Returns an object with key point values near the point given and within the maximum distance given. + void whereWithinRadians( + String column, ParseGeoPoint point, double maxDistance) { + var latitude = point.latitude; + var longitude = point.longitude; + + queries.add(MapEntry(_SINGLE_QUERY, + '\"$column\":{\"\$nearSphere\":{\"__type\":\"GeoPoint\",\"latitude\":$latitude,\"longitude\":$longitude},\"\$maxDistanceInRadians\":$maxDistance}')); + } + + /// Returns an object with key point values contained within a given rectangular geographic bounding box. + void whereWithinGeoBox( + String column, ParseGeoPoint southwest, ParseGeoPoint northeast) { + var latitudeS = southwest.latitude; + var longitudeS = southwest.longitude; + + var latitudeN = northeast.latitude; + var longitudeN = northeast.longitude; + + queries.add(MapEntry(_SINGLE_QUERY, + '\"$column\":{\"\$within\":{\"\$box\": [{\"__type\": \"GeoPoint\",\"latitude\":$latitudeS,\"longitude\":$longitudeS},{\"__type\": \"GeoPoint\",\"latitude\":$latitudeN,\"longitude\":$longitudeN}]}}')); + } + /// Finishes the query and calls the server /// /// Make sure to call this after defining your queries From 75d43a2d7c9bba6b7ffc26a9ea591653c679ad61 Mon Sep 17 00:00:00 2001 From: Phill Date: Wed, 6 Mar 2019 17:42:21 +0000 Subject: [PATCH 5/6] Merge branches 'develop' and 'master' of https://github.com/phillwiggins/flutter_parse_sdk # Conflicts: # .idea/libraries/Dart_Packages.xml # lib/src/objects/parse_file.dart # lib/src/objects/parse_user.dart # pubspec.yaml --- CHANGELOG.md | 5 +++++ README.md | 2 +- example/lib/main.dart | 13 +++++++------ example/pubspec.yaml | 2 +- lib/src/base/parse_constants.dart | 2 +- lib/src/objects/parse_object.dart | 5 +++-- pubspec.yaml | 2 +- 7 files changed, 19 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23bc07ed9..8ce20bba1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.0.14 +Corrected delete & path issue +Added Geo queries +Added ability to add login oAuth data + ## 1.0.13 Added full bool to convert objects to JSON correctly diff --git a/README.md b/README.md index 12abb93e9..563d31260 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Want to get involved? Join our Slack channel and help out! (http://flutter-parse To install, either add to your pubspec.yaml ``` dependencies: - parse_server_sdk: ^1.0.13 + parse_server_sdk: ^1.0.14 ``` or clone this repository and add to your project. As this is an early development with multiple contributors, it is probably best to download/clone and keep updating as an when a new feature is added. diff --git a/example/lib/main.dart b/example/lib/main.dart index 99468d277..06dbf8527 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,9 +1,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_plugin_example/application_constants.dart'; import 'package:flutter_plugin_example/diet_plan.dart'; +import 'package:flutter_stetho/flutter_stetho.dart'; import 'package:parse_server_sdk/parse_server_sdk.dart'; -void main() => runApp(new MyApp()); +void main() { + Stetho.initialize(); + runApp(new MyApp()); +} class MyApp extends StatefulWidget { @override @@ -109,10 +113,10 @@ class _MyAppState extends State { if (randomInt is int) print('Saving generic value worked!'); // Shows example of pinning an item - dietPlan.pin(); + await dietPlan.pin(); // shows example of retrieving a pin - var newDietPlanFromPin = DietPlan().fromPin('R5EonpUDWy'); + var newDietPlanFromPin = await DietPlan().fromPin('R5EonpUDWy'); if (newDietPlanFromPin != null) print('Retreiving from pin worked!'); } else { print(ApplicationConstants.keyAppName + ": " + apiResponse.error.message); @@ -149,9 +153,6 @@ class _MyAppState extends State { if (response.success) user = response.result; response = await user.verificationEmailRequest(); - if (response.success) user = response.result; - - user = null; // Best practice for starting the app. This will check for a valid user user = await ParseUser.currentUser(); await user.logout(); diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 152aa9e24..ba2f6813c 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -8,9 +8,9 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 + flutter_stetho: ^0.2.2 dev_dependencies: - parse_server_sdk: path: ../ diff --git a/lib/src/base/parse_constants.dart b/lib/src/base/parse_constants.dart index 1d6037a9e..dbdf3bb3f 100644 --- a/lib/src/base/parse_constants.dart +++ b/lib/src/base/parse_constants.dart @@ -1,7 +1,7 @@ part of flutter_parse_sdk; // Library -const String keySdkVersion = '1.0.13'; +const String keySdkVersion = '1.0.14'; const String keyLibraryName = 'Flutter Parse SDK'; // End Points diff --git a/lib/src/objects/parse_object.dart b/lib/src/objects/parse_object.dart index 5c28f8e8a..4ccca79a1 100644 --- a/lib/src/objects/parse_object.dart +++ b/lib/src/objects/parse_object.dart @@ -190,9 +190,10 @@ class ParseObject extends ParseBase implements ParseCloneable { } /// Deletes the current object locally and online - Future delete(String path, String objectId) async { + Future delete(String objectId, {String path}) async { try { - var uri = "${ParseCoreData().serverUrl}$_path/$objectId"; + path ??= _path; + var uri = "${ParseCoreData().serverUrl}$path/$objectId"; var result = await _client.delete(uri); return handleResponse(this, result, ParseApiRQ.delete, _debug, className); } on Exception catch (e) { diff --git a/pubspec.yaml b/pubspec.yaml index ec68b252b..f28937a4d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: parse_server_sdk description: Flutter plugin for Parse Server, (https://parseplatform.org), (https://back4app.com) -version: 1.0.13 +version: 1.0.14 homepage: https://github.com/phillwiggins/flutter_parse_sdk author: PhillWiggins From 251ccd2e2b7bf20251a2e4a7be83f2a2a47d8500 Mon Sep 17 00:00:00 2001 From: Phill Date: Thu, 7 Mar 2019 08:01:33 +0000 Subject: [PATCH 6/6] Hotfix for full bool null error --- CHANGELOG.md | 3 +++ README.md | 2 +- lib/src/base/parse_constants.dart | 2 +- lib/src/utils/parse_encoder.dart | 4 +++- pubspec.yaml | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ce20bba1..c333a7593 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 1.0.15 +Fixed 'full' bool issue + ## 1.0.14 Corrected delete & path issue Added Geo queries diff --git a/README.md b/README.md index 563d31260..411fdd69b 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Want to get involved? Join our Slack channel and help out! (http://flutter-parse To install, either add to your pubspec.yaml ``` dependencies: - parse_server_sdk: ^1.0.14 + parse_server_sdk: ^1.0.15 ``` or clone this repository and add to your project. As this is an early development with multiple contributors, it is probably best to download/clone and keep updating as an when a new feature is added. diff --git a/lib/src/base/parse_constants.dart b/lib/src/base/parse_constants.dart index dbdf3bb3f..b900b15a4 100644 --- a/lib/src/base/parse_constants.dart +++ b/lib/src/base/parse_constants.dart @@ -1,7 +1,7 @@ part of flutter_parse_sdk; // Library -const String keySdkVersion = '1.0.14'; +const String keySdkVersion = '1.0.15'; const String keyLibraryName = 'Flutter Parse SDK'; // End Points diff --git a/lib/src/utils/parse_encoder.dart b/lib/src/utils/parse_encoder.dart index e2d14bc72..ef0e564a9 100644 --- a/lib/src/utils/parse_encoder.dart +++ b/lib/src/utils/parse_encoder.dart @@ -9,7 +9,9 @@ dynamic dateTimeEncoder(dynamic item) { } /// Custom json encoder for types related to parse -dynamic parseEncode(dynamic value, {bool full = false}) { +dynamic parseEncode(dynamic value, {bool full}) { + full ??= false; + if (value is DateTime) return _encodeDate(value); if (value is List) { diff --git a/pubspec.yaml b/pubspec.yaml index f28937a4d..53fbb7f49 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: parse_server_sdk description: Flutter plugin for Parse Server, (https://parseplatform.org), (https://back4app.com) -version: 1.0.14 +version: 1.0.15 homepage: https://github.com/phillwiggins/flutter_parse_sdk author: PhillWiggins