123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683 |
- ////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2016 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 "RLMSyncUser_Private.hpp"
- #import "RLMJSONModels.h"
- #import "RLMNetworkClient.h"
- #import "RLMRealmConfiguration+Sync.h"
- #import "RLMRealmConfiguration_Private.hpp"
- #import "RLMRealmUtil.hpp"
- #import "RLMResults_Private.hpp"
- #import "RLMSyncConfiguration.h"
- #import "RLMSyncConfiguration_Private.hpp"
- #import "RLMSyncManager_Private.h"
- #import "RLMSyncPermissionResults.h"
- #import "RLMSyncPermission_Private.hpp"
- #import "RLMSyncSessionRefreshHandle.hpp"
- #import "RLMSyncSession_Private.hpp"
- #import "RLMSyncUtil_Private.hpp"
- #import "RLMUtil.hpp"
- #import "sync/sync_manager.hpp"
- #import "sync/sync_session.hpp"
- #import "sync/sync_user.hpp"
- using namespace realm;
- using ConfigMaker = std::function<Realm::Config(std::shared_ptr<SyncUser>, std::string)>;
- namespace {
- std::function<void(Results, std::exception_ptr)> RLMWrapPermissionResultsCallback(RLMPermissionResultsBlock callback) {
- return [callback](Results results, std::exception_ptr ptr) {
- if (ptr) {
- NSError *error = translateSyncExceptionPtrToError(std::move(ptr), RLMPermissionActionTypeGet);
- REALM_ASSERT(error);
- callback(nil, error);
- } else {
- // Finished successfully
- callback([[RLMSyncPermissionResults alloc] initWithResults:std::move(results)], nil);
- }
- };
- }
- NSString *tildeSubstitutedPathForRealmURL(NSURL *url, NSString *identity) {
- return [[url path] stringByReplacingOccurrencesOfString:@"~" withString:identity];
- }
- }
- void CocoaSyncUserContext::register_refresh_handle(const std::string& path, RLMSyncSessionRefreshHandle *handle)
- {
- REALM_ASSERT(handle);
- std::lock_guard<std::mutex> lock(m_mutex);
- auto it = m_refresh_handles.find(path);
- if (it != m_refresh_handles.end()) {
- [it->second invalidate];
- m_refresh_handles.erase(it);
- }
- m_refresh_handles.insert({path, handle});
- }
- void CocoaSyncUserContext::unregister_refresh_handle(const std::string& path)
- {
- std::lock_guard<std::mutex> lock(m_mutex);
- m_refresh_handles.erase(path);
- }
- void CocoaSyncUserContext::invalidate_all_handles()
- {
- std::lock_guard<std::mutex> lock(m_mutex);
- for (auto& it : m_refresh_handles) {
- [it.second invalidate];
- }
- m_refresh_handles.clear();
- }
- RLMUserErrorReportingBlock CocoaSyncUserContext::error_handler() const
- {
- std::lock_guard<std::mutex> lock(m_error_handler_mutex);
- return m_error_handler;
- }
- void CocoaSyncUserContext::set_error_handler(RLMUserErrorReportingBlock block)
- {
- std::lock_guard<std::mutex> lock(m_error_handler_mutex);
- m_error_handler = block;
- }
- PermissionChangeCallback RLMWrapPermissionStatusCallback(RLMPermissionStatusBlock callback) {
- return [callback](std::exception_ptr ptr) {
- if (ptr) {
- NSError *error = translateSyncExceptionPtrToError(std::move(ptr), RLMPermissionActionTypeChange);
- REALM_ASSERT(error);
- callback(error);
- } else {
- // Finished successfully
- callback(nil);
- }
- };
- }
- @interface RLMSyncUserInfo ()
- @property (nonatomic, readwrite) NSArray *accounts;
- @property (nonatomic, readwrite) NSDictionary *metadata;
- @property (nonatomic, readwrite) NSString *identity;
- @property (nonatomic, readwrite) BOOL isAdmin;
- + (instancetype)syncUserInfoWithModel:(RLMUserResponseModel *)model;
- @end
- @interface RLMSyncUser () {
- std::shared_ptr<SyncUser> _user;
- // FIXME: remove this when the object store ConfigMaker goes away
- std::unique_ptr<ConfigMaker> _configMaker;
- }
- - (instancetype)initPrivate NS_DESIGNATED_INITIALIZER;
- @end
- @implementation RLMSyncUser
- #pragma mark - static API
- + (NSDictionary *)allUsers {
- NSArray *allUsers = [[RLMSyncManager sharedManager] _allUsers];
- return [NSDictionary dictionaryWithObjects:allUsers
- forKeys:[allUsers valueForKey:@"identity"]];
- }
- + (RLMSyncUser *)currentUser {
- NSArray *allUsers = [[RLMSyncManager sharedManager] _allUsers];
- if (allUsers.count > 1) {
- @throw RLMException(@"+currentUser cannot be called if more that one valid, logged-in user exists.");
- }
- return allUsers.firstObject;
- }
- #pragma mark - API
- - (instancetype)initPrivate {
- if (self = [super init]) {
- _configMaker = std::make_unique<ConfigMaker>([](std::shared_ptr<SyncUser> user, std::string url) {
- NSURL *objCUrl = [NSURL URLWithString:@(url.c_str())];
- RLMSyncUser *objCUser = [[RLMSyncUser alloc] initWithSyncUser:std::move(user)];
- return [objCUser configurationWithURL:objCUrl fullSynchronization:true].config;
- });
- return self;
- }
- return nil;
- }
- - (instancetype)initWithSyncUser:(std::shared_ptr<SyncUser>)user {
- if (self = [self initPrivate]) {
- _user = user;
- return self;
- }
- return nil;
- }
- - (BOOL)isEqual:(id)object {
- if (![object isKindOfClass:[RLMSyncUser class]]) {
- return NO;
- }
- return _user == ((RLMSyncUser *)object)->_user;
- }
- + (void)logInWithCredentials:(RLMSyncCredentials *)credential
- authServerURL:(NSURL *)authServerURL
- onCompletion:(RLMUserCompletionBlock)completion {
- [self logInWithCredentials:credential
- authServerURL:authServerURL
- timeout:30
- callbackQueue:dispatch_get_main_queue()
- onCompletion:completion];
- }
- + (void)logInWithCredentials:(RLMSyncCredentials *)credential
- authServerURL:(NSURL *)authServerURL
- timeout:(NSTimeInterval)timeout
- callbackQueue:(dispatch_queue_t)callbackQueue
- onCompletion:(RLMUserCompletionBlock)completion {
- RLMSyncUser *user = [[RLMSyncUser alloc] initPrivate];
- [RLMSyncUser _performLogInForUser:user
- credentials:credential
- authServerURL:authServerURL
- timeout:timeout
- callbackQueue:callbackQueue
- completionBlock:completion];
- }
- - (RLMRealmConfiguration *)configuration {
- return [self configurationWithURL:nil
- fullSynchronization:NO
- enableSSLValidation:YES
- urlPrefix:nil];
- }
- - (RLMRealmConfiguration *)configurationWithURL:(NSURL *)url {
- return [self configurationWithURL:url
- fullSynchronization:NO
- enableSSLValidation:YES
- urlPrefix:nil];
- }
- - (RLMRealmConfiguration *)configurationWithURL:(NSURL *)url fullSynchronization:(bool)fullSynchronization {
- return [self configurationWithURL:url
- fullSynchronization:fullSynchronization
- enableSSLValidation:YES
- urlPrefix:nil];
- }
- - (RLMRealmConfiguration *)configurationWithURL:(NSURL *)url
- fullSynchronization:(bool)fullSynchronization
- enableSSLValidation:(bool)enableSSLValidation
- urlPrefix:(NSString * _Nullable)urlPrefix {
- auto syncConfig = [[RLMSyncConfiguration alloc] initWithUser:self
- realmURL:url ?: self.defaultRealmURL
- customFileURL:nil
- isPartial:!fullSynchronization
- stopPolicy:RLMSyncStopPolicyAfterChangesUploaded
- errorHandler:nullptr];
- syncConfig.urlPrefix = urlPrefix;
- syncConfig.enableSSLValidation = enableSSLValidation;
- syncConfig.pinnedCertificateURL = RLMSyncManager.sharedManager.pinnedCertificatePaths[syncConfig.realmURL.host];
- RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
- config.syncConfiguration = syncConfig;
- return config;
- }
- - (void)logOut {
- if (!_user) {
- return;
- }
- _user->log_out();
- context_for(_user).invalidate_all_handles();
- }
- - (RLMUserErrorReportingBlock)errorHandler {
- if (!_user) {
- return nil;
- }
- return context_for(_user).error_handler();
- }
- - (void)setErrorHandler:(RLMUserErrorReportingBlock)errorHandler {
- if (!_user) {
- return;
- }
- context_for(_user).set_error_handler([errorHandler copy]);
- }
- - (nullable RLMSyncSession *)sessionForURL:(NSURL *)url {
- if (!_user) {
- return nil;
- }
- auto path = SyncManager::shared().path_for_realm(*_user, [url.absoluteString UTF8String]);
- if (auto session = _user->session_for_on_disk_path(path)) {
- return [[RLMSyncSession alloc] initWithSyncSession:session];
- }
- return nil;
- }
- - (NSArray<RLMSyncSession *> *)allSessions {
- if (!_user) {
- return @[];
- }
- NSMutableArray<RLMSyncSession *> *buffer = [NSMutableArray array];
- auto sessions = _user->all_sessions();
- for (auto session : sessions) {
- [buffer addObject:[[RLMSyncSession alloc] initWithSyncSession:std::move(session)]];
- }
- return [buffer copy];
- }
- - (NSString *)identity {
- if (!_user) {
- return nil;
- }
- return @(_user->identity().c_str());
- }
- - (RLMSyncUserState)state {
- if (!_user) {
- return RLMSyncUserStateError;
- }
- switch (_user->state()) {
- case SyncUser::State::Active:
- return RLMSyncUserStateActive;
- case SyncUser::State::LoggedOut:
- return RLMSyncUserStateLoggedOut;
- case SyncUser::State::Error:
- return RLMSyncUserStateError;
- }
- }
- - (NSURL *)authenticationServer {
- if (!_user || _user->token_type() == SyncUser::TokenType::Admin) {
- return nil;
- }
- return [NSURL URLWithString:@(_user->server_url().c_str())];
- }
- - (BOOL)isAdmin {
- if (!_user) {
- return NO;
- }
- return _user->is_admin();
- }
- #pragma mark - Passwords
- - (void)changePassword:(NSString *)newPassword completion:(RLMPasswordChangeStatusBlock)completion {
- [self changePassword:newPassword forUserID:self.identity completion:completion];
- }
- - (void)changePassword:(NSString *)newPassword forUserID:(NSString *)userID completion:(RLMPasswordChangeStatusBlock)completion {
- if (self.state != RLMSyncUserStateActive) {
- completion([NSError errorWithDomain:RLMSyncErrorDomain
- code:RLMSyncErrorClientSessionError
- userInfo:nil]);
- return;
- }
- [RLMSyncChangePasswordEndpoint sendRequestToServer:self.authenticationServer
- JSON:@{kRLMSyncTokenKey: self.refreshToken,
- kRLMSyncUserIDKey: userID,
- kRLMSyncDataKey: @{kRLMSyncNewPasswordKey: newPassword}}
- options:[[RLMSyncManager sharedManager] networkRequestOptions]
- completion:completion];
- }
- + (void)requestPasswordResetForAuthServer:(NSURL *)serverURL
- userEmail:(NSString *)email
- completion:(RLMPasswordChangeStatusBlock)completion {
- [RLMSyncUpdateAccountEndpoint sendRequestToServer:serverURL
- JSON:@{@"provider_id": email, @"data": @{@"action": @"reset_password"}}
- options:[[RLMSyncManager sharedManager] networkRequestOptions]
- completion:completion];
- }
- + (void)completePasswordResetForAuthServer:(NSURL *)serverURL
- token:(NSString *)token
- password:(NSString *)newPassword
- completion:(RLMPasswordChangeStatusBlock)completion {
- [RLMSyncUpdateAccountEndpoint sendRequestToServer:serverURL
- JSON:@{@"data": @{@"action": @"complete_reset",
- @"token": token,
- @"new_password": newPassword}}
- options:[[RLMSyncManager sharedManager] networkRequestOptions]
- completion:completion];
- }
- + (void)requestEmailConfirmationForAuthServer:(NSURL *)serverURL
- userEmail:(NSString *)email
- completion:(RLMPasswordChangeStatusBlock)completion {
- [RLMSyncUpdateAccountEndpoint sendRequestToServer:serverURL
- JSON:@{@"provider_id": email, @"data": @{@"action": @"request_email_confirmation"}}
- options:[[RLMSyncManager sharedManager] networkRequestOptions]
- completion:completion];
- }
- + (void)confirmEmailForAuthServer:(NSURL *)serverURL
- token:(NSString *)token
- completion:(RLMPasswordChangeStatusBlock)completion {
- [RLMSyncUpdateAccountEndpoint sendRequestToServer:serverURL
- JSON:@{@"data": @{@"action": @"confirm_email",
- @"token": token}}
- options:[[RLMSyncManager sharedManager] networkRequestOptions]
- completion:completion];
- }
- #pragma mark - Administrator API
- - (void)retrieveInfoForUser:(NSString *)providerUserIdentity
- identityProvider:(RLMIdentityProvider)provider
- completion:(RLMRetrieveUserBlock)completion {
- [RLMNetworkClient sendRequestToEndpoint:[RLMSyncGetUserInfoEndpoint endpoint]
- server:self.authenticationServer
- JSON:@{
- kRLMSyncProviderKey: provider,
- kRLMSyncProviderIDKey: providerUserIdentity,
- kRLMSyncTokenKey: self.refreshToken
- }
- timeout:60
- options:[[RLMSyncManager sharedManager] networkRequestOptions]
- completion:^(NSError *error, NSDictionary *json) {
- if (error) {
- completion(nil, error);
- return;
- }
- RLMUserResponseModel *model = [[RLMUserResponseModel alloc] initWithDictionary:json];
- if (!model) {
- completion(nil, make_auth_error_bad_response(json));
- return;
- }
- completion([RLMSyncUserInfo syncUserInfoWithModel:model], nil);
- }];
- }
- #pragma mark - Permissions API
- static void verifyInRunLoop() {
- if (!RLMIsInRunLoop()) {
- @throw RLMException(@"Can only access or modify permissions from a thread which has a run loop (by default, only the main thread).");
- }
- }
- - (void)retrievePermissionsWithCallback:(RLMPermissionResultsBlock)callback {
- verifyInRunLoop();
- if (!_user || _user->state() == SyncUser::State::Error) {
- callback(nullptr, make_permission_error_get(@"Permissions cannot be retrieved using an invalid user."));
- return;
- }
- Permissions::get_permissions(_user, RLMWrapPermissionResultsCallback(callback), *_configMaker);
- }
- - (void)applyPermission:(RLMSyncPermission *)permission callback:(RLMPermissionStatusBlock)callback {
- verifyInRunLoop();
- if (!_user || _user->state() == SyncUser::State::Error) {
- callback(make_permission_error_change(@"Permissions cannot be applied using an invalid user."));
- return;
- }
- Permissions::set_permission(_user,
- [permission rawPermission],
- RLMWrapPermissionStatusCallback(callback),
- *_configMaker);
- }
- - (void)revokePermission:(RLMSyncPermission *)permission callback:(RLMPermissionStatusBlock)callback {
- verifyInRunLoop();
- if (!_user || _user->state() == SyncUser::State::Error) {
- callback(make_permission_error_change(@"Permissions cannot be revoked using an invalid user."));
- return;
- }
- Permissions::delete_permission(_user,
- [permission rawPermission],
- RLMWrapPermissionStatusCallback(callback),
- *_configMaker);
- }
- - (void)createOfferForRealmAtURL:(NSURL *)url
- accessLevel:(RLMSyncAccessLevel)accessLevel
- expiration:(NSDate *)expirationDate
- callback:(RLMPermissionOfferStatusBlock)callback {
- verifyInRunLoop();
- if (!_user || _user->state() == SyncUser::State::Error) {
- callback(nil, make_permission_error_change(@"A permission offer cannot be created using an invalid user."));
- return;
- }
- auto cb = [callback](util::Optional<std::string> token, std::exception_ptr ptr) {
- if (ptr) {
- NSError *error = translateSyncExceptionPtrToError(std::move(ptr), RLMPermissionActionTypeOffer);
- REALM_ASSERT_DEBUG(error);
- callback(nil, error);
- } else {
- REALM_ASSERT_DEBUG(token);
- callback(@(token->c_str()), nil);
- }
- };
- auto offer = PermissionOffer{
- [tildeSubstitutedPathForRealmURL(url, self.identity) UTF8String],
- accessLevelForObjCAccessLevel(accessLevel),
- RLMTimestampForNSDate(expirationDate),
- };
- Permissions::make_offer(_user, std::move(offer), std::move(cb), *_configMaker);
- }
- - (void)acceptOfferForToken:(NSString *)token
- callback:(RLMPermissionOfferResponseStatusBlock)callback {
- verifyInRunLoop();
- if (!_user || _user->state() == SyncUser::State::Error) {
- callback(nil, make_permission_error_change(@"A permission offer cannot be accepted by an invalid user."));
- return;
- }
- NSURLComponents *baseURL = [NSURLComponents componentsWithURL:self.authenticationServer
- resolvingAgainstBaseURL:YES];
- if ([baseURL.scheme isEqualToString:@"http"]) {
- baseURL.scheme = @"realm";
- } else if ([baseURL.scheme isEqualToString:@"https"]) {
- baseURL.scheme = @"realms";
- }
- auto cb = [baseURL, callback](util::Optional<std::string> raw_path, std::exception_ptr ptr) {
- if (ptr) {
- NSError *error = translateSyncExceptionPtrToError(std::move(ptr), RLMPermissionActionTypeAcceptOffer);
- REALM_ASSERT_DEBUG(error);
- callback(nil, error);
- } else {
- // Note that ROS currently vends the path to the Realm, so we need to construct the full URL ourselves.
- REALM_ASSERT_DEBUG(raw_path);
- baseURL.path = @(raw_path->c_str());
- callback([baseURL URL], nil);
- }
- };
- Permissions::accept_offer(_user, [token UTF8String], std::move(cb), *_configMaker);
- }
- #pragma mark - Private API
- - (NSURL *)defaultRealmURL
- {
- NSURLComponents *components = [NSURLComponents componentsWithURL:self.authenticationServer resolvingAgainstBaseURL:YES];
- if ([components.scheme caseInsensitiveCompare:@"http"] == NSOrderedSame)
- components.scheme = @"realm";
- else if ([components.scheme caseInsensitiveCompare:@"https"] == NSOrderedSame)
- components.scheme = @"realms";
- else
- @throw RLMException(@"The provided user's authentication server URL (%@) was not valid.", self.authenticationServer);
- components.path = @"/default";
- return components.URL;
- }
- + (void)_setUpBindingContextFactory {
- SyncUser::set_binding_context_factory([] {
- return std::make_shared<CocoaSyncUserContext>();
- });
- }
- - (NSString *)refreshToken {
- if (!_user) {
- return nil;
- }
- return @(_user->refresh_token().c_str());
- }
- - (std::shared_ptr<SyncUser>)_syncUser {
- return _user;
- }
- + (void)_performLogInForUser:(RLMSyncUser *)user
- credentials:(RLMSyncCredentials *)credentials
- authServerURL:(NSURL *)authServerURL
- timeout:(NSTimeInterval)timeout
- callbackQueue:(dispatch_queue_t)callbackQueue
- completionBlock:(RLMUserCompletionBlock)completion {
- // Special credential login should be treated differently.
- if (credentials.provider == RLMIdentityProviderAccessToken) {
- [self _performLoginForDirectAccessTokenCredentials:credentials
- user:user
- authServerURL:authServerURL
- completionBlock:completion];
- return;
- }
- if (!authServerURL) {
- @throw RLMException(@"A user cannot be logged in without specifying an authentication server URL.");
- }
- // Prepare login network request
- NSMutableDictionary *json = [@{
- kRLMSyncProviderKey: credentials.provider,
- kRLMSyncDataKey: credentials.token,
- kRLMSyncAppIDKey: [RLMSyncManager sharedManager].appID,
- } mutableCopy];
- NSMutableDictionary *info = [(credentials.userInfo ?: @{}) mutableCopy];
- if ([info count] > 0) {
- // Munge user info into the JSON request.
- json[@"user_info"] = info;
- }
- RLMSyncCompletionBlock handler = ^(NSError *error, NSDictionary *json) {
- if (json && !error) {
- RLMAuthResponseModel *model = [[RLMAuthResponseModel alloc] initWithDictionary:json
- requireAccessToken:NO
- requireRefreshToken:YES];
- if (!model) {
- // Malformed JSON
- NSError *badResponseError = make_auth_error_bad_response(json);
- dispatch_async(callbackQueue, ^{
- completion(nil, badResponseError);
- });
- return;
- } else {
- std::string server_url = authServerURL.absoluteString.UTF8String;
- SyncUserIdentifier identity{[model.refreshToken.tokenData.identity UTF8String], std::move(server_url)};
- auto sync_user = SyncManager::shared().get_user(identity , [model.refreshToken.token UTF8String]);
- if (!sync_user) {
- NSError *authError = make_auth_error_client_issue();
- dispatch_async(callbackQueue, ^{
- completion(nil, authError);
- });
- return;
- }
- sync_user->set_is_admin(model.refreshToken.tokenData.isAdmin);
- user->_user = sync_user;
- dispatch_async(callbackQueue, ^{
- completion(user, nil);
- });
- }
- } else {
- // Something else went wrong
- dispatch_async(callbackQueue, ^{
- completion(nil, error);
- });
- }
- };
- [RLMNetworkClient sendRequestToEndpoint:[RLMSyncAuthEndpoint endpoint]
- server:authServerURL
- JSON:json
- timeout:timeout
- options:[[RLMSyncManager sharedManager] networkRequestOptions]
- completion:^(NSError *error, NSDictionary *dictionary) {
- dispatch_async(callbackQueue, ^{
- handler(error, dictionary);
- });
- }];
- }
- + (void)_performLoginForDirectAccessTokenCredentials:(RLMSyncCredentials *)credentials
- user:(RLMSyncUser *)user
- authServerURL:(NSURL *)serverURL
- completionBlock:(nonnull RLMUserCompletionBlock)completion {
- NSString *identity = credentials.userInfo[kRLMSyncIdentityKey];
- std::shared_ptr<SyncUser> sync_user;
- if (serverURL) {
- NSString *scheme = serverURL.scheme;
- if (![scheme isEqualToString:@"http"] && ![scheme isEqualToString:@"https"]) {
- @throw RLMException(@"The Realm Object Server authentication URL provided for this user, \"%@\", "
- @" is invalid. It must begin with http:// or https://.", serverURL);
- }
- // Retrieve the user based on the auth server URL.
- util::Optional<std::string> identity_string;
- if (identity) {
- identity_string = std::string(identity.UTF8String);
- }
- sync_user = SyncManager::shared().get_admin_token_user([serverURL absoluteString].UTF8String,
- credentials.token.UTF8String,
- std::move(identity_string));
- } else {
- // Retrieve the user based on the identity.
- if (!identity) {
- @throw RLMException(@"A direct access credential must specify either an identity, a server URL, or both.");
- }
- sync_user = SyncManager::shared().get_admin_token_user_from_identity(identity.UTF8String,
- none,
- credentials.token.UTF8String);
- }
- if (!sync_user) {
- completion(nil, make_auth_error_client_issue());
- return;
- }
- user->_user = sync_user;
- completion(user, nil);
- }
- @end
- #pragma mark - RLMSyncUserInfo
- @implementation RLMSyncUserInfo
- - (instancetype)initPrivate {
- return [super init];
- }
- + (instancetype)syncUserInfoWithModel:(RLMUserResponseModel *)model {
- RLMSyncUserInfo *info = [[RLMSyncUserInfo alloc] initPrivate];
- info.accounts = model.accounts;
- info.metadata = model.metadata;
- info.isAdmin = model.isAdmin;
- info.identity = model.identity;
- return info;
- }
- @end
|