RLMSyncUtil.mm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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. #import "RLMSyncUtil_Private.hpp"
  19. #import "RLMJSONModels.h"
  20. #import "RLMObject_Private.hpp"
  21. #import "RLMRealmConfiguration+Sync.h"
  22. #import "RLMRealmConfiguration_Private.hpp"
  23. #import "RLMRealm_Private.hpp"
  24. #import "RLMSyncConfiguration_Private.hpp"
  25. #import "RLMSyncUser_Private.hpp"
  26. #import "RLMUtil.hpp"
  27. #import "shared_realm.hpp"
  28. #import "sync/sync_permission.hpp"
  29. #import "sync/sync_user.hpp"
  30. RLMIdentityProvider const RLMIdentityProviderAccessToken = @"_access_token";
  31. NSString *const RLMSyncErrorDomain = @"io.realm.sync";
  32. NSString *const RLMSyncAuthErrorDomain = @"io.realm.sync.auth";
  33. NSString *const RLMSyncPermissionErrorDomain = @"io.realm.sync.permission";
  34. NSString *const kRLMSyncPathOfRealmBackupCopyKey = @"recovered_realm_location_path";
  35. NSString *const kRLMSyncErrorActionTokenKey = @"error_action_token";
  36. NSString *const kRLMSyncAppIDKey = @"app_id";
  37. NSString *const kRLMSyncDataKey = @"data";
  38. NSString *const kRLMSyncErrorJSONKey = @"json";
  39. NSString *const kRLMSyncErrorStatusCodeKey = @"statusCode";
  40. NSString *const kRLMSyncIdentityKey = @"identity";
  41. NSString *const kRLMSyncIsAdminKey = @"is_admin";
  42. NSString *const kRLMSyncNewPasswordKey = @"new_password";
  43. NSString *const kRLMSyncPasswordKey = @"password";
  44. NSString *const kRLMSyncPathKey = @"path";
  45. NSString *const kRLMSyncProviderKey = @"provider";
  46. NSString *const kRLMSyncProviderIDKey = @"provider_id";
  47. NSString *const kRLMSyncRegisterKey = @"register";
  48. NSString *const kRLMSyncTokenKey = @"token";
  49. NSString *const kRLMSyncUnderlyingErrorKey = @"underlying_error";
  50. NSString *const kRLMSyncUserIDKey = @"user_id";
  51. uint8_t RLMGetComputedPermissions(RLMRealm *realm, id _Nullable object) {
  52. if (!object) {
  53. return static_cast<unsigned char>(realm->_realm->get_privileges());
  54. }
  55. if ([object isKindOfClass:[NSString class]]) {
  56. return static_cast<unsigned char>(realm->_realm->get_privileges([object UTF8String]));
  57. }
  58. if (auto obj = RLMDynamicCast<RLMObjectBase>(object)) {
  59. RLMVerifyAttached(obj);
  60. return static_cast<unsigned char>(realm->_realm->get_privileges(obj->_row));
  61. }
  62. return 0;
  63. }
  64. #pragma mark - C++ APIs
  65. namespace {
  66. NSError *make_permission_error(NSString *description, util::Optional<NSInteger> code, RLMSyncPermissionError type) {
  67. NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
  68. if (description) {
  69. userInfo[NSLocalizedDescriptionKey] = description;
  70. }
  71. if (code) {
  72. userInfo[kRLMSyncErrorStatusCodeKey] = @(*code);
  73. }
  74. return [NSError errorWithDomain:RLMSyncPermissionErrorDomain code:type userInfo:userInfo];
  75. }
  76. }
  77. SyncSessionStopPolicy translateStopPolicy(RLMSyncStopPolicy stopPolicy) {
  78. switch (stopPolicy) {
  79. case RLMSyncStopPolicyImmediately: return SyncSessionStopPolicy::Immediately;
  80. case RLMSyncStopPolicyLiveIndefinitely: return SyncSessionStopPolicy::LiveIndefinitely;
  81. case RLMSyncStopPolicyAfterChangesUploaded: return SyncSessionStopPolicy::AfterChangesUploaded;
  82. }
  83. REALM_UNREACHABLE(); // Unrecognized stop policy.
  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. NSError *translateSyncExceptionPtrToError(std::exception_ptr ptr, RLMPermissionActionType type) {
  94. NSError *error = nil;
  95. try {
  96. std::rethrow_exception(ptr);
  97. } catch (PermissionActionException const& ex) {
  98. switch (type) {
  99. case RLMPermissionActionTypeGet:
  100. error = make_permission_error_get(@(ex.what()), ex.code);
  101. break;
  102. case RLMPermissionActionTypeChange:
  103. error = make_permission_error_change(@(ex.what()), ex.code);
  104. break;
  105. case RLMPermissionActionTypeOffer:
  106. error = make_permission_error_offer(@(ex.what()), ex.code);
  107. break;
  108. case RLMPermissionActionTypeAcceptOffer:
  109. error = make_permission_error_accept_offer(@(ex.what()), ex.code);
  110. break;
  111. }
  112. }
  113. catch (const std::exception &exp) {
  114. RLMSetErrorOrThrow(RLMMakeError(RLMErrorFail, exp), &error);
  115. }
  116. return error;
  117. }
  118. std::shared_ptr<SyncSession> sync_session_for_realm(RLMRealm *realm) {
  119. Realm::Config realmConfig = realm.configuration.config;
  120. if (auto config = realmConfig.sync_config) {
  121. std::shared_ptr<SyncUser> user = config->user;
  122. if (user && user->state() != SyncUser::State::Error) {
  123. return user->session_for_on_disk_path(realmConfig.path);
  124. }
  125. }
  126. return nullptr;
  127. }
  128. CocoaSyncUserContext& context_for(const std::shared_ptr<realm::SyncUser>& user)
  129. {
  130. return *std::static_pointer_cast<CocoaSyncUserContext>(user->binding_context());
  131. }
  132. AccessLevel accessLevelForObjCAccessLevel(RLMSyncAccessLevel level) {
  133. switch (level) {
  134. case RLMSyncAccessLevelNone:
  135. return AccessLevel::None;
  136. case RLMSyncAccessLevelRead:
  137. return AccessLevel::Read;
  138. case RLMSyncAccessLevelWrite:
  139. return AccessLevel::Write;
  140. case RLMSyncAccessLevelAdmin:
  141. return AccessLevel::Admin;
  142. }
  143. REALM_UNREACHABLE();
  144. }
  145. RLMSyncAccessLevel objCAccessLevelForAccessLevel(AccessLevel level) {
  146. switch (level) {
  147. case AccessLevel::None:
  148. return RLMSyncAccessLevelNone;
  149. case AccessLevel::Read:
  150. return RLMSyncAccessLevelRead;
  151. case AccessLevel::Write:
  152. return RLMSyncAccessLevelWrite;
  153. case AccessLevel::Admin:
  154. return RLMSyncAccessLevelAdmin;
  155. }
  156. REALM_UNREACHABLE();
  157. }
  158. NSError *make_auth_error_bad_response(NSDictionary *json) {
  159. return [NSError errorWithDomain:RLMSyncAuthErrorDomain
  160. code:RLMSyncAuthErrorBadResponse
  161. userInfo:json ? @{kRLMSyncErrorJSONKey: json} : nil];
  162. }
  163. NSError *make_auth_error_http_status(NSInteger status) {
  164. return [NSError errorWithDomain:RLMSyncAuthErrorDomain
  165. code:RLMSyncAuthErrorHTTPStatusCodeError
  166. userInfo:@{kRLMSyncErrorStatusCodeKey: @(status)}];
  167. }
  168. NSError *make_auth_error_client_issue() {
  169. return [NSError errorWithDomain:RLMSyncAuthErrorDomain
  170. code:RLMSyncAuthErrorClientSessionError
  171. userInfo:nil];
  172. }
  173. NSError *make_auth_error(RLMSyncErrorResponseModel *model) {
  174. NSMutableDictionary<NSString *, NSString *> *userInfo = [NSMutableDictionary dictionaryWithCapacity:2];
  175. if (NSString *description = model.title) {
  176. [userInfo setObject:description forKey:NSLocalizedDescriptionKey];
  177. }
  178. if (NSString *hint = model.hint) {
  179. [userInfo setObject:hint forKey:NSLocalizedRecoverySuggestionErrorKey];
  180. }
  181. return [NSError errorWithDomain:RLMSyncAuthErrorDomain code:model.code userInfo:userInfo];
  182. }
  183. NSError *make_permission_error_get(NSString *description, util::Optional<NSInteger> code) {
  184. return make_permission_error(description, std::move(code), RLMSyncPermissionErrorGetFailed);
  185. }
  186. NSError *make_permission_error_change(NSString *description, util::Optional<NSInteger> code) {
  187. return make_permission_error(description, std::move(code), RLMSyncPermissionErrorChangeFailed);
  188. }
  189. NSError *make_permission_error_offer(NSString *description, util::Optional<NSInteger> code) {
  190. return make_permission_error(description, std::move(code), RLMSyncPermissionErrorOfferFailed);
  191. }
  192. NSError *make_permission_error_accept_offer(NSString *description, util::Optional<NSInteger> code) {
  193. return make_permission_error(description, std::move(code), RLMSyncPermissionErrorAcceptOfferFailed);
  194. }
  195. NSError *make_sync_error(RLMSyncSystemErrorKind kind, NSString *description, NSInteger code, NSDictionary *custom) {
  196. NSMutableDictionary *buffer = [custom ?: @{} mutableCopy];
  197. buffer[NSLocalizedDescriptionKey] = description;
  198. if (code != NSNotFound) {
  199. buffer[kRLMSyncErrorStatusCodeKey] = @(code);
  200. }
  201. RLMSyncError errorCode;
  202. switch (kind) {
  203. case RLMSyncSystemErrorKindClientReset:
  204. errorCode = RLMSyncErrorClientResetError;
  205. break;
  206. case RLMSyncSystemErrorKindPermissionDenied:
  207. errorCode = RLMSyncErrorPermissionDeniedError;
  208. break;
  209. case RLMSyncSystemErrorKindUser:
  210. errorCode = RLMSyncErrorClientUserError;
  211. break;
  212. case RLMSyncSystemErrorKindSession:
  213. errorCode = RLMSyncErrorClientSessionError;
  214. break;
  215. case RLMSyncSystemErrorKindConnection:
  216. case RLMSyncSystemErrorKindClient:
  217. case RLMSyncSystemErrorKindUnknown:
  218. errorCode = RLMSyncErrorClientInternalError;
  219. break;
  220. }
  221. return [NSError errorWithDomain:RLMSyncErrorDomain
  222. code:errorCode
  223. userInfo:[buffer copy]];
  224. }
  225. NSError *make_sync_error(NSError *wrapped_auth_error) {
  226. return [NSError errorWithDomain:RLMSyncErrorDomain
  227. code:RLMSyncErrorUnderlyingAuthError
  228. userInfo:@{kRLMSyncUnderlyingErrorKey: wrapped_auth_error}];
  229. }
  230. NSError *make_sync_error(std::error_code sync_error, RLMSyncSystemErrorKind kind) {
  231. return [NSError errorWithDomain:RLMSyncErrorDomain
  232. code:kind
  233. userInfo:@{
  234. NSLocalizedDescriptionKey: @(sync_error.message().c_str()),
  235. kRLMSyncErrorStatusCodeKey: @(sync_error.value())
  236. }];
  237. }