1 ////////////////////////////////////////////////////////////////////////////
3 // Copyright 2016 Realm Inc.
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
17 ////////////////////////////////////////////////////////////////////////////
19 #import <Foundation/Foundation.h>
21 #import "RLMJSONModels.h"
22 #import "RLMSyncConfiguration_Private.hpp"
23 #import "RLMSyncUtil_Private.hpp"
24 #import "RLMSyncUser_Private.hpp"
25 #import "RLMRealmConfiguration+Sync.h"
26 #import "RLMRealmConfiguration_Private.hpp"
29 #import "shared_realm.hpp"
31 #import "sync/sync_permission.hpp"
32 #import "sync/sync_user.hpp"
34 RLMIdentityProvider const RLMIdentityProviderAccessToken = @"_access_token";
36 NSString *const RLMSyncErrorDomain = @"io.realm.sync";
37 NSString *const RLMSyncAuthErrorDomain = @"io.realm.sync.auth";
38 NSString *const RLMSyncPermissionErrorDomain = @"io.realm.sync.permission";
40 NSString *const kRLMSyncPathOfRealmBackupCopyKey = @"recovered_realm_location_path";
41 NSString *const kRLMSyncErrorActionTokenKey = @"error_action_token";
43 NSString *const kRLMSyncAppIDKey = @"app_id";
44 NSString *const kRLMSyncDataKey = @"data";
45 NSString *const kRLMSyncErrorJSONKey = @"json";
46 NSString *const kRLMSyncErrorStatusCodeKey = @"statusCode";
47 NSString *const kRLMSyncIdentityKey = @"identity";
48 NSString *const kRLMSyncIsAdminKey = @"is_admin";
49 NSString *const kRLMSyncNewPasswordKey = @"new_password";
50 NSString *const kRLMSyncPasswordKey = @"password";
51 NSString *const kRLMSyncPathKey = @"path";
52 NSString *const kRLMSyncProviderKey = @"provider";
53 NSString *const kRLMSyncProviderIDKey = @"provider_id";
54 NSString *const kRLMSyncRegisterKey = @"register";
55 NSString *const kRLMSyncTokenKey = @"token";
56 NSString *const kRLMSyncUnderlyingErrorKey = @"underlying_error";
57 NSString *const kRLMSyncUserIDKey = @"user_id";
59 #pragma mark - C++ APIs
63 NSError *make_permission_error(NSString *description, util::Optional<NSInteger> code, RLMSyncPermissionError type) {
64 NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
66 userInfo[NSLocalizedDescriptionKey] = description;
69 userInfo[kRLMSyncErrorStatusCodeKey] = @(*code);
71 return [NSError errorWithDomain:RLMSyncPermissionErrorDomain code:type userInfo:userInfo];
76 SyncSessionStopPolicy translateStopPolicy(RLMSyncStopPolicy stopPolicy) {
78 case RLMSyncStopPolicyImmediately: return SyncSessionStopPolicy::Immediately;
79 case RLMSyncStopPolicyLiveIndefinitely: return SyncSessionStopPolicy::LiveIndefinitely;
80 case RLMSyncStopPolicyAfterChangesUploaded: return SyncSessionStopPolicy::AfterChangesUploaded;
82 REALM_UNREACHABLE(); // Unrecognized stop policy.
85 RLMSyncStopPolicy translateStopPolicy(SyncSessionStopPolicy stop_policy) {
86 switch (stop_policy) {
87 case SyncSessionStopPolicy::Immediately: return RLMSyncStopPolicyImmediately;
88 case SyncSessionStopPolicy::LiveIndefinitely: return RLMSyncStopPolicyLiveIndefinitely;
89 case SyncSessionStopPolicy::AfterChangesUploaded: return RLMSyncStopPolicyAfterChangesUploaded;
94 NSError *translateSyncExceptionPtrToError(std::exception_ptr ptr, RLMPermissionActionType type) {
97 std::rethrow_exception(ptr);
98 } catch (PermissionActionException const& ex) {
100 case RLMPermissionActionTypeGet:
101 error = make_permission_error_get(@(ex.what()), ex.code);
103 case RLMPermissionActionTypeChange:
104 error = make_permission_error_change(@(ex.what()), ex.code);
106 case RLMPermissionActionTypeOffer:
107 error = make_permission_error_offer(@(ex.what()), ex.code);
109 case RLMPermissionActionTypeAcceptOffer:
110 error = make_permission_error_accept_offer(@(ex.what()), ex.code);
114 catch (const std::exception &exp) {
115 RLMSetErrorOrThrow(RLMMakeError(RLMErrorFail, exp), &error);
120 std::shared_ptr<SyncSession> sync_session_for_realm(RLMRealm *realm) {
121 Realm::Config realmConfig = realm.configuration.config;
122 if (auto config = realmConfig.sync_config) {
123 std::shared_ptr<SyncUser> user = config->user;
124 if (user && user->state() != SyncUser::State::Error) {
125 return user->session_for_on_disk_path(realmConfig.path);
131 CocoaSyncUserContext& context_for(const std::shared_ptr<realm::SyncUser>& user)
133 return *std::static_pointer_cast<CocoaSyncUserContext>(user->binding_context());
136 AccessLevel accessLevelForObjCAccessLevel(RLMSyncAccessLevel level) {
138 case RLMSyncAccessLevelNone:
139 return AccessLevel::None;
140 case RLMSyncAccessLevelRead:
141 return AccessLevel::Read;
142 case RLMSyncAccessLevelWrite:
143 return AccessLevel::Write;
144 case RLMSyncAccessLevelAdmin:
145 return AccessLevel::Admin;
150 RLMSyncAccessLevel objCAccessLevelForAccessLevel(AccessLevel level) {
152 case AccessLevel::None:
153 return RLMSyncAccessLevelNone;
154 case AccessLevel::Read:
155 return RLMSyncAccessLevelRead;
156 case AccessLevel::Write:
157 return RLMSyncAccessLevelWrite;
158 case AccessLevel::Admin:
159 return RLMSyncAccessLevelAdmin;
164 NSError *make_auth_error_bad_response(NSDictionary *json) {
165 return [NSError errorWithDomain:RLMSyncAuthErrorDomain
166 code:RLMSyncAuthErrorBadResponse
167 userInfo:json ? @{kRLMSyncErrorJSONKey: json} : nil];
170 NSError *make_auth_error_http_status(NSInteger status) {
171 return [NSError errorWithDomain:RLMSyncAuthErrorDomain
172 code:RLMSyncAuthErrorHTTPStatusCodeError
173 userInfo:@{kRLMSyncErrorStatusCodeKey: @(status)}];
176 NSError *make_auth_error_client_issue() {
177 return [NSError errorWithDomain:RLMSyncAuthErrorDomain
178 code:RLMSyncAuthErrorClientSessionError
182 NSError *make_auth_error(RLMSyncErrorResponseModel *model) {
183 NSMutableDictionary<NSString *, NSString *> *userInfo = [NSMutableDictionary dictionaryWithCapacity:2];
184 if (NSString *description = model.title) {
185 [userInfo setObject:description forKey:NSLocalizedDescriptionKey];
187 if (NSString *hint = model.hint) {
188 [userInfo setObject:hint forKey:NSLocalizedRecoverySuggestionErrorKey];
190 return [NSError errorWithDomain:RLMSyncAuthErrorDomain code:model.code userInfo:userInfo];
193 NSError *make_permission_error_get(NSString *description, util::Optional<NSInteger> code) {
194 return make_permission_error(description, std::move(code), RLMSyncPermissionErrorGetFailed);
197 NSError *make_permission_error_change(NSString *description, util::Optional<NSInteger> code) {
198 return make_permission_error(description, std::move(code), RLMSyncPermissionErrorChangeFailed);
201 NSError *make_permission_error_offer(NSString *description, util::Optional<NSInteger> code) {
202 return make_permission_error(description, std::move(code), RLMSyncPermissionErrorOfferFailed);
205 NSError *make_permission_error_accept_offer(NSString *description, util::Optional<NSInteger> code) {
206 return make_permission_error(description, std::move(code), RLMSyncPermissionErrorAcceptOfferFailed);
209 NSError *make_sync_error(RLMSyncSystemErrorKind kind, NSString *description, NSInteger code, NSDictionary *custom) {
210 NSMutableDictionary *buffer = [custom ?: @{} mutableCopy];
211 buffer[NSLocalizedDescriptionKey] = description;
212 if (code != NSNotFound) {
213 buffer[kRLMSyncErrorStatusCodeKey] = @(code);
216 RLMSyncError errorCode;
218 case RLMSyncSystemErrorKindClientReset:
219 errorCode = RLMSyncErrorClientResetError;
221 case RLMSyncSystemErrorKindPermissionDenied:
222 errorCode = RLMSyncErrorPermissionDeniedError;
224 case RLMSyncSystemErrorKindUser:
225 errorCode = RLMSyncErrorClientUserError;
227 case RLMSyncSystemErrorKindSession:
228 errorCode = RLMSyncErrorClientSessionError;
230 case RLMSyncSystemErrorKindConnection:
231 case RLMSyncSystemErrorKindClient:
232 case RLMSyncSystemErrorKindUnknown:
233 errorCode = RLMSyncErrorClientInternalError;
236 return [NSError errorWithDomain:RLMSyncErrorDomain
238 userInfo:[buffer copy]];
241 NSError *make_sync_error(NSError *wrapped_auth_error) {
242 return [NSError errorWithDomain:RLMSyncErrorDomain
243 code:RLMSyncErrorUnderlyingAuthError
244 userInfo:@{kRLMSyncUnderlyingErrorKey: wrapped_auth_error}];
247 NSError *make_sync_error(std::error_code sync_error, RLMSyncSystemErrorKind kind) {
248 return [NSError errorWithDomain:RLMSyncErrorDomain
251 NSLocalizedDescriptionKey: @(sync_error.message().c_str()),
252 kRLMSyncErrorStatusCodeKey: @(sync_error.value())