added iOS source code
[wl-app.git] / iOS / Pods / Realm / Realm / RLMSyncUtil.mm
1 ////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright 2016 Realm Inc.
4 //
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
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17 ////////////////////////////////////////////////////////////////////////////
18
19 #import <Foundation/Foundation.h>
20
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"
27 #import "RLMUtil.hpp"
28
29 #import "shared_realm.hpp"
30
31 #import "sync/sync_permission.hpp"
32 #import "sync/sync_user.hpp"
33
34 RLMIdentityProvider const RLMIdentityProviderAccessToken = @"_access_token";
35
36 NSString *const RLMSyncErrorDomain = @"io.realm.sync";
37 NSString *const RLMSyncAuthErrorDomain = @"io.realm.sync.auth";
38 NSString *const RLMSyncPermissionErrorDomain = @"io.realm.sync.permission";
39
40 NSString *const kRLMSyncPathOfRealmBackupCopyKey            = @"recovered_realm_location_path";
41 NSString *const kRLMSyncErrorActionTokenKey                 = @"error_action_token";
42
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";
58
59 #pragma mark - C++ APIs
60
61 namespace {
62
63 NSError *make_permission_error(NSString *description, util::Optional<NSInteger> code, RLMSyncPermissionError type) {
64     NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
65     if (description) {
66         userInfo[NSLocalizedDescriptionKey] = description;
67     }
68     if (code) {
69         userInfo[kRLMSyncErrorStatusCodeKey] = @(*code);
70     }
71     return [NSError errorWithDomain:RLMSyncPermissionErrorDomain code:type userInfo:userInfo];
72 }
73
74 }
75
76 SyncSessionStopPolicy translateStopPolicy(RLMSyncStopPolicy stopPolicy) {
77     switch (stopPolicy) {
78         case RLMSyncStopPolicyImmediately:              return SyncSessionStopPolicy::Immediately;
79         case RLMSyncStopPolicyLiveIndefinitely:         return SyncSessionStopPolicy::LiveIndefinitely;
80         case RLMSyncStopPolicyAfterChangesUploaded:     return SyncSessionStopPolicy::AfterChangesUploaded;
81     }
82     REALM_UNREACHABLE();    // Unrecognized stop policy.
83 }
84
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;
90     }
91     REALM_UNREACHABLE();
92 }
93
94 NSError *translateSyncExceptionPtrToError(std::exception_ptr ptr, RLMPermissionActionType type) {
95     NSError *error = nil;
96     try {
97         std::rethrow_exception(ptr);
98     } catch (PermissionActionException const& ex) {
99         switch (type) {
100             case RLMPermissionActionTypeGet:
101                 error = make_permission_error_get(@(ex.what()), ex.code);
102                 break;
103             case RLMPermissionActionTypeChange:
104                 error = make_permission_error_change(@(ex.what()), ex.code);
105                 break;
106             case RLMPermissionActionTypeOffer:
107                 error = make_permission_error_offer(@(ex.what()), ex.code);
108                 break;
109             case RLMPermissionActionTypeAcceptOffer:
110                 error = make_permission_error_accept_offer(@(ex.what()), ex.code);
111                 break;
112         }
113     }
114     catch (const std::exception &exp) {
115         RLMSetErrorOrThrow(RLMMakeError(RLMErrorFail, exp), &error);
116     }
117     return error;
118 }
119
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);
126         }
127     }
128     return nullptr;
129 }
130
131 CocoaSyncUserContext& context_for(const std::shared_ptr<realm::SyncUser>& user)
132 {
133     return *std::static_pointer_cast<CocoaSyncUserContext>(user->binding_context());
134 }
135
136 AccessLevel accessLevelForObjCAccessLevel(RLMSyncAccessLevel level) {
137     switch (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;
146     }
147     REALM_UNREACHABLE();
148 }
149
150 RLMSyncAccessLevel objCAccessLevelForAccessLevel(AccessLevel level) {
151     switch (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;
160     }
161     REALM_UNREACHABLE();
162 }
163
164 NSError *make_auth_error_bad_response(NSDictionary *json) {
165     return [NSError errorWithDomain:RLMSyncAuthErrorDomain
166                                code:RLMSyncAuthErrorBadResponse
167                            userInfo:json ? @{kRLMSyncErrorJSONKey: json} : nil];
168 }
169
170 NSError *make_auth_error_http_status(NSInteger status) {
171     return [NSError errorWithDomain:RLMSyncAuthErrorDomain
172                                code:RLMSyncAuthErrorHTTPStatusCodeError
173                            userInfo:@{kRLMSyncErrorStatusCodeKey: @(status)}];
174 }
175
176 NSError *make_auth_error_client_issue() {
177     return [NSError errorWithDomain:RLMSyncAuthErrorDomain
178                                code:RLMSyncAuthErrorClientSessionError
179                            userInfo:nil];
180 }
181
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];
186     }
187     if (NSString *hint = model.hint) {
188         [userInfo setObject:hint forKey:NSLocalizedRecoverySuggestionErrorKey];
189     }
190     return [NSError errorWithDomain:RLMSyncAuthErrorDomain code:model.code userInfo:userInfo];
191 }
192
193 NSError *make_permission_error_get(NSString *description, util::Optional<NSInteger> code) {
194     return make_permission_error(description, std::move(code), RLMSyncPermissionErrorGetFailed);
195 }
196
197 NSError *make_permission_error_change(NSString *description, util::Optional<NSInteger> code) {
198     return make_permission_error(description, std::move(code), RLMSyncPermissionErrorChangeFailed);
199 }
200
201 NSError *make_permission_error_offer(NSString *description, util::Optional<NSInteger> code) {
202     return make_permission_error(description, std::move(code), RLMSyncPermissionErrorOfferFailed);
203 }
204
205 NSError *make_permission_error_accept_offer(NSString *description, util::Optional<NSInteger> code) {
206     return make_permission_error(description, std::move(code), RLMSyncPermissionErrorAcceptOfferFailed);
207 }
208
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);
214     }
215
216     RLMSyncError errorCode;
217     switch (kind) {
218         case RLMSyncSystemErrorKindClientReset:
219             errorCode = RLMSyncErrorClientResetError;
220             break;
221         case RLMSyncSystemErrorKindPermissionDenied:
222             errorCode = RLMSyncErrorPermissionDeniedError;
223             break;
224         case RLMSyncSystemErrorKindUser:
225             errorCode = RLMSyncErrorClientUserError;
226             break;
227         case RLMSyncSystemErrorKindSession:
228             errorCode = RLMSyncErrorClientSessionError;
229             break;
230         case RLMSyncSystemErrorKindConnection:
231         case RLMSyncSystemErrorKindClient:
232         case RLMSyncSystemErrorKindUnknown:
233             errorCode = RLMSyncErrorClientInternalError;
234             break;
235     }
236     return [NSError errorWithDomain:RLMSyncErrorDomain
237                                code:errorCode
238                            userInfo:[buffer copy]];
239 }
240
241 NSError *make_sync_error(NSError *wrapped_auth_error) {
242     return [NSError errorWithDomain:RLMSyncErrorDomain
243                                code:RLMSyncErrorUnderlyingAuthError
244                            userInfo:@{kRLMSyncUnderlyingErrorKey: wrapped_auth_error}];
245 }
246
247 NSError *make_sync_error(std::error_code sync_error, RLMSyncSystemErrorKind kind) {
248     return [NSError errorWithDomain:RLMSyncErrorDomain
249                                code:kind
250                            userInfo:@{
251                                       NSLocalizedDescriptionKey: @(sync_error.message().c_str()),
252                                       kRLMSyncErrorStatusCodeKey: @(sync_error.value())
253                                       }];
254 }