From 2d04437818c2f6a3c63f3a9e22047b594f1d4d57 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Thu, 15 Mar 2018 17:09:23 -0700 Subject: [PATCH 01/20] Throttle HTTP requests made to the auth server Making thousands of HTTP requests simultaneously inevitably results in some failing or the server being overwhelmed, so limit how many can be made at once (currently to the arbitrary cap of 5) and enqueue any further requests. --- CHANGELOG.md | 15 +++++++++++++++ lib/user-methods.js | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6da2d5b..c70c630e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +X.Y.Z Release notes +============================================================= +### Breaking changes +* None. + +### Enhancements +* None. + +### Bug fixes +* [Sync] Avoid hammering the ROS authentication service when large numbers of Realms are opened at once. + +### Internal +* None. + + 2.2.15 Release notes (2018-3-9) ============================================================= ### Breaking changes diff --git a/lib/user-methods.js b/lib/user-methods.js index 9634ef37..2367837d 100644 --- a/lib/user-methods.js +++ b/lib/user-methods.js @@ -36,8 +36,43 @@ function checkTypes(args, types) { } } -/* global fetch */ -const performFetch = typeof fetch === 'undefined' ? node_require('node-fetch') : fetch; +// Perform a HTTP request, enqueuing it if too many requests are already in +// progress to avoid hammering the server. +const performFetch = (function() { + const doFetch = typeof fetch === 'undefined' ? node_require('node-fetch') : fetch; + const queue = []; + let count = 0; + const maxCount = 5; + const next = () => { + if (count >= maxCount) { + return; + } + const req = queue.shift(); + if (!req) { + return; + } + const [url, options, resolve, reject] = req; + ++count; + // node doesn't support Promise.prototype.finally until 10 + doFetch(url, options) + .then(response => { + --count; + next(); + resolve(response); + }) + .catch(error => { + --count; + next(); + reject(error); + }); + }; + return (url, options) => { + return new Promise((resolve, reject) => { + queue.push([url, options, resolve, reject]); + next(); + }); + }; +})(); const url_parse = require('url-parse'); From 31fb9ceb1afcdb053c92e4cdd0c3daaf8cf078fc Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Fri, 16 Mar 2018 09:38:35 +0100 Subject: [PATCH 02/20] [2.2.16] Bump version --- CHANGELOG.md | 2 +- dependencies.list | 2 +- package.json | 2 +- src/RealmJS.xcodeproj/project.pbxproj | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c70c630e..9d5a14f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -X.Y.Z Release notes +2.2.16 Release notes (2018-3-16) ============================================================= ### Breaking changes * None. diff --git a/dependencies.list b/dependencies.list index b5b26536..d3dd2dd7 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,5 +1,5 @@ PACKAGE_NAME=realm-js -VERSION=2.2.15 +VERSION=2.2.16 REALM_CORE_VERSION=5.1.2 REALM_SYNC_VERSION=2.2.15 REALM_OBJECT_SERVER_VERSION=2.5.1 diff --git a/package.json b/package.json index 41687bcf..59c5780b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "realm", "description": "Realm is a mobile database: an alternative to SQLite and key-value stores", - "version": "2.2.15", + "version": "2.2.16", "license": "Apache-2.0", "homepage": "https://realm.io", "keywords": [ diff --git a/src/RealmJS.xcodeproj/project.pbxproj b/src/RealmJS.xcodeproj/project.pbxproj index 1f91bf63..e5194a5d 100644 --- a/src/RealmJS.xcodeproj/project.pbxproj +++ b/src/RealmJS.xcodeproj/project.pbxproj @@ -961,7 +961,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.2.15; + CURRENT_PROJECT_VERSION = 2.2.16; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -1025,7 +1025,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.2.15; + CURRENT_PROJECT_VERSION = 2.2.16; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; From b452c1fb046760114ed44a439e81c18904bd3f2e Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Wed, 21 Mar 2018 10:20:00 +0100 Subject: [PATCH 03/20] Updating changelog --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d5a14f0..a42c4664 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +X.Y.Z Release notes +============================================================= +### Breaking changes +* None. + +### Enhancements +* None. + +### Bug fixes +* [Sync] Do a better job of not opening the notifier pipe file for global notifier realms. + +### Internal +* None. + + 2.2.16 Release notes (2018-3-16) ============================================================= ### Breaking changes From 1d0b1dcc242043e1fe9c846a46022dd985108e9f Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Wed, 21 Mar 2018 10:33:49 +0100 Subject: [PATCH 04/20] [2.2.17] Bump realm-js version --- CHANGELOG.md | 2 +- dependencies.list | 2 +- package.json | 2 +- src/RealmJS.xcodeproj/project.pbxproj | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a42c4664..86789d32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -X.Y.Z Release notes +2.2.17 Release notes (2018-3-21) ============================================================= ### Breaking changes * None. diff --git a/dependencies.list b/dependencies.list index d3dd2dd7..e5836f16 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,5 +1,5 @@ PACKAGE_NAME=realm-js -VERSION=2.2.16 +VERSION=2.2.17 REALM_CORE_VERSION=5.1.2 REALM_SYNC_VERSION=2.2.15 REALM_OBJECT_SERVER_VERSION=2.5.1 diff --git a/package.json b/package.json index 59c5780b..71ac39fd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "realm", "description": "Realm is a mobile database: an alternative to SQLite and key-value stores", - "version": "2.2.16", + "version": "2.2.17", "license": "Apache-2.0", "homepage": "https://realm.io", "keywords": [ diff --git a/src/RealmJS.xcodeproj/project.pbxproj b/src/RealmJS.xcodeproj/project.pbxproj index e5194a5d..045da518 100644 --- a/src/RealmJS.xcodeproj/project.pbxproj +++ b/src/RealmJS.xcodeproj/project.pbxproj @@ -961,7 +961,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.2.16; + CURRENT_PROJECT_VERSION = 2.2.17; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -1025,7 +1025,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.2.16; + CURRENT_PROJECT_VERSION = 2.2.17; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; From bf26c01fd32d472825b07513918b2691be5f8bb9 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 20 Mar 2018 16:52:52 -0700 Subject: [PATCH 05/20] Avoid leaking realms when an error occurs within an event handler --- lib/notification-worker.js | 9 ++++++++- lib/notifier.js | 17 +++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/notification-worker.js b/lib/notification-worker.js index d6c3f030..84191b3b 100644 --- a/lib/notification-worker.js +++ b/lib/notification-worker.js @@ -43,7 +43,14 @@ process.on('message', (m) => { if (impl.onchange) { const change = Realm.Sync._deserializeChangeSet(m.change); if (!change.isEmpty) { - impl.onchange(change); + try { + impl.onchange(change); + } + catch (e) { + change.close(); + process.send({change: m.change}); + throw e; + } } change.close(); } diff --git a/lib/notifier.js b/lib/notifier.js index ea62a36c..a6bc6dd4 100644 --- a/lib/notifier.js +++ b/lib/notifier.js @@ -65,11 +65,24 @@ class FunctionListener { changes.release(); return; } - const promise = Promise.resolve(this.fn(changes)); + + let promise; + try { + promise = Promise.resolve(this.fn(changes)); + } + catch (e) { + changes.release(); + throw e; + } + this.pending.push(promise); - promise.then(() => { + const release = () => { changes.release(); this.pending.splice(this.pending.indexOf(promise), 1); + }; + promise.then(release).catch(e => { + release(); + throw e; }); } }; From 339cf14c38daa302256c3bfa71d7c59272428735 Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Fri, 23 Mar 2018 09:57:42 +0100 Subject: [PATCH 06/20] [2.2.18] Bump version --- CHANGELOG.md | 15 +++++++++++++++ dependencies.list | 2 +- package.json | 2 +- src/RealmJS.xcodeproj/project.pbxproj | 4 ++-- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86789d32..6bdeb7e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +2.2.18 Release notes (2018-3-23) +============================================================= +### Breaking changes +* None. + +### Enhancements +* None. + +### Bug fixes +* Fixed a bug where leaking Realms when an error occurs within an event handler (#1725). + +### Internal +* None. + + 2.2.17 Release notes (2018-3-21) ============================================================= ### Breaking changes diff --git a/dependencies.list b/dependencies.list index e5836f16..424c2fe6 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,5 +1,5 @@ PACKAGE_NAME=realm-js -VERSION=2.2.17 +VERSION=2.2.18 REALM_CORE_VERSION=5.1.2 REALM_SYNC_VERSION=2.2.15 REALM_OBJECT_SERVER_VERSION=2.5.1 diff --git a/package.json b/package.json index 71ac39fd..83e91720 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "realm", "description": "Realm is a mobile database: an alternative to SQLite and key-value stores", - "version": "2.2.17", + "version": "2.2.18", "license": "Apache-2.0", "homepage": "https://realm.io", "keywords": [ diff --git a/src/RealmJS.xcodeproj/project.pbxproj b/src/RealmJS.xcodeproj/project.pbxproj index 045da518..a6655a49 100644 --- a/src/RealmJS.xcodeproj/project.pbxproj +++ b/src/RealmJS.xcodeproj/project.pbxproj @@ -961,7 +961,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.2.17; + CURRENT_PROJECT_VERSION = 2.2.18; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -1025,7 +1025,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.2.17; + CURRENT_PROJECT_VERSION = 2.2.18; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; From 7387a79e1031bc6668ea721ee84fb09315a9df6f Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Fri, 23 Mar 2018 09:57:42 +0100 Subject: [PATCH 07/20] [2.2.18] Bump version --- CHANGELOG.md | 15 +++++++++++++++ dependencies.list | 2 +- package.json | 2 +- src/RealmJS.xcodeproj/project.pbxproj | 4 ++-- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86789d32..bdeb4d17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +2.2.18 Release notes (2018-3-23) +============================================================= +### Breaking changes +* None. + +### Enhancements +* None. + +### Bug fixes +* Fixed a bug where leaking Realms when an error occurs within an event handler (#1725). + +### Internal +* Added trace logging to the global notifier (realm-js-private #426). + + 2.2.17 Release notes (2018-3-21) ============================================================= ### Breaking changes diff --git a/dependencies.list b/dependencies.list index e5836f16..424c2fe6 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,5 +1,5 @@ PACKAGE_NAME=realm-js -VERSION=2.2.17 +VERSION=2.2.18 REALM_CORE_VERSION=5.1.2 REALM_SYNC_VERSION=2.2.15 REALM_OBJECT_SERVER_VERSION=2.5.1 diff --git a/package.json b/package.json index 71ac39fd..83e91720 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "realm", "description": "Realm is a mobile database: an alternative to SQLite and key-value stores", - "version": "2.2.17", + "version": "2.2.18", "license": "Apache-2.0", "homepage": "https://realm.io", "keywords": [ diff --git a/src/RealmJS.xcodeproj/project.pbxproj b/src/RealmJS.xcodeproj/project.pbxproj index 045da518..a6655a49 100644 --- a/src/RealmJS.xcodeproj/project.pbxproj +++ b/src/RealmJS.xcodeproj/project.pbxproj @@ -961,7 +961,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.2.17; + CURRENT_PROJECT_VERSION = 2.2.18; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -1025,7 +1025,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.2.17; + CURRENT_PROJECT_VERSION = 2.2.18; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; From 5140824d9369b92f0758c1b3747aa5fe68c41095 Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Tue, 10 Apr 2018 10:43:13 +0200 Subject: [PATCH 08/20] Preparing 2.2.19 (#1745) --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdeb4d17..7eb8a17e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +X.Y.Z Release notes +============================================================= +### Breaking changes +* None. + +### Enhancements +* None. + +### Bug fixes +* Avoid crashing if partial Realms find their way into the admin Realm when using Realm Object Server v3.0.0 or later (realm-js-private #430). + +### +* None. + + 2.2.18 Release notes (2018-3-23) ============================================================= ### Breaking changes From 78a4478aa7cd1cec0c5abfe9248d70c48708bb95 Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Tue, 10 Apr 2018 10:44:51 +0200 Subject: [PATCH 09/20] [2.2.19] Bump version --- CHANGELOG.md | 2 +- dependencies.list | 2 +- package.json | 2 +- src/RealmJS.xcodeproj/project.pbxproj | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eb8a17e..fb95ed9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -X.Y.Z Release notes +2.2.19 Release notes (2018-4-10) ============================================================= ### Breaking changes * None. diff --git a/dependencies.list b/dependencies.list index 424c2fe6..6cea8b3b 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,5 +1,5 @@ PACKAGE_NAME=realm-js -VERSION=2.2.18 +VERSION=2.2.19 REALM_CORE_VERSION=5.1.2 REALM_SYNC_VERSION=2.2.15 REALM_OBJECT_SERVER_VERSION=2.5.1 diff --git a/package.json b/package.json index 83e91720..d7201ea7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "realm", "description": "Realm is a mobile database: an alternative to SQLite and key-value stores", - "version": "2.2.18", + "version": "2.2.19", "license": "Apache-2.0", "homepage": "https://realm.io", "keywords": [ diff --git a/src/RealmJS.xcodeproj/project.pbxproj b/src/RealmJS.xcodeproj/project.pbxproj index a6655a49..204922c1 100644 --- a/src/RealmJS.xcodeproj/project.pbxproj +++ b/src/RealmJS.xcodeproj/project.pbxproj @@ -961,7 +961,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.2.18; + CURRENT_PROJECT_VERSION = 2.2.19; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -1025,7 +1025,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.2.18; + CURRENT_PROJECT_VERSION = 2.2.19; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; From 4c811524b1f27120da420e4ef289f5658dd6b2d3 Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Fri, 13 Apr 2018 10:07:56 +0200 Subject: [PATCH 10/20] Updating to Realm Sync 2.2.17 (#1749) --- CHANGELOG.md | 17 ++++++++++++++++- dependencies.list | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb95ed9f..c7fdd28a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +X.Y.Z Release notes +============================================================= +### Breaking changes +* None. + +### Enhancements +* None. + +### Bug fixes +* None. + +### Internal +* Updated to Realm Sync 2.2.17 + + 2.2.19 Release notes (2018-4-10) ============================================================= ### Breaking changes @@ -9,7 +24,7 @@ ### Bug fixes * Avoid crashing if partial Realms find their way into the admin Realm when using Realm Object Server v3.0.0 or later (realm-js-private #430). -### +### Internal * None. diff --git a/dependencies.list b/dependencies.list index 6cea8b3b..4a603450 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,5 +1,5 @@ PACKAGE_NAME=realm-js VERSION=2.2.19 REALM_CORE_VERSION=5.1.2 -REALM_SYNC_VERSION=2.2.15 +REALM_SYNC_VERSION=2.2.17 REALM_OBJECT_SERVER_VERSION=2.5.1 From 144732ee965f2d1922413dcc2b6747d878679d7a Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Fri, 13 Apr 2018 10:09:19 +0200 Subject: [PATCH 11/20] [2.2.20] Bump version --- CHANGELOG.md | 2 +- dependencies.list | 2 +- package.json | 2 +- src/RealmJS.xcodeproj/project.pbxproj | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7fdd28a..79d18a4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -X.Y.Z Release notes +2.2.20 Release notes (2018-4-13) ============================================================= ### Breaking changes * None. diff --git a/dependencies.list b/dependencies.list index 4a603450..eea139fd 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,5 +1,5 @@ PACKAGE_NAME=realm-js -VERSION=2.2.19 +VERSION=2.2.20 REALM_CORE_VERSION=5.1.2 REALM_SYNC_VERSION=2.2.17 REALM_OBJECT_SERVER_VERSION=2.5.1 diff --git a/package.json b/package.json index d7201ea7..eb0b1d00 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "realm", "description": "Realm is a mobile database: an alternative to SQLite and key-value stores", - "version": "2.2.19", + "version": "2.2.20", "license": "Apache-2.0", "homepage": "https://realm.io", "keywords": [ diff --git a/src/RealmJS.xcodeproj/project.pbxproj b/src/RealmJS.xcodeproj/project.pbxproj index 204922c1..d77654f6 100644 --- a/src/RealmJS.xcodeproj/project.pbxproj +++ b/src/RealmJS.xcodeproj/project.pbxproj @@ -961,7 +961,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.2.19; + CURRENT_PROJECT_VERSION = 2.2.20; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -1025,7 +1025,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.2.19; + CURRENT_PROJECT_VERSION = 2.2.20; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; From 72d10eb572bd474ee89795926855a82885332578 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 24 Apr 2018 23:11:54 -0700 Subject: [PATCH 12/20] Don't hang forever when the React tests fail to start (#1764) * Exclude unavailable simulator runtimes * Fix some warnings * Don't hang forever when the React tests fail to start `simctl launch --console` goes into an infinite loop if the app fails to launch successfully, so don't use --console and manually wait for it to exit. --- lib/notification-worker.js | 2 +- lib/notifier.js | 6 +++--- lib/worker.js | 2 +- scripts/test.sh | 14 ++++++++++++-- tests/js/session-tests.js | 8 ++++---- 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/lib/notification-worker.js b/lib/notification-worker.js index 84191b3b..5aa6b4ae 100644 --- a/lib/notification-worker.js +++ b/lib/notification-worker.js @@ -25,7 +25,7 @@ function nodeRequire(module) { return require_method(module); } -const Realm = require('.'); +const Realm = nodeRequire('.'); let impl; process.on('message', (m) => { diff --git a/lib/notifier.js b/lib/notifier.js index a6bc6dd4..0add6bf6 100644 --- a/lib/notifier.js +++ b/lib/notifier.js @@ -85,7 +85,7 @@ class FunctionListener { throw e; }); } -}; +} class OutOfProcListener { constructor(regex, regexStr, worker) { @@ -120,7 +120,7 @@ class OutOfProcListener { } this.worker.onchange(changes); } -}; +} class Listener { constructor(Sync, server, user) { @@ -231,7 +231,7 @@ class Listener { } this.initPromises = []; } -}; +} let listener; function addListener(server, user, regex, event, callback) { diff --git a/lib/worker.js b/lib/worker.js index 77a8f8bc..eec34c50 100644 --- a/lib/worker.js +++ b/lib/worker.js @@ -123,6 +123,6 @@ class Worker { const message = this._workQueue.shift(); worker.send(message); } -}; +} module.exports = Worker; diff --git a/scripts/test.sh b/scripts/test.sh index f4bd0784..4cfc3dfc 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -147,7 +147,17 @@ xctest() { echo "Launching application. (output is in $(pwd)/build/out.txt)" - xcrun simctl launch --console ${SIM_DEVICE_NAME} io.realm.$1 | tee $(pwd)/build/out.txt + testpid=$(xcrun simctl launch --stdout=$(pwd)/build/out.txt --stderr=$(pwd)/build/err.txt ${SIM_DEVICE_NAME} io.realm.$1 | grep -m1 -o '\d\+$') + tail -n +0 -f $(pwd)/build/out.txt & + stdoutpid=$! + tail -n +0 -f $(pwd)/build/err.txt & + stderrpid=$! + + # `kill -0` checks if a signal can be sent to the pid without actually doing so + while kill -0 $testpid 2> /dev/null; do sleep 1; done + + kill $stdoutpid + kill $stderrpid echo "Shuttting down ${SIM_DEVICE_NAME} simulator. (device is not deleted. you can use it to debug the app)" shutdown_ios_simulator @@ -171,7 +181,7 @@ setup_ios_simulator() { delete_ios_simulator >/dev/null 2>&1 #parse devices - IOS_RUNTIME=$(xcrun simctl list runtimes | grep -m1 -o 'com.apple.CoreSimulator.SimRuntime.iOS.*' | sed 's/[()]//g') + IOS_RUNTIME=$(xcrun simctl list runtimes | grep -v unavailable | grep -m1 -o 'com.apple.CoreSimulator.SimRuntime.iOS.*' | sed 's/[()]//g') echo using iOS Runtime ${IOS_RUNTIME} to create new simulator ${SIM_DEVICE_NAME} #create new test simulator diff --git a/tests/js/session-tests.js b/tests/js/session-tests.js index f6199335..e6f3970a 100644 --- a/tests/js/session-tests.js +++ b/tests/js/session-tests.js @@ -751,7 +751,7 @@ module.exports = { const realm = new Realm(config1); TestCase.assertFalse(realm.isClosed); realm.close(); - }; + } function __partialIsNotAllowed() { let config2 = { @@ -762,7 +762,7 @@ module.exports = { } }; TestCase.assertThrows(() => new Realm(config2)); - }; + } function shouldFail() { let config = { @@ -780,11 +780,11 @@ module.exports = { TestCase.assertEqual(realm.objects('Dog').length, 0); TestCase.assertThrows(function () { var subscription = realm.objects('Dog').filtered("name == 'Lassy 1'").subscribe(); } ); realm.close(); - }; + } function defaultRealmInvalidArguments() { TestCase.assertThrows(() => Realm.automaticSyncConfiguration('foo', 'bar')); // too many arguments - }; + } return runOutOfProcess(__dirname + '/partial-sync-api-helper.js', username, REALM_MODULE_PATH) From 032ee3d178681e66e6ae52d32b2b239ff8454fdd Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Wed, 25 Apr 2018 09:48:34 +0200 Subject: [PATCH 13/20] Updating change log (forgot in PR #1744). (#1755) * Updating change log (forgot in PR #1744). --- CHANGELOG.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 002d3a63..cad9dd63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ X.Y.Z Release notes ============================================================= +### Compatibility +* Sync protocol: 24 +* Server-side history format: 4 +* File format: 7 +* Realm Object Server: 3.0.0 or later + ### Breaking changes * None. @@ -8,9 +14,11 @@ X.Y.Z Release notes ### Bug fixes * Fixed logout error due to fetch body not being stringified (#1731). +* Added `Subscription` import to `browser/index.js` and register type converter (#1711). ### Internal -* None. +* Updated `scripts/test.sh` so it doesn't hang forever when the React tests fail to start (#1764). + 2.3.4 Release notes (2018-4-12) ============================================================= From 1c95abbff1502724be9362b0d019189356c011dd Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Wed, 25 Apr 2018 10:21:52 +0100 Subject: [PATCH 14/20] Add a certificate validation using Android Keystore for RN (#1761) * add a certificate validation using Android Keystore for RN --- .../java/io/realm/react/RealmReactModule.java | 16 ++ .../io/realm/react/RealmReactPackage.java | 16 ++ .../java/io/realm/react/util/SSLHelper.java | 152 ++++++++++++++++++ react-native/android/src/main/jni/Android.mk | 1 + .../io_realm_react_RealmReactModule.cpp | 32 ++++ src/android/jni_utils.cpp | 50 ++++++ src/android/jni_utils.hpp | 59 +++++++ src/js_sync.hpp | 37 ++++- 8 files changed, 361 insertions(+), 2 deletions(-) create mode 100644 react-native/android/src/main/java/io/realm/react/util/SSLHelper.java create mode 100644 src/android/jni_utils.cpp create mode 100644 src/android/jni_utils.hpp diff --git a/react-native/android/src/main/java/io/realm/react/RealmReactModule.java b/react-native/android/src/main/java/io/realm/react/RealmReactModule.java index f09f65ec..9b84da3f 100644 --- a/react-native/android/src/main/java/io/realm/react/RealmReactModule.java +++ b/react-native/android/src/main/java/io/realm/react/RealmReactModule.java @@ -1,3 +1,19 @@ +/* + * Copyright 2018 Realm Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.realm.react; import android.content.res.AssetManager; diff --git a/react-native/android/src/main/java/io/realm/react/RealmReactPackage.java b/react-native/android/src/main/java/io/realm/react/RealmReactPackage.java index 9fb66f9d..a722b059 100644 --- a/react-native/android/src/main/java/io/realm/react/RealmReactPackage.java +++ b/react-native/android/src/main/java/io/realm/react/RealmReactPackage.java @@ -1,3 +1,19 @@ +/* + * Copyright 2018 Realm Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package io.realm.react; import com.facebook.react.ReactPackage; diff --git a/react-native/android/src/main/java/io/realm/react/util/SSLHelper.java b/react-native/android/src/main/java/io/realm/react/util/SSLHelper.java new file mode 100644 index 00000000..df49dd72 --- /dev/null +++ b/react-native/android/src/main/java/io/realm/react/util/SSLHelper.java @@ -0,0 +1,152 @@ +/* + * Copyright 2018 Realm Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.realm.react.util; + +import android.util.Log; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import okhttp3.internal.tls.OkHostnameVerifier; + +public class SSLHelper { + private final static String TAG = "REALM SSLHelper"; + // Holds the certificate chain (per hostname). We need to keep the order of each certificate + // according to it's depth in the chain. The depth of the last + // certificate is 0. The depth of the first certificate is chain + // length - 1. + private static HashMap> ROS_CERTIFICATES_CHAIN; + + // The default Android Trust Manager which uses the default KeyStore to + // validate the certificate chain. + private static X509TrustManager TRUST_MANAGER; + + // Help transform a String PEM representation of the certificate, into + // X509Certificate format. + private static CertificateFactory CERTIFICATE_FACTORY; + + // From Sync implementation: + // A recommended way of using the callback function is to return true + // if preverify_ok = 1 and depth > 0, + // always check the host name if depth = 0, + // and use an independent verification step if preverify_ok = 0. + // + // Another possible way of using the callback is to collect all the + // ROS_CERTIFICATES_CHAIN until depth = 0, and present the entire chain for + // independent verification. + // + // In this implementation we use the second method, since it's more suitable for + // the underlying Java API we need to call to validate the certificate chain. + + public synchronized static boolean certificateVerifier(String serverAddress, String pemData, int depth) { + try { + if (ROS_CERTIFICATES_CHAIN == null) { + ROS_CERTIFICATES_CHAIN = new HashMap<>(); + TRUST_MANAGER = systemDefaultTrustManager(); + CERTIFICATE_FACTORY = CertificateFactory.getInstance("X.509"); + } + + if (!ROS_CERTIFICATES_CHAIN.containsKey(serverAddress)) { + ROS_CERTIFICATES_CHAIN.put(serverAddress, new ArrayList()); + } + + ROS_CERTIFICATES_CHAIN.get(serverAddress).add(pemData); + + if (depth == 0) { + // transform all PEM ROS_CERTIFICATES_CHAIN into Java X509 + // with respecting the order/depth provided from Sync. + List pemChain = ROS_CERTIFICATES_CHAIN.get(serverAddress); + int n = pemChain.size(); + X509Certificate[] chain = new X509Certificate[n]; + for (String pem : pemChain) { + // The depth of the last certificate is 0. + // The depth of the first certificate is chain length - 1. + chain[--n] = buildCertificateFromPEM(pem); + } + + // verify the entire chain + try { + TRUST_MANAGER.checkServerTrusted(chain, "RSA"); + // verify the hostname + boolean isValid = OkHostnameVerifier.INSTANCE.verify(serverAddress, chain[0]); + if (isValid) { + return true; + } else { + Log.e(TAG, "Can not verify the hostname for the host: " + serverAddress); + return false; + } + } catch (CertificateException e) { + Log.e(TAG, "Can not validate SSL chain certificate for the host: " + serverAddress, e); + return false; + } finally { + // don't keep the certificate chain in memory + ROS_CERTIFICATES_CHAIN.remove(serverAddress); + } + } else { + // return true, since the verification will happen for the entire chain + // when receiving the depth == 0 (host certificate) + return true; + } + } catch (Exception e) { + Log.e(TAG, "Error during certificate validation for host: " + serverAddress, e); + return false; + } + } + + // Credit OkHttp https://github.com/square/okhttp/blob/e5c84e1aef9572adb493197c1b6c4e882aca085b/okhttp/src/main/java/okhttp3/OkHttpClient.java#L270 + private static X509TrustManager systemDefaultTrustManager() { + try { + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( + TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init((KeyStore) null); + TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); + if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { + throw new IllegalStateException("Unexpected default trust managers:" + + Arrays.toString(trustManagers)); + } + return (X509TrustManager) trustManagers[0]; + } catch (GeneralSecurityException e) { + throw new AssertionError(); // The system has no TLS. Just give up. + } + } + + private static X509Certificate buildCertificateFromPEM(String pem) throws IOException, CertificateException { + InputStream stream = null; + try { + stream = new ByteArrayInputStream(pem.getBytes("UTF-8")); + return (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(stream); + } finally { + if (stream != null) { + stream.close(); + } + } + } +} diff --git a/react-native/android/src/main/jni/Android.mk b/react-native/android/src/main/jni/Android.mk index ce0554ca..a3d727c3 100644 --- a/react-native/android/src/main/jni/Android.mk +++ b/react-native/android/src/main/jni/Android.mk @@ -45,6 +45,7 @@ LOCAL_SRC_FILES += src/rpc.cpp LOCAL_SRC_FILES += src/jsc/jsc_init.cpp LOCAL_SRC_FILES += src/jsc/jsc_value.cpp LOCAL_SRC_FILES += src/android/io_realm_react_RealmReactModule.cpp +LOCAL_SRC_FILES += src/android/jni_utils.cpp LOCAL_SRC_FILES += src/android/jsc_override.cpp LOCAL_SRC_FILES += src/android/platform.cpp LOCAL_SRC_FILES += src/object-store/src/impl/collection_change_builder.cpp diff --git a/src/android/io_realm_react_RealmReactModule.cpp b/src/android/io_realm_react_RealmReactModule.cpp index e776bca0..78c4e730 100644 --- a/src/android/io_realm_react_RealmReactModule.cpp +++ b/src/android/io_realm_react_RealmReactModule.cpp @@ -23,17 +23,49 @@ #include "io_realm_react_RealmReactModule.h" #include "rpc.hpp" #include "platform.hpp" +#include "jni_utils.hpp" using namespace realm::rpc; +using namespace realm::jni_util; static RPCServer *s_rpc_server; extern bool realmContextInjected; +jclass ssl_helper_class; namespace realm { // set the AssetManager used to access bundled files within the APK void set_asset_manager(AAssetManager* assetManager); } +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) +{ + JNIEnv* env; + if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) { + return JNI_ERR; + } + else { + JniUtils::initialize(vm, JNI_VERSION_1_6); + } + + // We do lookup the class in this Thread, since FindClass sometimes fails + // when issued from the sync client thread + ssl_helper_class = reinterpret_cast(env->NewGlobalRef(env->FindClass("io/realm/react/util/SSLHelper"))); + + return JNI_VERSION_1_6; +} + +JNIEXPORT void JNI_OnUnload(JavaVM* vm, void*) +{ + JNIEnv* env; + if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) { + return; + } + else { + env->DeleteLocalRef(ssl_helper_class); + JniUtils::release(); + } +} + JNIEXPORT void JNICALL Java_io_realm_react_RealmReactModule_setDefaultRealmFileDirectory (JNIEnv *env, jclass, jstring fileDir, jobject javaAssetManager) { diff --git a/src/android/jni_utils.cpp b/src/android/jni_utils.cpp new file mode 100644 index 00000000..a9ea88da --- /dev/null +++ b/src/android/jni_utils.cpp @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Realm Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jni_utils.hpp" + +#include + +using namespace realm::jni_util; + +static std::unique_ptr s_instance; + +void JniUtils::initialize(JavaVM* vm, jint vm_version) noexcept +{ + s_instance = std::unique_ptr(new JniUtils(vm, vm_version)); +} + +void JniUtils::release() +{ + s_instance.release(); +} + +JNIEnv* JniUtils::get_env(bool attach_if_needed) +{ + JNIEnv* env; + if (s_instance->m_vm->GetEnv(reinterpret_cast(&env), s_instance->m_vm_version) != JNI_OK) { + if (attach_if_needed) { + jint ret = s_instance->m_vm->AttachCurrentThread(reinterpret_cast(&env), nullptr); + } + } + + return env; +} + +void JniUtils::detach_current_thread() +{ + s_instance->m_vm->DetachCurrentThread(); +} diff --git a/src/android/jni_utils.hpp b/src/android/jni_utils.hpp new file mode 100644 index 00000000..9c8869fc --- /dev/null +++ b/src/android/jni_utils.hpp @@ -0,0 +1,59 @@ +/* + * Copyright 2018 Realm Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef REALM_JNI_UTIL_JNI_UTILS_HPP +#define REALM_JNI_UTIL_JNI_UTILS_HPP + +#include + +#include + +namespace realm { +namespace jni_util { + +// Util functions for JNI. +class JniUtils { +public: + ~JniUtils() + { + } + + // Call this only once in JNI_OnLoad. + static void initialize(JavaVM* vm, jint vm_version) noexcept; + // Call this in JNI_OnUnload. + static void release(); + // When attach_if_needed is false, returns the JNIEnv if there is one attached to this thread. Assert if there is + // none. When attach_if_needed is true, try to attach and return a JNIEnv if necessary. + static JNIEnv* get_env(bool attach_if_needed = false); + // Detach the current thread from the JVM. Only required for C++ threads that where attached in the first place. + // Failing to do so is a resource leak. + static void detach_current_thread(); + +private: + JniUtils(JavaVM* vm, jint vm_version) noexcept + : m_vm(vm) + , m_vm_version(vm_version) + { + } + + JavaVM* m_vm; + jint m_vm_version; +}; + +} // namespace realm +} // namespace jni_util + +#endif // REALM_JNI_UTIL_JNI_UTILS_HPP diff --git a/src/js_sync.hpp b/src/js_sync.hpp index 36826965..501fc1a3 100644 --- a/src/js_sync.hpp +++ b/src/js_sync.hpp @@ -33,6 +33,14 @@ #include "realm/util/logger.hpp" #include "realm/util/uri.hpp" +#if REALM_ANDROID +#include +#include "./android/io_realm_react_RealmReactModule.h" +#include "./android/jni_utils.hpp" + +extern jclass ssl_helper_class; +#endif + namespace realm { namespace js { @@ -303,7 +311,6 @@ public: bool operator ()(const std::string& server_address, sync::Session::port_type server_port, const char* pem_data, size_t pem_size, int preverify_ok, int depth) { const std::string pem_certificate {pem_data, pem_size}; - { std::lock_guard lock {*m_mutex}; m_ssl_certificate_callback_done = false; @@ -824,7 +831,33 @@ void SyncClass::populate_sync_config(ContextType ctx, ObjectType realm_constr SSLVerifyCallbackSyncThreadFunctor ssl_verify_functor {ctx, Value::validated_to_function(ctx, ssl_verify_func)}; ssl_verify_callback = std::move(ssl_verify_functor); } - +#if REALM_ANDROID + // For React Native Android, if the user didn't define the ssl_verify_callback, we provide a default + // implementation for him, otherwise all SSL validation will fail, since the Sync client doesn't have + // access to the Android Keystore. + // This default implementation will perform a JNI call to invoke a Java method defined at the `SSLHelper` + // to perform the certificate verification. + else { + auto ssl_verify_functor = + [](const std::string server_address, realm::sync::Session::port_type server_port, + const char* pem_data, size_t pem_size, int preverify_ok, int depth) { + JNIEnv* env = realm::jni_util::JniUtils::get_env(true); + static jmethodID java_certificate_verifier = env->GetStaticMethodID(ssl_helper_class, "certificateVerifier", "(Ljava/lang/String;Ljava/lang/String;I)Z"); + jstring jserver_address = env->NewStringUTF(server_address.c_str()); + // deep copy the pem_data into a string so DeleteLocalRef delete the local reference not the original const char + std::string pem(pem_data, pem_size); + jstring jpem = env->NewStringUTF(pem.c_str()); + + bool isValid = env->CallStaticBooleanMethod(ssl_helper_class, java_certificate_verifier, + jserver_address, + jpem, depth) == JNI_TRUE; + env->DeleteLocalRef(jserver_address); + env->DeleteLocalRef(jpem); + return isValid; + }; + ssl_verify_callback = std::move(ssl_verify_functor); + } +#endif bool is_partial = false; ValueType partial_value = Object::get_property(ctx, sync_config_object, "partial"); if (!Value::is_undefined(ctx, partial_value)) { From b321808f4b2127e60855848272f051acb8d16ca6 Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Wed, 25 Apr 2018 10:23:47 +0100 Subject: [PATCH 15/20] Add password reset wrappers (#1699). (#1757) * Add password reset wrappers (#1699). --- CHANGELOG.md | 2 +- docs/sync.js | 49 +++++++++++++++++++++++++++++++ lib/index.d.ts | 8 +++++ lib/user-methods.js | 71 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cad9dd63..184a94fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ X.Y.Z Release notes * None. ### Enhancements -* None. +* Add password reset wrappers (#1699). ### Bug fixes * Fixed logout error due to fetch body not being stringified (#1731). diff --git a/docs/sync.js b/docs/sync.js index cd435ea5..0e3c02f6 100644 --- a/docs/sync.js +++ b/docs/sync.js @@ -270,6 +270,55 @@ class User { */ static register(server, username, password, callback) {} + /** + * Request a password reset email to be sent to a user's email. + * This will not throw an exception, even if the email doesn't belong to a Realm Object Server user. + * + * This can only be used for users who authenticated with the 'password' provider, and passed a valid email address as a username. + * + * @param {string} server - authentication server + * @param {string} email - The email that corresponds to the user's username. + * @return {Promise} A promise which is resolved when the request has been sent. + */ + static requestPasswordReset(server, email) {} + + /** + * Complete the password reset flow by using the reset token sent to the user's email as a one-time authorization token to change the password. + * + * By default, Realm Object Server will send a link to the user's email that will redirect to a webpage where they can enter their new password. + * If you wish to provide a native UX, you may wish to modify the password authentication provider to use a custom URL with deep linking, so you can + * open the app, extract the token, and navigate to a view that allows to change the password within the app. + * + * @param {string} server - authentication server + * @param {string} reset_token - The token that was sent to the user's email address. + * @param {string} new_password - The user's new password. + * @return {Promise} A promise which is resolved when the request has been sent. + */ + static completePasswordReset(server, reset_token, new_password) {} + + /** + * Request an email confirmation email to be sent to a user's email. + * This will not throw an exception, even if the email doesn't belong to a Realm Object Server user. + * + * @param {string} server - authentication server + * @param {string} email - The email that corresponds to the user's username. + * @return {Promise} A promise which is resolved when the request has been sent. + */ + static requestEmailConfirmation(server, email) {} + + /** + * Complete the email confirmation flow by using the confirmation token sent to the user's email as a one-time authorization token to confirm their email. + * + * By default, Realm Object Server will send a link to the user's email that will redirect to a webpage where they can enter their new password. + * If you wish to provide a native UX, you may wish to modify the password authentication provider to use a custom URL with deep linking, so you can + * open the app, extract the token, and navigate to a view that allows to confirm the email within the app. + * + * @param {string} server - authentication server + * @param {string} confirmation_token - The token that was sent to the user's email address. + * @return {Promise} A promise which is resolved when the request has been sent. + */ + static confirmEmail(server, confirmation_token) {} + /** * Create an admin user for the given authentication server with an existing token * @param {string} adminToken - existing admin token diff --git a/lib/index.d.ts b/lib/index.d.ts index 664168e4..7f80ad01 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -296,6 +296,14 @@ declare namespace Realm.Sync { static registerWithProvider(server: string, options: { provider: string, providerToken: string, userInfo: any }, callback: (error: Error | null, user: User | null) => void): void; static registerWithProvider(server: string, options: { provider: string, providerToken: string, userInfo: any }): Promise; + static requestPasswordReset(server: string, email: string): Promise; + + static completePasswordReset(server:string, reset_token:string, new_password:string): Promise; + + static requestEmailConfirmation(server:string, email:string): Promise; + + static confirmEmail(server:string, confirmation_token:string): Promise; + authenticate(server: string, provider: string, options: any): Promise; logout(): void; openManagementRealm(): Realm; diff --git a/lib/user-methods.js b/lib/user-methods.js index a15e31ae..f83b2a86 100644 --- a/lib/user-methods.js +++ b/lib/user-methods.js @@ -275,6 +275,32 @@ function _authenticate(userConstructor, server, json, callback) { } } +function _updateAccount(userConstructor, server, json) { + const url = append_url(server, 'auth/password/updateAccount'); + const options = { + method: 'POST', + body: JSON.stringify(json), + headers: postHeaders, + open_timeout: 5000 + }; + + return performFetch(url, options) + .then((response) => { + const contentType = response.headers.get('Content-Type'); + if (contentType.indexOf('application/json') === -1) { + return response.text().then((body) => { + throw new AuthError({ + title: `Could not update user account: Realm Object Server didn't respond with valid JSON`, + body, + }); + }); + } + if (!response.ok) { + return response.json().then((body) => Promise.reject(new AuthError(body))); + } + }); +} + const staticMethods = { get current() { const allUsers = this.all; @@ -379,6 +405,51 @@ const staticMethods = { return _authenticate(this, server, json) }, + requestPasswordReset(server, email) { + checkTypes(arguments, ['string', 'string']); + const json = { + provider_id: email, + data: { action: 'reset_password' } + }; + + return _updateAccount(this, server, json); + }, + + completePasswordReset(server, reset_token, new_password) { + checkTypes(arguments, ['string', 'string']); + const json = { + data: { + action: 'complete_reset', + token: reset_token, + new_password: new_password + } + }; + + return _updateAccount(this, server, json); + }, + + requestEmailConfirmation(server, email) { + checkTypes(arguments, ['string', 'string']); + const json = { + provider_id: email, + data: { action: 'request_email_confirmation' } + }; + + return _updateAccount(this, server, json); + }, + + confirmEmail(server, confirmation_token) { + checkTypes(arguments, ['string', 'string']); + const json = { + data: { + action: 'confirm_email', + token: confirmation_token + } + }; + + return _updateAccount(this, server, json); + }, + _refreshAccessToken: refreshAccessToken, }; From 4d0cccb8e5fff703a798e62b73c10d3c9c7a758d Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Wed, 25 Apr 2018 12:54:25 +0200 Subject: [PATCH 16/20] [2.3.5] Bump version --- CHANGELOG.md | 5 +++-- package.json | 2 +- src/RealmJS.xcodeproj/project.pbxproj | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 184a94fe..d9179ad8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -X.Y.Z Release notes +2.3.5 Release notes (2018-4-25) ============================================================= ### Compatibility * Sync protocol: 24 @@ -10,7 +10,8 @@ X.Y.Z Release notes * None. ### Enhancements -* Add password reset wrappers (#1699). +* Added password reset wrappers (#1699). +* Added a certificate validation using Android Keystore for RN (#1761). ### Bug fixes * Fixed logout error due to fetch body not being stringified (#1731). diff --git a/package.json b/package.json index b065ba7e..8a6ac59f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "realm", "description": "Realm is a mobile database: an alternative to SQLite and key-value stores", - "version": "2.3.4", + "version": "2.3.5", "license": "Apache-2.0", "homepage": "https://realm.io", "keywords": [ diff --git a/src/RealmJS.xcodeproj/project.pbxproj b/src/RealmJS.xcodeproj/project.pbxproj index 55c00be9..bfbedffe 100644 --- a/src/RealmJS.xcodeproj/project.pbxproj +++ b/src/RealmJS.xcodeproj/project.pbxproj @@ -969,7 +969,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.3.4; + CURRENT_PROJECT_VERSION = 2.3.5; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -1033,7 +1033,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.3.4; + CURRENT_PROJECT_VERSION = 2.3.5; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; From 2eccaac4315e97ecb55676ff9effa9db9d38e9d2 Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Thu, 26 Apr 2018 11:38:24 +0200 Subject: [PATCH 17/20] Kneth/rn logout (#1766) * `logout()` is implemented in JS and RN debugging must know of `_logout()` instead. --- CHANGELOG.md | 21 +++++++++++++++++++++ lib/browser/user.js | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9179ad8..dd90b459 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,24 @@ +X.Y.Z Release notes +============================================================= +### Compatibility +* Sync protocol: 24 +* Server-side history format: 4 +* File format: 7 +* Realm Object Server: 3.0.0 or later + +### Breaking changes +* None. + +### Enhancements +* None. + +### Bug fixes +* Fixed call to `logout()` when debugging React Native apps (#1744). + +### Internal +* None. + + 2.3.5 Release notes (2018-4-25) ============================================================= ### Compatibility diff --git a/lib/browser/user.js b/lib/browser/user.js index 85f34ba1..25627353 100644 --- a/lib/browser/user.js +++ b/lib/browser/user.js @@ -42,7 +42,7 @@ export default class User { } createMethods(User.prototype, objectTypes.USER, [ - 'logout', + '_logout', '_sessionForOnDiskPath' ]); From ad1962b02bd7cc75b037673de0dc335ab45dbac6 Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Thu, 26 Apr 2018 11:45:38 +0200 Subject: [PATCH 18/20] [2.4.0] Bump version --- CHANGELOG.md | 24 ++---------------------- dependencies.list | 2 +- package.json | 2 +- src/RealmJS.xcodeproj/project.pbxproj | 4 ++-- 4 files changed, 6 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd90b459..2c4745e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,25 +1,4 @@ -X.Y.Z Release notes -============================================================= -### Compatibility -* Sync protocol: 24 -* Server-side history format: 4 -* File format: 7 -* Realm Object Server: 3.0.0 or later - -### Breaking changes -* None. - -### Enhancements -* None. - -### Bug fixes -* Fixed call to `logout()` when debugging React Native apps (#1744). - -### Internal -* None. - - -2.3.5 Release notes (2018-4-25) +2.4.0 Release notes (2018-4-26) ============================================================= ### Compatibility * Sync protocol: 24 @@ -37,6 +16,7 @@ X.Y.Z Release notes ### Bug fixes * Fixed logout error due to fetch body not being stringified (#1731). * Added `Subscription` import to `browser/index.js` and register type converter (#1711). +* Fixed call to `logout()` when debugging React Native apps (#1744). ### Internal * Updated `scripts/test.sh` so it doesn't hang forever when the React tests fail to start (#1764). diff --git a/dependencies.list b/dependencies.list index a55b1843..55ac5c05 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,5 +1,5 @@ PACKAGE_NAME=realm-js -VERSION=2.3.4 +VERSION=2.4.0 REALM_CORE_VERSION=5.4.0 REALM_SYNC_VERSION=3.0.0 REALM_OBJECT_SERVER_VERSION=3.0.0 diff --git a/package.json b/package.json index 8a6ac59f..fa0b1379 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "realm", "description": "Realm is a mobile database: an alternative to SQLite and key-value stores", - "version": "2.3.5", + "version": "2.4.0", "license": "Apache-2.0", "homepage": "https://realm.io", "keywords": [ diff --git a/src/RealmJS.xcodeproj/project.pbxproj b/src/RealmJS.xcodeproj/project.pbxproj index bfbedffe..7ca13e1e 100644 --- a/src/RealmJS.xcodeproj/project.pbxproj +++ b/src/RealmJS.xcodeproj/project.pbxproj @@ -969,7 +969,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.3.5; + CURRENT_PROJECT_VERSION = 2.4.0; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -1033,7 +1033,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 2.3.5; + CURRENT_PROJECT_VERSION = 2.4.0; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; From 5e64d04c192761270ced96d0ab1437a07b6c5e90 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Tue, 1 May 2018 10:26:59 +0200 Subject: [PATCH 19/20] Update sync.js (#1773) --- docs/sync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sync.js b/docs/sync.js index 0e3c02f6..8afcfddd 100644 --- a/docs/sync.js +++ b/docs/sync.js @@ -640,7 +640,7 @@ class Worker { */ class Adapter { /** - * Create a new Adapter to moitor and process changes made across multiple Realms + * Create a new Adapter to monitor and process changes made across multiple Realms * @param {string} localPath - the local path where realm files are stored * @param {string} serverUrl - the sync server to listen to * @param {SyncUser} adminUser - an admin user obtained by calling `new Realm.Sync.User.adminUser` From 4f65e057eb7970958852e8daa37479f48be676a2 Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Mon, 7 May 2018 10:09:22 +0200 Subject: [PATCH 20/20] Update to sync 3.3.0 (#1778) * Updating sync and core * Simplying linking on node.js binding. * Adapting to new distribution packages of core. --- CHANGELOG.md | 22 ++++++++++++++++++++++ dependencies.list | 4 ++-- realm.gypi | 9 ++------- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b218172..8386d8eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +X.Y.Z Release notes +============================================================= +### Compatibility +* Sync protocol: 24 +* Server-side history format: 4 +* File format: 7 +* Realm Object Server: 3.0.0 or later + +### Breaking changes +* None. + +### Enhancements +* None. + +### Bug fixes +* None. + +### Internal +* Updated to Relm Sync 3.3.0. +* Updated to Realm Core 5.6.0. + + 2.4.0 Release notes (2018-4-26) ============================================================= ### Compatibility diff --git a/dependencies.list b/dependencies.list index f85f19fc..a0c22ddf 100644 --- a/dependencies.list +++ b/dependencies.list @@ -1,6 +1,6 @@ PACKAGE_NAME=realm-js VERSION=2.4.0 -REALM_CORE_VERSION=5.4.0 -REALM_SYNC_VERSION=3.0.0 +REALM_CORE_VERSION=5.6.0 +REALM_SYNC_VERSION=3.3.0 REALM_OBJECT_SERVER_VERSION=3.0.0 diff --git a/realm.gypi b/realm.gypi index 45aa4dfb..792b0518 100644 --- a/realm.gypi +++ b/realm.gypi @@ -200,13 +200,7 @@ "type": "none", "dependencies": [ "realm-core" ], "link_settings": { - "conditions": [ - ["OS=='win'", { - "libraries": [ "-lrealm-sync<(debug_library_suffix)" ] - }, { - "libraries": [ "-lrealm-sync-node<(debug_library_suffix)" ] - }] - ] + "libraries": [ "-lrealm-sync<(debug_library_suffix)" ], }, "all_dependent_settings": { "defines": [ "REALM_ENABLE_SYNC=1" ] @@ -259,6 +253,7 @@ "include_dirs": [ "<(vendor_dir)/include" ], "library_dirs": [ "<(vendor_dir)/lib", + "<(vendor_dir)/lib64", "<(vendor_dir)/osx" ] },