Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

application login user #469

Merged
merged 63 commits into from
Apr 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
453e018
Rollback Dart_WeakHandle finalizer hack
nielsenko Mar 14, 2022
8430d42
Use dart main/flutter beta in github actions.
nielsenko Mar 22, 2022
e847de2
Add dart specific support for realm_http_transport_new
nielsenko Mar 16, 2022
6a5c9c4
Wire up realm_core
nielsenko Mar 18, 2022
fca9182
Apply suggestions from code review
nielsenko Mar 28, 2022
435e484
Copy all info from realm_http_request before starting async request
nielsenko Mar 28, 2022
d7207d9
Added ApplicationConfiguration
nielsenko Mar 18, 2022
ea8d7ef
Added Application class with async logIn method (includes stubs for U…
nielsenko Mar 25, 2022
a54b1a8
Use common GCHandle class for userdata on all callbacks
nielsenko Mar 30, 2022
6ae70e2
Support hard gc handles as well, as suggested by Yavor. Ie. handles t…
nielsenko Apr 7, 2022
c81e0c0
Backport to dart 2.16 where we have to work around a finalization iss…
nielsenko Apr 1, 2022
6899dc8
Add support for http_transport
nielsenko Mar 18, 2022
9a17d45
Added ApplicationConfiguration
nielsenko Mar 18, 2022
73e2e4c
Update docs on public interface
nielsenko Apr 7, 2022
0baa62f
Address PR feedback
nielsenko Apr 11, 2022
20e95af
Added Application class with async logIn method (includes stubs for U…
nielsenko Apr 8, 2022
d63f205
Add testWithBass function
nielsenko Apr 8, 2022
0cdf4b7
Merge branch 'master' into realm_app_config
desistefanova Apr 11, 2022
b9cc163
Update CHANGELOG.md
desistefanova Apr 11, 2022
8448ffd
Merge branch 'realm_app_config' into realm_app
desistefanova Apr 11, 2022
7ff02ef
Commit after merge
desistefanova Apr 11, 2022
fc5e481
Fixes after merge
desistefanova Apr 11, 2022
c1cb35e
Merge branch 'realm_app'
desistefanova Apr 12, 2022
e07be97
Fixes after merge
desistefanova Apr 12, 2022
b7ddc96
Remove user and login
desistefanova Apr 12, 2022
938a168
size of handles
desistefanova Apr 12, 2022
d447fe0
Set size of handles
desistefanova Apr 12, 2022
ef644c5
workflow chanel = stable
desistefanova Apr 12, 2022
a132bf4
Delete realm_dart_http_transport
desistefanova Apr 12, 2022
4e15ea7
remove import dart:async from tests
desistefanova Apr 12, 2022
c453fde
Merge branch 'master' into realm_app
desistefanova Apr 12, 2022
348ed3e
Fixes after merge
desistefanova Apr 12, 2022
2778ff2
Fix after merge
desistefanova Apr 12, 2022
a359038
Merge branch 'master' into realm_app
desistefanova Apr 12, 2022
792589b
Merge branch 'realm_app' into login_user
desistefanova Apr 12, 2022
6f28a22
Fix after merge
desistefanova Apr 12, 2022
1489eee
Merge branch 'master' into realm_app
desistefanova Apr 12, 2022
9fd8fec
Fix after merge
desistefanova Apr 12, 2022
07be0ae
Fix after merge
desistefanova Apr 12, 2022
b85cbb4
Merge branch 'realm_app' into login_user
desistefanova Apr 12, 2022
18ec3ca
Updarte CHANGELOG.md
desistefanova Apr 12, 2022
a69d013
Merge branch 'master' into login_user
blagoev Apr 13, 2022
60b665c
fix build
blagoev Apr 13, 2022
4e26d96
rename method
blagoev Apr 13, 2022
b94d62c
fix login invocation
blagoev Apr 13, 2022
bad719b
fix GC hints
blagoev Apr 13, 2022
333b99d
[test] build in debug
blagoev Apr 13, 2022
e8aa395
application holds the HttpTransport, AppConfig and SyncClient handles
blagoev Apr 17, 2022
5f3ace8
Merge branch 'master' into login_user
blagoev Apr 17, 2022
9fc1e1b
support weak and persistent handles
blagoev Apr 20, 2022
0ed9ada
add api doc
blagoev Apr 20, 2022
a94f222
add user api doc
blagoev Apr 20, 2022
ab1f03e
revert build type for linux
blagoev Apr 20, 2022
bcbc522
add ctor api doc
blagoev Apr 20, 2022
d8effa6
remove dead arg
blagoev Apr 20, 2022
5a1523e
use named arg
blagoev Apr 21, 2022
ef5e89d
rename methods
blagoev Apr 21, 2022
8c0deb4
use string skip if url not present in test env
blagoev Apr 21, 2022
b37247d
move creation of httpTransportHandle, appConfigHandle and sycnClientC…
blagoev Apr 21, 2022
9c7127d
rename TO BAAS
blagoev Apr 21, 2022
7cc27d0
rename to BAAS
blagoev Apr 21, 2022
ec217bb
use non async login method
blagoev Apr 21, 2022
6392968
set skip to error if url is null
blagoev Apr 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ x.x.x Release notes (yyyy-MM-dd)
* Support should realm compact on open callback `Configuration.shouldCompactCallback` as option when configuring a Realm to determine if it should be compacted before being returned. ([#466](https://github.com/realm/realm-dart/pull/466/))
* Support ObjectId type. ([#468](https://github.com/realm/realm-dart/pull/468))
* Support Uuid type. ([#470](https://github.com/realm/realm-dart/pull/470))
* Support application login. ([#469](https://github.com/realm/realm-dart/pull/469/))

### Fixed
* Fixed an issue that would result in the wrong transaction being rolled back if you start a write transaction inside a write transaction. ([#442](https://github.com/realm/realm-dart/issues/442))
Expand Down
15 changes: 14 additions & 1 deletion lib/src/application.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import 'dart:io';
import 'package:meta/meta.dart';
import 'native/realm_core.dart';
import 'credentials.dart';
import 'user.dart';
import 'configuration.dart';

/// Specify if and how to persists user objects.
Expand All @@ -36,6 +38,7 @@ enum MetadataPersistenceMode {
@immutable

/// A class exposing configuration options for an [Application]
/// {@category Application}
class ApplicationConfiguration {
/// The [appId] is the unique id that identifies the Realm application.
final String appId;
Expand Down Expand Up @@ -108,13 +111,23 @@ class ApplicationConfiguration {
/// The [Application]] can be used to
/// * Register uses and perform various user-related operations through authentication providers
/// * Synchronize data between the local device and a remote Realm App with Synchronized Realms
/// {@category Application}
class Application {
final AppHandle _handle;
final ApplicationConfiguration configuration;

Application(this.configuration) : _handle = realmCore.getApp(configuration);
/// Create an app with a particular [AppConfiguration]
Application(this.configuration) :
_handle = realmCore.getApp(configuration);

/// Logs in a user with the given credentials.
Future<User> logIn(Credentials credentials) async {
var userHandle = await realmCore.logIn(this, credentials);
return UserInternal.create(userHandle);
}
}

/// @nodoc
extension ApplicationInternal on Application {
AppHandle get handle => _handle;
}
62 changes: 52 additions & 10 deletions lib/src/native/realm_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7449,34 +7449,76 @@ class RealmLibrary {
late final _realm_delete_finalizable = _realm_delete_finalizablePtr
.asFunction<void Function(Dart_FinalizableHandle, Object)>();

ffi.Pointer<ffi.Void> object_to_gc_handle(
ffi.Pointer<ffi.Void> object_to_weak_handle(
Object handle,
) {
return _object_to_gc_handle(
return _object_to_weak_handle(
handle,
);
}

late final _object_to_gc_handlePtr =
late final _object_to_weak_handlePtr =
_lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Handle)>>(
'object_to_gc_handle');
late final _object_to_gc_handle = _object_to_gc_handlePtr
'object_to_weak_handle');
late final _object_to_weak_handle = _object_to_weak_handlePtr
.asFunction<ffi.Pointer<ffi.Void> Function(Object)>();

Object gc_handle_to_object(
Object weak_handle_to_object(
ffi.Pointer<ffi.Void> handle,
) {
return _gc_handle_to_object(
return _weak_handle_to_object(
handle,
);
}

late final _gc_handle_to_objectPtr =
late final _weak_handle_to_objectPtr =
_lookup<ffi.NativeFunction<ffi.Handle Function(ffi.Pointer<ffi.Void>)>>(
'gc_handle_to_object');
late final _gc_handle_to_object = _gc_handle_to_objectPtr
'weak_handle_to_object');
late final _weak_handle_to_object = _weak_handle_to_objectPtr
.asFunction<Object Function(ffi.Pointer<ffi.Void>)>();

ffi.Pointer<ffi.Void> object_to_persistent_handle(
Object handle,
) {
return _object_to_persistent_handle(
handle,
);
}

late final _object_to_persistent_handlePtr =
_lookup<ffi.NativeFunction<ffi.Pointer<ffi.Void> Function(ffi.Handle)>>(
'object_to_persistent_handle');
late final _object_to_persistent_handle = _object_to_persistent_handlePtr
.asFunction<ffi.Pointer<ffi.Void> Function(Object)>();

Object persistent_handle_to_object(
ffi.Pointer<ffi.Void> handle,
) {
return _persistent_handle_to_object(
handle,
);
}

late final _persistent_handle_to_objectPtr =
_lookup<ffi.NativeFunction<ffi.Handle Function(ffi.Pointer<ffi.Void>)>>(
'persistent_handle_to_object');
late final _persistent_handle_to_object = _persistent_handle_to_objectPtr
.asFunction<Object Function(ffi.Pointer<ffi.Void>)>();

void delete_persistent_handle(
ffi.Pointer<ffi.Void> handle,
) {
return _delete_persistent_handle(
handle,
);
}

late final _delete_persistent_handlePtr =
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>(
'delete_persistent_handle');
late final _delete_persistent_handle = _delete_persistent_handlePtr
.asFunction<void Function(ffi.Pointer<ffi.Void>)>();

ffi.Pointer<realm_scheduler_t> realm_dart_create_scheduler(
int isolateId,
int port,
Expand Down
91 changes: 70 additions & 21 deletions lib/src/native/realm_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,13 @@ class _RealmCore {
static _RealmCore? _instance;
late final int isolateKey;

late final Pointer<NativeFunction<Void Function(Pointer<Void>)>> _deletePersistentHandlePtr;

_RealmCore._() {
final lib = initRealm();
_realmLib = RealmLibrary(lib);

_deletePersistentHandlePtr = lib.lookup<NativeFunction<Void Function(Pointer<Void>)>>('delete_persistent_handle');
}

factory _RealmCore() {
Expand Down Expand Up @@ -164,12 +168,13 @@ class _RealmCore {
}

if (config.initialDataCallback != null) {
_realmLib.realm_config_set_data_initialization_function(configHandle._pointer, Pointer.fromFunction(initial_data_callback, FALSE), config.toGCHandle());
_realmLib.realm_config_set_data_initialization_function(
configHandle._pointer, Pointer.fromFunction(initial_data_callback, FALSE), config.toWeakHandle());
}

if (config.shouldCompactCallback != null) {
_realmLib.realm_config_set_should_compact_on_launch_function(
configHandle._pointer, Pointer.fromFunction(should_compact_callback, 0), config.toGCHandle());
configHandle._pointer, Pointer.fromFunction(should_compact_callback, 0), config.toWeakHandle());
}

return configHandle;
Expand Down Expand Up @@ -609,7 +614,7 @@ class _RealmCore {
RealmNotificationTokenHandle subscribeResultsNotifications(RealmResultsHandle handle, NotificationsController controller, SchedulerHandle schedulerHandle) {
final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_results_add_notification_callback(
handle._pointer,
controller.toGCHandle(),
controller.toWeakHandle(),
nullptr,
nullptr,
Pointer.fromFunction(collection_change_callback),
Expand All @@ -623,7 +628,7 @@ class _RealmCore {
RealmNotificationTokenHandle subscribeListNotifications(RealmListHandle handle, NotificationsController controller, SchedulerHandle schedulerHandle) {
final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_list_add_notification_callback(
handle._pointer,
controller.toGCHandle(),
controller.toWeakHandle(),
nullptr,
nullptr,
Pointer.fromFunction(collection_change_callback),
Expand All @@ -637,7 +642,7 @@ class _RealmCore {
RealmNotificationTokenHandle subscribeObjectNotifications(RealmObjectHandle handle, NotificationsController controller, SchedulerHandle schedulerHandle) {
final pointer = _realmLib.invokeGetPointer(() => _realmLib.realm_object_add_notification_callback(
handle._pointer,
controller.toGCHandle(),
controller.toWeakHandle(),
nullptr,
nullptr,
Pointer.fromFunction(object_change_callback),
Expand All @@ -663,7 +668,7 @@ class _RealmCore {
});
}

AppConfigHandle createAppConfig(ApplicationConfiguration configuration, RealmHttpTransportHandle httpTransport) {
AppConfigHandle _createAppConfig(ApplicationConfiguration configuration, RealmHttpTransportHandle httpTransport) {
return using((arena) {
final app_id = configuration.appId.toUtf8Ptr(arena);
final handle = AppConfigHandle._(_realmLib.realm_app_config_new(app_id, httpTransport._pointer));
Expand Down Expand Up @@ -703,10 +708,10 @@ class _RealmCore {
});
}

RealmHttpTransportHandle createHttpTransport(HttpClient httpClient) {
RealmHttpTransportHandle _createHttpTransport(HttpClient httpClient) {
return RealmHttpTransportHandle._(_realmLib.realm_http_transport_new(
Pointer.fromFunction(request_callback),
httpClient.toGCHandle(),
httpClient.toWeakHandle(),
nullptr,
));
}
Expand Down Expand Up @@ -805,12 +810,13 @@ class _RealmCore {
responseRef.headers = arena<realm_http_header>(headerCnt);
responseRef.num_headers = headerCnt;

int index = 0;
response.headers.forEach((name, values) {
int idx = 0;
for (final value in values) {
final headerRef = responseRef.headers.elementAt(idx).ref;
final headerRef = responseRef.headers.elementAt(index).ref;
headerRef.name = name.toUtf8Ptr(arena);
headerRef.value = value.toUtf8Ptr(arena);
index++;
}
});

Expand All @@ -828,7 +834,7 @@ class _RealmCore {
});
}

SyncClientConfigHandle createSyncClientConfig(ApplicationConfiguration configuration) {
SyncClientConfigHandle _createSyncClientConfig(ApplicationConfiguration configuration) {
return using((arena) {
final handle = SyncClientConfigHandle._(_realmLib.realm_sync_client_config_new());

Expand All @@ -844,11 +850,46 @@ class _RealmCore {
}

AppHandle getApp(ApplicationConfiguration configuration) {
final httpTransport = createHttpTransport(configuration.httpClient);
final appConfig = createAppConfig(configuration, httpTransport);
final syncClientConfig = createSyncClientConfig(configuration);
final realm_app = _realmLib.invokeGetPointer(() => _realmLib.realm_app_get(appConfig._pointer, syncClientConfig._pointer));
return AppHandle._(realm_app);
final httpTransportHandle = _createHttpTransport(configuration.httpClient);
final appConfigHandle = _createAppConfig(configuration, httpTransportHandle);
final syncClientConfigHandle = _createSyncClientConfig(configuration);
final realmAppPtr = _realmLib.invokeGetPointer(() => _realmLib.realm_app_get(appConfigHandle._pointer, syncClientConfigHandle._pointer));
return AppHandle._(realmAppPtr);
}

static void _logInCallback(Pointer<Void> userdata, Pointer<realm_user> user, Pointer<realm_app_error> error) {
final Completer<UserHandle>? completer = userdata.toObject(isPersistent: true);
if (completer == null) {
return;
}

if (error != nullptr) {
final message = error.ref.message.cast<Utf8>().toDartString();
completer.completeError(RealmException(message));
return;
}

var userClone = _realmLib.realm_clone(user.cast());
if (userClone == nullptr) {
completer.completeError(RealmException("Error while cloning login data"));
return;
}

completer.complete(UserHandle._(userClone.cast()));
}

Future<UserHandle> logIn(Application application, Credentials credentials) {
final completer = Completer<UserHandle>();
_realmLib.invokeGetBool(
() => _realmLib.realm_app_log_in_with_credentials(
application.handle._pointer,
credentials.handle._pointer,
Pointer.fromFunction(_logInCallback),
completer.toPersistentHandle(),
_deletePersistentHandlePtr,
),
"Login failed");
return completer.future;
}
}

Expand Down Expand Up @@ -925,7 +966,7 @@ class RealmQueryHandle extends Handle<realm_query> {

class RealmNotificationTokenHandle extends Handle<realm_notification_token> {
bool released = false;
RealmNotificationTokenHandle._(Pointer<realm_notification_token> pointer) : super(pointer, 1 << 32);
RealmNotificationTokenHandle._(Pointer<realm_notification_token> pointer) : super(pointer, 32);

void release() {
if (released) {
Expand Down Expand Up @@ -966,6 +1007,10 @@ class AppHandle extends Handle<realm_app> {
AppHandle._(Pointer<realm_app> pointer) : super(pointer, 16);
}

class UserHandle extends Handle<realm_user> {
UserHandle._(Pointer<realm_user> pointer) : super(pointer, 24);
}

extension on List<int> {
Pointer<Int8> toInt8Ptr(Allocator allocator) {
return toUint8Ptr(allocator).cast();
Expand Down Expand Up @@ -1123,10 +1168,10 @@ extension on Pointer<IntPtr> {
}

extension on Pointer<Void> {
T? toObject<T extends Object>() {
T? toObject<T extends Object>({bool isPersistent = false}) {
assert(this != nullptr, "Pointer<Void> is null");

final object = _realmLib.gc_handle_to_object(this);
Object object = isPersistent ? _realmLib.persistent_handle_to_object(this) : _realmLib.weak_handle_to_object(this);
blagoev marked this conversation as resolved.
Show resolved Hide resolved

assert(object is T, "$T expected");
if (object is! T) {
Expand All @@ -1138,8 +1183,12 @@ extension on Pointer<Void> {
}

extension on Object {
Pointer<Void> toGCHandle() {
return _realmLib.object_to_gc_handle(this);
Pointer<Void> toWeakHandle() {
return _realmLib.object_to_weak_handle(this);
}

Pointer<Void> toPersistentHandle() {
return _realmLib.object_to_persistent_handle(this);
}
}

Expand Down
1 change: 1 addition & 0 deletions lib/src/realm_class.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export 'realm_object.dart' show RealmEntity, RealmException, RealmObject, RealmO
export 'realm_property.dart';
export 'results.dart' show RealmResults, RealmResultsChanges;
export 'credentials.dart' show Credentials, AuthProvider;
export 'user.dart' show User;

/// A [Realm] instance represents a `Realm` database.
///
Expand Down
36 changes: 36 additions & 0 deletions lib/src/user.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2022 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.
//
////////////////////////////////////////////////////////////////////////////////

import 'native/realm_core.dart';

/// This class represents a user in a MongoDB Realm app.
/// A user can log in to the server and, if access is granted, it is possible to synchronize the local Realm to MongoDB.
/// Moreover, synchronization is halted when the user is logged out. It is possible to persist a user. By retrieving a user, there is no need to log in again.
/// Persisting a user between sessions, the user's credentials are stored
/// locally on the device, and should be treated as sensitive data.
/// {@category Application}
class User {
final UserHandle _handle;

User._(this._handle);
}

/// @nodoc
extension UserInternal on User {
static User create(UserHandle handle) => User._(handle);
}
Loading