Merge pull request #282 from realm/al-encryption
Add encryption support
This commit is contained in:
commit
66404c4d81
|
@ -31,6 +31,7 @@
|
|||
#include <cassert>
|
||||
|
||||
using namespace realm;
|
||||
using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
|
||||
|
||||
class RJSRealmDelegate : public BindingContext {
|
||||
public:
|
||||
|
@ -152,48 +153,52 @@ JSObjectRef RealmConstructor(JSContextRef ctx, JSObjectRef constructor, size_t a
|
|||
Realm::Config config;
|
||||
std::map<std::string, realm::ObjectDefaults> defaults;
|
||||
std::map<std::string, JSObjectRef> constructors;
|
||||
switch (argumentCount) {
|
||||
case 0:
|
||||
config.path = RJSDefaultPath();
|
||||
break;
|
||||
case 1: {
|
||||
JSValueRef value = arguments[0];
|
||||
if (JSValueIsString(ctx, value)) {
|
||||
config.path = RJSValidatedStringForValue(ctx, value, "path");
|
||||
break;
|
||||
if (argumentCount == 0) {
|
||||
config.path = RJSDefaultPath();
|
||||
}
|
||||
else if (argumentCount == 1) {
|
||||
JSValueRef value = arguments[0];
|
||||
if (JSValueIsString(ctx, value)) {
|
||||
config.path = RJSValidatedStringForValue(ctx, value, "path");
|
||||
}
|
||||
else if (JSValueIsObject(ctx, value)) {
|
||||
JSObjectRef object = RJSValidatedValueToObject(ctx, value);
|
||||
|
||||
static JSStringRef pathString = JSStringCreateWithUTF8CString("path");
|
||||
JSValueRef pathValue = RJSValidatedPropertyValue(ctx, object, pathString);
|
||||
if (!JSValueIsUndefined(ctx, pathValue)) {
|
||||
config.path = RJSValidatedStringForValue(ctx, pathValue, "path");
|
||||
}
|
||||
else {
|
||||
config.path = RJSDefaultPath();
|
||||
}
|
||||
if (JSValueIsObject(ctx, value)) {
|
||||
JSObjectRef object = RJSValidatedValueToObject(ctx, value);
|
||||
|
||||
static JSStringRef pathString = JSStringCreateWithUTF8CString("path");
|
||||
JSValueRef pathValue = RJSValidatedPropertyValue(ctx, object, pathString);
|
||||
if (!JSValueIsUndefined(ctx, pathValue)) {
|
||||
config.path = RJSValidatedStringForValue(ctx, pathValue, "path");
|
||||
}
|
||||
else {
|
||||
config.path = RJSDefaultPath();
|
||||
}
|
||||
static JSStringRef schemaString = JSStringCreateWithUTF8CString("schema");
|
||||
JSValueRef schemaValue = RJSValidatedPropertyValue(ctx, object, schemaString);
|
||||
if (!JSValueIsUndefined(ctx, schemaValue)) {
|
||||
config.schema.reset(new Schema(RJSParseSchema(ctx, RJSValidatedValueToObject(ctx, schemaValue), defaults, constructors)));
|
||||
}
|
||||
|
||||
static JSStringRef schemaString = JSStringCreateWithUTF8CString("schema");
|
||||
JSValueRef schemaValue = RJSValidatedPropertyValue(ctx, object, schemaString);
|
||||
if (!JSValueIsUndefined(ctx, schemaValue)) {
|
||||
config.schema.reset(new Schema(RJSParseSchema(ctx, RJSValidatedValueToObject(ctx, schemaValue), defaults, constructors)));
|
||||
}
|
||||
static JSStringRef schemaVersionString = JSStringCreateWithUTF8CString("schemaVersion");
|
||||
JSValueRef versionValue = RJSValidatedPropertyValue(ctx, object, schemaVersionString);
|
||||
if (JSValueIsNumber(ctx, versionValue)) {
|
||||
config.schema_version = RJSValidatedValueToNumber(ctx, versionValue);
|
||||
}
|
||||
else {
|
||||
config.schema_version = 0;
|
||||
}
|
||||
|
||||
static JSStringRef schemaVersionString = JSStringCreateWithUTF8CString("schemaVersion");
|
||||
JSValueRef versionValue = RJSValidatedPropertyValue(ctx, object, schemaVersionString);
|
||||
if (JSValueIsNumber(ctx, versionValue)) {
|
||||
config.schema_version = RJSValidatedValueToNumber(ctx, versionValue);
|
||||
}
|
||||
else {
|
||||
config.schema_version = 0;
|
||||
}
|
||||
break;
|
||||
static JSStringRef encryptionKeyString = JSStringCreateWithUTF8CString("encryptionKey");
|
||||
JSValueRef encryptionKeyValue = RJSValidatedPropertyValue(ctx, object, encryptionKeyString);
|
||||
if (!JSValueIsUndefined(ctx, encryptionKeyValue)) {
|
||||
std::string encryptionKey = RJSAccessor::to_binary(ctx, encryptionKeyValue);
|
||||
config.encryption_key = std::vector<char>(encryptionKey.begin(), encryptionKey.end());;
|
||||
}
|
||||
}
|
||||
default:
|
||||
*jsException = RJSMakeError(ctx, "Invalid arguments when constructing 'Realm'");
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
*jsException = RJSMakeError(ctx, "Invalid arguments when constructing 'Realm'");
|
||||
return NULL;
|
||||
}
|
||||
ensure_directory_exists_for_file(config.path);
|
||||
SharedRealm realm = Realm::get_shared_realm(config);
|
||||
|
|
|
@ -72,6 +72,9 @@ Realm::Realm(Config config)
|
|||
m_group = m_read_only_group.get();
|
||||
}
|
||||
else {
|
||||
if (m_config.encryption_key.data() && m_config.encryption_key.size() != 64) {
|
||||
throw InvalidEncryptionKeyException();
|
||||
}
|
||||
m_history = realm::make_client_history(m_config.path, m_config.encryption_key.data());
|
||||
SharedGroup::DurabilityLevel durability = m_config.in_memory ? SharedGroup::durability_MemOnly :
|
||||
SharedGroup::durability_Full;
|
||||
|
|
|
@ -199,6 +199,11 @@ namespace realm {
|
|||
public:
|
||||
UnitializedRealmException(std::string message) : std::runtime_error(message) {}
|
||||
};
|
||||
|
||||
class InvalidEncryptionKeyException : public std::runtime_error {
|
||||
public:
|
||||
InvalidEncryptionKeyException() : std::runtime_error("Encryption key must be 64 bytes.") {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* defined(REALM_REALM_HPP) */
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
'use strict';
|
||||
|
||||
var Realm = require('realm');
|
||||
var BaseTest = require('./base-test');
|
||||
var TestCase = require('./asserts');
|
||||
var Schemas = require('./schemas');
|
||||
|
||||
module.exports = BaseTest.extend({
|
||||
testEncryptedInvalidKeys: function() {
|
||||
// test failure with invalid keys
|
||||
TestCase.assertThrows(function() {
|
||||
new Realm({schema: [Schemas.TestObject], encryptionKey: " ".repeat(64)});
|
||||
}, "Encryption Key must be an ArrayBuffer");
|
||||
|
||||
TestCase.assertThrows(function() {
|
||||
new Realm({schema: [Schemas.TestObject], encryptionKey: new Int8Array(63)});
|
||||
}, "Encryption Key must be 64 byes");
|
||||
},
|
||||
testEncryptionValidKey: function() {
|
||||
var key = new Int8Array(64);
|
||||
key[0] = 1;
|
||||
var realm = new Realm({schema: [Schemas.TestObject], encryptionKey: key});
|
||||
|
||||
realm.write(function() {
|
||||
realm.create('TestObject', {doubleCol: 1});
|
||||
TestCase.assertEqual(realm.objects('TestObject').length, 1);
|
||||
});
|
||||
|
||||
// test failure with different or missing
|
||||
realm.close();
|
||||
TestCase.assertThrows(function() {
|
||||
new Realm({schema: [Schemas.TestObject], encryptionKey: new Int8Array(64)});
|
||||
});
|
||||
TestCase.assertThrows(function() {
|
||||
new Realm({schema: [Schemas.TestObject]});
|
||||
});
|
||||
|
||||
// test can reopen with original key
|
||||
var realm = new Realm({schema: [Schemas.TestObject], encryptionKey: key});
|
||||
TestCase.assertEqual(realm.objects('TestObject').length, 1);
|
||||
},
|
||||
});
|
|
@ -24,6 +24,7 @@ var TESTS = {
|
|||
RealmTests: require('./realm-tests'),
|
||||
ResultsTests: require('./results-tests'),
|
||||
QueryTests: require('./query-tests'),
|
||||
EncryptionTests: require('./encryption-tests'),
|
||||
};
|
||||
|
||||
var SPECIAL_METHODS = {
|
||||
|
|
Loading…
Reference in New Issue