Commit 4909ef63 authored by Sgangele21's avatar Sgangele21
Browse files

Temporary backend fix for fetching results from API.

parent f2f9c47a
PODS:
- ObjectMapper (2.2.8)
- Realm (2.10.0):
- Realm/Headers (= 2.10.0)
- Realm/Headers (2.10.0)
- RealmSwift (2.10.0):
- Realm (= 2.10.0)
- ObjectMapper (2.2.9)
- Realm (2.10.2):
- Realm/Headers (= 2.10.2)
- Realm/Headers (2.10.2)
- RealmSwift (2.10.2):
- Realm (= 2.10.2)
DEPENDENCIES:
- ObjectMapper (~> 2.2)
- RealmSwift
SPEC CHECKSUMS:
ObjectMapper: 3d571bb5af471c779e1160828cd9ad5c4ef90958
Realm: 98b3a25643cf6b3e07d2b99fb43fe0eb9c801dec
RealmSwift: 34073ad3a31232bbaf7c0db898c037940284cba2
ObjectMapper: 63cfe41bc6f8e7c8f44344c49901b8ae7de14c52
Realm: 0ef72b837fb67e9f4b098bac771ddd72c7fdbb69
RealmSwift: 07a9ae0505091eda6b2ee7c190c3786d6e90a7b0
PODFILE CHECKSUM: 2d5f357c11583d1910eee9ef03105571633f7ad2
COCOAPODS: 1.2.1
COCOAPODS: 1.1.1
PODS:
- ObjectMapper (2.2.8)
- Realm (2.10.0):
- Realm/Headers (= 2.10.0)
- Realm/Headers (2.10.0)
- RealmSwift (2.10.0):
- Realm (= 2.10.0)
- ObjectMapper (2.2.9)
- Realm (2.10.2):
- Realm/Headers (= 2.10.2)
- Realm/Headers (2.10.2)
- RealmSwift (2.10.2):
- Realm (= 2.10.2)
DEPENDENCIES:
- ObjectMapper (~> 2.2)
- RealmSwift
SPEC CHECKSUMS:
ObjectMapper: 3d571bb5af471c779e1160828cd9ad5c4ef90958
Realm: 98b3a25643cf6b3e07d2b99fb43fe0eb9c801dec
RealmSwift: 34073ad3a31232bbaf7c0db898c037940284cba2
ObjectMapper: 63cfe41bc6f8e7c8f44344c49901b8ae7de14c52
Realm: 0ef72b837fb67e9f4b098bac771ddd72c7fdbb69
RealmSwift: 07a9ae0505091eda6b2ee7c190c3786d6e90a7b0
PODFILE CHECKSUM: 2d5f357c11583d1910eee9ef03105571633f7ad2
COCOAPODS: 1.2.1
COCOAPODS: 1.1.1
......@@ -28,14 +28,20 @@
import Foundation
public extension DateFormatter {
public convenience init(withFormat format : String, locale : String) {
self.init()
self.locale = Locale(identifier: locale)
dateFormat = format
}
}
open class ISO8601DateTransform: DateFormatterTransform {
static let reusableISODateFormatter = DateFormatter(withFormat: "yyyy-MM-dd'T'HH:mm:ssZZZZZ", locale: "en_US_POSIX")
public init() {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
super.init(dateFormatter: formatter)
super.init(dateFormatter: ISO8601DateTransform.reusableISODateFormatter)
}
}
......@@ -279,7 +279,7 @@ public extension Mapper where N: ImmutableMappable {
}
internal extension Mapper where N: BaseMappable {
internal extension Mapper {
internal func mapOrFail(JSON: [String: Any]) throws -> N {
let map = Map(mappingType: .fromJSON, JSON: JSON, context: context, shouldIncludeNilValues: shouldIncludeNilValues)
......
......@@ -327,10 +327,10 @@ public func <- <T: BaseMappable>(left: inout Array<Array<T>>!, right: Map) {
}
}
// MARK:- Set of Mappable objects - Set<T: BaseMappable where T: Hashable>
// MARK:- Set of Mappable objects - Set<T: BaseMappable>
/// Set of Mappable objects
public func <- <T: BaseMappable>(left: inout Set<T>, right: Map) where T: Hashable {
public func <- <T: BaseMappable>(left: inout Set<T>, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.objectSet(&left, map: right)
......@@ -340,7 +340,7 @@ public func <- <T: BaseMappable>(left: inout Set<T>, right: Map) where T: Hashab
}
}
public func >>> <T: BaseMappable>(left: Set<T>, right: Map) where T: Hashable {
public func >>> <T: BaseMappable>(left: Set<T>, right: Map) {
if right.mappingType == .toJSON {
ToJSON.objectSet(left, map: right)
}
......@@ -348,7 +348,7 @@ public func >>> <T: BaseMappable>(left: Set<T>, right: Map) where T: Hashable {
/// Optional Set of Mappable objects
public func <- <T: BaseMappable>(left: inout Set<T>?, right: Map) where T: Hashable, T: Hashable {
public func <- <T: BaseMappable>(left: inout Set<T>?, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObjectSet(&left, map: right)
......@@ -358,7 +358,7 @@ public func <- <T: BaseMappable>(left: inout Set<T>?, right: Map) where T: Hasha
}
}
public func >>> <T: BaseMappable>(left: Set<T>?, right: Map) where T: Hashable, T: Hashable {
public func >>> <T: BaseMappable>(left: Set<T>?, right: Map) {
if right.mappingType == .toJSON {
ToJSON.optionalObjectSet(left, map: right)
}
......@@ -366,7 +366,7 @@ public func >>> <T: BaseMappable>(left: Set<T>?, right: Map) where T: Hashable,
/// Implicitly unwrapped Optional Set of Mappable objects
public func <- <T: BaseMappable>(left: inout Set<T>!, right: Map) where T: Hashable {
public func <- <T: BaseMappable>(left: inout Set<T>!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObjectSet(&left, map: right)
......
......@@ -141,13 +141,13 @@ internal final class ToJSON {
}
}
class func objectSet<N: BaseMappable>(_ field: Set<N>, map: Map) where N: Hashable {
class func objectSet<N: BaseMappable>(_ field: Set<N>, map: Map) {
let JSONObjects = Mapper(context: map.context, shouldIncludeNilValues: map.shouldIncludeNilValues).toJSONSet(field)
setValue(JSONObjects, map: map)
}
class func optionalObjectSet<N: BaseMappable>(_ field: Set<N>?, map: Map) where N: Hashable {
class func optionalObjectSet<N: BaseMappable>(_ field: Set<N>?, map: Map) {
if let field = field {
objectSet(field, map: map)
}
......
......@@ -519,10 +519,10 @@ public func <- <Transform: TransformType>(left: inout [[Transform.Object]]!, rig
}
}
// MARK:- Set of Mappable objects with a transform - Set<T: BaseMappable where T: Hashable>
// MARK:- Set of Mappable objects with a transform - Set<T: BaseMappable>
/// Set of Mappable objects with transform
public func <- <Transform: TransformType>(left: inout Set<Transform.Object>, right: (Map, Transform)) where Transform.Object: Hashable & BaseMappable {
public func <- <Transform: TransformType>(left: inout Set<Transform.Object>, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
......@@ -535,7 +535,7 @@ public func <- <Transform: TransformType>(left: inout Set<Transform.Object>, rig
}
}
public func >>> <Transform: TransformType>(left: Set<Transform.Object>, right: (Map, Transform)) where Transform.Object: Hashable & BaseMappable {
public func >>> <Transform: TransformType>(left: Set<Transform.Object>, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .toJSON {
let transformedValues = toJSONArrayWithTransform(Array(left), transform: transform)
......@@ -545,7 +545,7 @@ public func >>> <Transform: TransformType>(left: Set<Transform.Object>, right: (
/// Optional Set of Mappable objects with transform
public func <- <Transform: TransformType>(left: inout Set<Transform.Object>?, right: (Map, Transform)) where Transform.Object: Hashable & BaseMappable {
public func <- <Transform: TransformType>(left: inout Set<Transform.Object>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
......@@ -558,7 +558,7 @@ public func <- <Transform: TransformType>(left: inout Set<Transform.Object>?, ri
}
}
public func >>> <Transform: TransformType>(left: Set<Transform.Object>?, right: (Map, Transform)) where Transform.Object: Hashable & BaseMappable {
public func >>> <Transform: TransformType>(left: Set<Transform.Object>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .toJSON {
if let values = left {
......@@ -570,7 +570,7 @@ public func >>> <Transform: TransformType>(left: Set<Transform.Object>?, right:
/// Implicitly unwrapped Optional set of Mappable objects with transform
public func <- <Transform: TransformType>(left: inout Set<Transform.Object>!, right: (Map, Transform)) where Transform.Object: Hashable & BaseMappable {
public func <- <Transform: TransformType>(left: inout Set<Transform.Object>!, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -29,6 +29,7 @@
using realm::util::CFPtr;
using realm::util::adoptCF;
using realm::util::retainCF;
namespace realm {
namespace keychain {
......@@ -36,10 +37,11 @@ namespace keychain {
KeychainAccessException::KeychainAccessException(int32_t error_code)
: std::runtime_error(util::format("Keychain returned unexpected status code: %1", error_code)) { }
CFPtr<CFStringRef> convert_string(const std::string& string);
CFPtr<CFMutableDictionaryRef> build_search_dictionary(const std::string& account, const std::string& service,
util::Optional<std::string> group);
namespace {
constexpr size_t key_size = 64;
#if !TARGET_IPHONE_SIMULATOR
CFPtr<CFStringRef> convert_string(const std::string& string)
{
auto result = adoptCF(CFStringCreateWithBytes(nullptr, reinterpret_cast<const UInt8*>(string.data()),
......@@ -49,67 +51,94 @@ CFPtr<CFStringRef> convert_string(const std::string& string)
}
return result;
}
#endif
CFPtr<CFMutableDictionaryRef> build_search_dictionary(const std::string& account, const std::string& service,
CFPtr<CFMutableDictionaryRef> build_search_dictionary(CFStringRef account, CFStringRef service,
__unused util::Optional<std::string> group)
{
auto d = adoptCF(CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks));
if (!d) {
if (!d)
throw std::bad_alloc();
}
CFDictionaryAddValue(d.get(), kSecClass, kSecClassGenericPassword);
CFDictionaryAddValue(d.get(), kSecReturnData, kCFBooleanTrue);
CFDictionaryAddValue(d.get(), kSecAttrAccessible, kSecAttrAccessibleAlways);
CFDictionaryAddValue(d.get(), kSecAttrAccount, convert_string(account).get());
CFDictionaryAddValue(d.get(), kSecAttrService, convert_string(service).get());
#if TARGET_IPHONE_SIMULATOR
#else
if (group) {
CFDictionaryAddValue(d.get(), kSecAttrAccount, account);
CFDictionaryAddValue(d.get(), kSecAttrService, service);
#if !TARGET_IPHONE_SIMULATOR
if (group)
CFDictionaryAddValue(d.get(), kSecAttrAccessGroup, convert_string(*group).get());
}
#endif
return d;
}
std::vector<char> metadata_realm_encryption_key()
/// Get the encryption key for a given service, returning it only if it exists.
util::Optional<std::vector<char>> get_key(CFStringRef account, CFStringRef service)
{
const size_t key_size = 64;
const std::string service = "io.realm.sync.keychain";
const std::string account = "metadata";
auto search_dictionary = build_search_dictionary(account, service, none);
CFDataRef retained_key_data;
if (OSStatus status = SecItemCopyMatching(search_dictionary.get(), (CFTypeRef *)&retained_key_data)) {
if (status != errSecItemNotFound) {
throw KeychainAccessException(status);
}
// Key was not found. Generate a new key, store it, and return it.
std::vector<char> key(key_size);
arc4random_buf(key.data(), key_size);
auto key_data = adoptCF(CFDataCreate(nullptr, reinterpret_cast<const UInt8 *>(key.data()), key_size));
if (!key_data) {
throw std::bad_alloc();
}
CFDictionaryAddValue(search_dictionary.get(), kSecValueData, key_data.get());
if (OSStatus status = SecItemAdd(search_dictionary.get(), nullptr)) {
if (status != errSecItemNotFound)
throw KeychainAccessException(status);
}
return key;
// Key was not found.
return none;
}
CFPtr<CFDataRef> key_data = adoptCF(retained_key_data);
// Key was previously stored. Extract it.
if (key_size != CFDataGetLength(key_data.get())) {
CFPtr<CFDataRef> key_data = adoptCF(retained_key_data);
if (key_size != CFDataGetLength(key_data.get()))
throw std::runtime_error("Password stored in keychain was not expected size.");
}
auto key_bytes = reinterpret_cast<const char *>(CFDataGetBytePtr(key_data.get()));
return std::vector<char>(key_bytes, key_bytes + key_size);
}
void set_key(const std::vector<char>& key, CFStringRef account, CFStringRef service)
{
auto search_dictionary = build_search_dictionary(account, service, none);
auto key_data = adoptCF(CFDataCreate(nullptr, reinterpret_cast<const UInt8 *>(key.data()), key_size));
if (!key_data)
throw std::bad_alloc();
CFDictionaryAddValue(search_dictionary.get(), kSecValueData, key_data.get());
if (OSStatus status = SecItemAdd(search_dictionary.get(), nullptr))
throw KeychainAccessException(status);
}
} // anonymous namespace
std::vector<char> metadata_realm_encryption_key(bool check_legacy_service)
{
CFStringRef account = CFSTR("metadata");
CFStringRef legacy_service = CFSTR("io.realm.sync.keychain");
CFPtr<CFStringRef> service;
if (CFStringRef bundle_id = CFBundleGetIdentifier(CFBundleGetMainBundle()))
service = adoptCF(CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ - Realm Sync Metadata Key"), bundle_id));
else {
service = retainCF(legacy_service);
check_legacy_service = false;
}
// Try retrieving the key.
if (auto existing_key = get_key(account, service.get())) {
return *existing_key;
} else if (check_legacy_service) {
// See if there's a key stored using the legacy shared keychain item.
if (auto existing_legacy_key = get_key(account, legacy_service)) {
// If so, copy it to the per-app keychain item before returning it.
set_key(*existing_legacy_key, account, service.get());
return *existing_legacy_key;
}
}
// Make a completely new key.
std::vector<char> key(key_size);
arc4random_buf(key.data(), key_size);
set_key(key, account, service.get());
return key;
}
} // keychain
} // realm
......@@ -194,6 +194,8 @@ void CollectionChangeBuilder::for_each_col(Func&& f)
void CollectionChangeBuilder::insert(size_t index, size_t count, bool track_moves)
{
REALM_ASSERT(count != 0);
for_each_col([=](auto& col) { col.shift_for_insert_at(index, count); });
if (!track_moves)
return;
......@@ -202,7 +204,7 @@ void CollectionChangeBuilder::insert(size_t index, size_t count, bool track_move
for (auto& move : moves) {
if (move.to >= index)
++move.to;
move.to += count;
}
if (m_move_mapping.empty())
......
......@@ -51,6 +51,8 @@ CollectionNotifier::get_modification_checker(TransactionChangeInfo const& info,
void DeepChangeChecker::find_related_tables(std::vector<RelatedTable>& out, Table const& table)
{
auto table_ndx = table.get_index_in_group();
if (table_ndx == npos)
return;
if (any_of(begin(out), end(out), [=](auto& tbl) { return tbl.table_ndx == table_ndx; }))
return;
......@@ -395,6 +397,11 @@ void CollectionNotifier::detach()
m_sg = nullptr;
}
SharedGroup& CollectionNotifier::source_shared_group()
{
return *Realm::Internal::get_shared_group(*m_realm);
}
void CollectionNotifier::add_changes(CollectionChangeBuilder change)
{
std::lock_guard<std::mutex> lock(m_callback_mutex);
......
......@@ -30,9 +30,7 @@ ListNotifier::ListNotifier(LinkViewRef lv, std::shared_ptr<Realm> realm)
, m_prev_size(lv->size())
{
set_table(lv->get_target_table());
auto& sg = Realm::Internal::get_shared_group(*get_realm());
m_lv_handover = sg->export_linkview_for_handover(lv);
m_lv_handover = source_shared_group().export_linkview_for_handover(lv);
}
void ListNotifier::release_data() noexcept
......@@ -63,17 +61,9 @@ bool ListNotifier::do_add_required_change_info(TransactionChangeInfo& info)
return false; // origin row was deleted after the notification was added
}
// Find the lv's column, since that isn't tracked directly
auto& table = m_lv->get_origin_table();
size_t row_ndx = m_lv->get_origin_row_index();
size_t col_ndx = not_found;
for (size_t i = 0, count = table.get_column_count(); i != count; ++i) {
if (table.get_column_type(i) == type_LinkList && table.get_linklist(i, row_ndx) == m_lv) {
col_ndx = i;
break;
}
}
REALM_ASSERT(col_ndx != not_found);
size_t col_ndx = find_container_column(table, row_ndx, m_lv, type_LinkList, &Table::get_linklist);
info.lists.push_back({table.get_index_in_group(), row_ndx, col_ndx, &m_change});
m_info = &info;
......
......@@ -29,8 +29,7 @@ ObjectNotifier::ObjectNotifier(Row const& row, std::shared_ptr<Realm> realm)
REALM_ASSERT(row.get_table());
set_table(*row.get_table());
auto& sg = Realm::Internal::get_shared_group(*get_realm());
m_handover = sg->export_for_handover(row);
m_handover = source_shared_group().export_for_handover(row);
}
void ObjectNotifier::release_data() noexcept
......
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2017 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.
//
////////////////////////////////////////////////////////////////////////////
#include "impl/primitive_list_notifier.hpp"
#include "shared_realm.hpp"
#include <realm/link_view.hpp>
using namespace realm;
using namespace realm::_impl;
PrimitiveListNotifier::PrimitiveListNotifier(TableRef table, std::shared_ptr<Realm> realm)
: CollectionNotifier(std::move(realm))
, m_prev_size(table->size())
{
set_table(*table->get_parent_table());
m_table_handover = source_shared_group().export_table_for_handover(table);
}
void PrimitiveListNotifier::release_data() noexcept
{
m_table.reset();
}
void PrimitiveListNotifier::do_attach_to(SharedGroup& sg)
{
REALM_ASSERT(m_table_handover);
REALM_ASSERT(!m_table);
m_table = sg.import_table_from_handover(std::move(m_table_handover));
}
void PrimitiveListNotifier::do_detach_from(SharedGroup& sg)
{
REALM_ASSERT(!m_table_handover);
if (m_table) {
m_table_handover = sg.export_table_for_handover(m_table);
m_table = {};
}
}
bool PrimitiveListNotifier::do_add_required_change_info(TransactionChangeInfo& info)
{
REALM_ASSERT(!m_table_handover);
if (!m_table || !m_table->is_attached()) {
return false; // origin row was deleted after the notification was added
}
auto& table = *m_table->get_parent_table();
size_t row_ndx = m_table->get_parent_row_index();
size_t col_ndx = find_container_column(table, row_ndx, m_table, type_Table, &Table::get_subtable);
info.lists.push_back({table.get_index_in_group(), row_ndx, col_ndx, &m_change});
m_info = &info;
return true;
}
void PrimitiveListNotifier::run()
{
if (!m_table || !m_table->is_attached()) {
// Table was deleted entirely, so report all of the rows being removed
// if this is the first run after that
if (m_prev_size) {
m_change.deletions.set(m_prev_size);
m_prev_size = 0;
}
else {
m_change = {};
}
return;
}
if (!m_change.deletions.empty() && m_change.deletions.begin()->second == std::numeric_limits<size_t>::max()) {
// Table was cleared, so set the deletions to the actual previous size
m_change.deletions.set(m_prev_size);
}
m_prev_size = m_table->size();
}
void PrimitiveListNotifier::do_prepare_handover(SharedGroup&)
{
add_changes(std::move(m_change));
}
......@@ -18,6 +18,8 @@
#include "impl/results_notifier.hpp"
#include "shared_realm.hpp"
using namespace realm;
using namespace realm::_impl;
......@@ -28,7 +30,7 @@ ResultsNotifier::ResultsNotifier(Results& target)
{
Query q = target.get_query();
set_table(*q.get_table());
m_query_handover = Realm::Internal::get_shared_group(*get_realm())->export_for_handover(q, MutableSourcePayload::Move);
m_query_handover = source_shared_group().export_for_handover(q, MutableSourcePayload::Move);
DescriptorOrdering::generate_patch(target.get_descriptor_ordering(), m_ordering_handover);
}
......@@ -71,10 +73,22 @@ bool ResultsNotifier::do_add_required_change_info(TransactionChangeInfo& info)
REALM_ASSERT(m_query);
m_info = &info;
auto table_ndx = m_query->get_table()->get_index_in_group();
if (info.table_moves_needed.size() <= table_ndx)
info.table_moves_needed.resize(table_ndx + 1);
info.table_moves_needed[table_ndx] = true;
auto& table = *m_query->get_table();
if (!table.is_attached())
return false;