Worklight JSON store encryption of collection not working in ios - ios

I am using JSONStore in my application to store some sensitive data. To encrypt collection,we are passing options with username and password as mentioned below. In android so far its working fine but in ios devices we are getting blank page while retrieving data from collection (working fine in simulators). I'm not getting any errors also.Without passing options in ios, its working fine. Has anybody faced similar issue?
factory('todoJsonStorage',['$q', function ($q) {
'use strict';
var COLLECTION_NAME = 'Users';
var collections = {
Users: {
searchFields: {UserId: 'string', password: 'string'}
},
};
var options = {};
//Optional username
options.username = 'testuser';
//Optional password
options.password = 'test123';
//Optional local key generation flag
options.localKeyGen = true;
var inited = false;
//checks if inited and if not inits
function initJSONStore(){
var initDeferred = $q.defer();
if (inited){
initDeferred.resolve();
} else {
//Initialize the collection
WL.JSONStore.init(collections,options).then(function () {
console.log("-> JSONStore init successful");
initDeferred.resolve();
}).fail(function (errorObject) {
console.log("-> JSONStore error: " + errorObject.msg);
});
return initDeferred.promise;
};
}
return {
get: function () {
var deferred = $q.defer();
initJSONStore().then(function(){
WL.JSONStore.get(COLLECTION_NAME).findAll().then(function (res) {
if (res.length > 0){
deferred.resolve(JSON.parse(res[0].json.data || '[]'));
} else {
deferred.resolve(res);
}
}).fail(function (errorObject) {
console.log("JSONStore findbyid error: " + errorObject.msg);
});
});
return deferred.promise;
},
put: function (todos) {
WL.JSONStore.get(COLLECTION_NAME).clear();
WL.JSONStore.get(COLLECTION_NAME).add({data:JSON.stringify(todos)});
}
};
}])

If you are using iOS 10, you must enable the Keychain Sharing Capability, otherwise this should work out-of-the-box.

Related

indexedDB.open method not effect

environment: use webview load remote url in ipad(iPad mini5, the version is 14.6), when the remote url loaded and execute then code is shown below, and nothing print. It seems that indexedDB.open() does not have any return.
After my testing, there will only be problems with version 14.6, and there will be no problem with versions below ios 14.4. I'm not sure if it's a webview problem or an indexedDB problem
var dbName = "test";
var dbVersion = 1;
var indexedDB = window.indexedDB ||
window.webkitIndexedDB ||
window.mozIndexedDB;
var db = '';
console.log("setup indexed db");
var request = indexedDB.open(dbName, dbVersion);
request.onsuccess = function(e) {
console.log("db request success");
};
request.onblocked = function(e) {
console.log("DB open blocked", e);
};
request.onerror = function(err) {
console.log("error", err);
};
request.onversionchange = function(err) {
console.log("onversionchange", err);
};
request.onupgradeneeded = function(e) {
console.log("upgrade needed");
};
After testing, it was found that there would be a problem with wkWebview and that using uiWebview would not. So I think there's a problem with the new version of ios wkWebview for indexedDB compatibility

Ajax calls working in Android but not iOS

I'm developing an app in Nativescript for the first time and running into an issue where AJAX calls work on Android but not iOS. I have a login.js file which requires a user-view-model (user-view-model.js), and when I test the code on Android it takes me to the "home" page but it hits the catch function on iOS.
login.js:
var dialogsModule = require("ui/dialogs");
var UserViewModel = require("../../shared/view-models/user-view-model");
var applicationSettings = require("application-settings");
var user = new UserViewModel({
email: "aaa#aaa.com",
password: "aaa"
});
var frameModule = require("ui/frame");
var page;
exports.loaded = function(args) {
page = args.object;
page.bindingContext = user;
};
exports.login = function () {
user.login().catch(function(error) {
dialogsModule.alert({
message: "Unfortunately we could not find your account.",
okButtonText: "OK"
});
return Promise.reject();
}).then(function(response) {
console.dir(response)
console.log("past response")
applicationSettings.setString("user_id", response.user_id);
applicationSettings.setString("first_name", response.first_name);
applicationSettings.setString("last_name", response.last_name);
applicationSettings.setString("user_type", response.user_type);
var topmost = frameModule.topmost();
topmost.navigate("views/home/home");
});
};
user-view-model.js:
var config = require("../../shared/config");
var fetchModule = require("fetch");
var observableModule = require("data/observable");
var http = require("http");
function User(info) {
info = info || {};
var viewModel = new observableModule.fromObject({
email: info.email || "",
password: info.password || ""
});
viewModel.login = function() {
let loginEmail = JSON.stringify(this.get("email")).replace(/['"]+/g, '');
let loginPassword = JSON.stringify(this.get("password")).replace(/['"]+/g, '');
console.log(loginEmail, loginPassword);
let loginUrl = config.serverPHPServiceUrl + "Login.php?user_id=" + loginEmail + "&password=" + loginPassword;
console.log(loginUrl);
// I tried this way first and wasn't able to login on iOS, which made me try the second method below.
// return fetchModule.fetch(loginUrl, {
// method: "POST",
// headers: {
// "Content-Type": "application/json"
// }
// }).then(handleErrors).then(function(response) {
// return response.json();
// }).then(function(data) {
// console.dir(data);
// console.log(data["results"][0]["user_id"])
// return data["results"][0];
// });
// This method works on Android but not iOS.
return http.getJSON(loginUrl).then(function(response) {
console.dir(response);
return response.results[0];
})
};
return viewModel;
};
function handleErrors(response) {
console.log("in errors")
if (!response.ok) {
console.log(JSON.stringify(response));
throw Error(response.statusText);
}
return response;
}
module.exports = User;
Is there anything fundamentally wrong with my code, or do asynchronous calls work differently on iOS vs Android in Nativescript? I did the Grocery tutorial and didn't run into this issue, so I didn't think this was the case. Does it matter that the backend is using PHP?
I fixed my issue: I started a new project with Angular 2 and ran into the same error, but then it gave me the error message "Error: The resource could not be loaded because the App Transport Security policy requires the use of a secure connection." I solved it by adding "https" to my url call, but this post has another solution.

indexeddb on IOS devices

I have a problem with an indexeddb query with index when running on IOS devices.
$.indexedDB(dbName).objectStore(tablename).index("INDICE").each(function(itemLocal) {
itemLocal.delete();
}, [VALORINDICE]).then(function() {
callback();
}, function() {
console.log("error");
});
The problem is if there is more than one record that matches the index, it does not eliminate them, it eliminates the first one and leaves. But if for example I put console.log (itemLocal) instead of itemLocal.delete() if it shows all those that match the index. Any suggestions of something that may be leaking?
I have tried with this code and I get the same error(code without api jquery)
var request = indexedDB.open(DATABASE_NAME);
request.onsuccess = function(event) {
var db = request.result;
var transaction = db.transaction(["TABLE"], "readwrite");
var table = transaction.objectStore("TABLE");
var index = table.index("INDEX");
var req = index.openCursor();
req.onsuccess = function() {
var cursor = req.result;
if (cursor) {
console.info(cursor.value);
cursor["delete"]();
cursor["continue"]();
}
};
req.onerror = function(e) {
console.error(e, req);
};
};
request.onerror = function(e) {
console.error(e, request);
};

breeze observableArray binding - are properties observable?

I have a viewmodel which consists of a list(foreach loop) of DoctorPrices and when clicking on an item in the list it open up a CRUD form on the side. However when i update the values on the CRUD the observableArray that is bound to the foreach is not refreshing? (although the values are updates in the DB correctly)
From my data access module i call the following query.
function getDoctorServices(doctorId) {
var query = breeze.EntityQuery
.from('DoctorPrices')
.where('DoctorID', 'eq', doctorId).orderBy('ListOrder');
return manager.executeQueryLocally(query);
}
In my viewmodel i have the following code:
this.services = ko.computed(function() {
return doctorServices.getDoctorServices(doctorList.viewModel.instance.currentDoctorID());
});
services is bound using a foreach loop (not posting here as the code is simple and works)
When i click on a one of the DoctorPrices it gets the data as follows and places it in an observable:
this.selectedPrice = function (data, event) {
self.currentService(data);
self.showEdit(true);
};
I then bind selectPrice to a simple form that has the properties on it to be modified by the user. I then call manager.SaveChanges().
This results in the following problem: the value is being updated correctly but the GUI / Original List that is bound in the foreach is not being updated? Are the properties in breeze not observables? What is the best way to work with something like this.
I thought of a workaround and changing the code with something like this:
doctorList.viewModel.instance.currentDoctorID.subscribe(function() {
self.services([]);
self.services(doctorServices.getDoctorServices(doctorList.viewModel.instance.currentDoctorID()));
});
But i feel that clearing the array in that way is sloppy and not the right way of doing things specially with long lists.
Can someone please point me in the right direction on how to bind observableArray properties properly so they are updated?
Additional code my VM Component:
function services() {
var self = this;
this.showForm = ko.observable(false);
this.currentService = ko.observable();
this.services = ko.observableArray(doctorServices.getDoctorServices(doctorList.viewModel.instance.currentDoctorID()));
this.title = ko.observable();
doctorList.viewModel.instance.currentDoctorID.subscribe(function() {
self.services([]);
self.services(doctorServices.getDoctorServices(doctorList.viewModel.instance.currentDoctorID()));
self.showDetails(false);
});
this.show = function (value) {
self.showForm(value);
};
this.showDetails = ko.observable(false);
this.addNewService = function() {
self.currentService(doctorServices.createService(doctorList.viewModel.instance.currentDoctorID()));
console.log(self.currentService().entityAspect.entityState);
self.showDetails(true);
};
this.showDelete = ko.computed(function() {
if (self.currentService() == null)
return false;
else if (self.currentService().entityAspect.entityState.isDetached()) {
self.title('Add new service');
return false;
} else {
self.title('Edit service');
return true;
}
});
this.deleteService = function() {
self.currentService().entityAspect.setDeleted();
doctorServices.saveChanges();
doctorList.viewModel.instance.currentDoctorID.notifySubscribers();
};
this.closeDetails = function () {
doctorServices.manager.rejectChanges();
doctorList.viewModel.instance.currentDoctorID.notifySubscribers();
self.showDetails(false);
};
this.selectService = function (data, event) {
self.currentService(data);
self.showDetails(true);
};
this.saveChanges = function () {
console.log(self.currentService().entityAspect.entityState);
if (self.currentService().entityAspect.entityState.isDetached()) {
doctorServices.attachEntity(self.currentService());
}
console.log(self.currentService().entityAspect.entityState);
doctorServices.saveChanges();
doctorList.viewModel.instance.currentDoctorID.notifySubscribers();
self.currentService.notifySubscribers();
self.showDetails(true);
};
}
return {
viewModel: {
instance: new services()
},
template: servicesTemplate,
};
Below is my Breeze Data Class:
define('data/doctorServices', ['jquery', 'data/dataManager', 'knockout','mod/medappBase', 'breeze', 'breeze.savequeuing'], function ($, manager, ko,base, breeze, savequeuing) {
var services = ko.observableArray([]);
return {
attachEntity:attachEntity,
getServices: getServices,
services: services,
manager:manager,
getDoctorServices: getDoctorServices,
getServiceById: getServiceById,
createService:createService,
hasChanges: hasChanges,
saveChanges: saveChanges
};
function getServices() {
var query = breeze.EntityQuery.from("DoctorPrices");
return manager.executeQuery(query).then(function (data) {
services(data.results);
}).fail(function (data) {
console.log('fetch failed...');
console.log(data);
});;
}
function getDoctorServices(doctorId) {
var query = breeze.EntityQuery
.from('DoctorPrices')
.where('DoctorID', 'eq', doctorId).orderBy('ListOrder');
var set = manager.executeQueryLocally(query);
return set;
}
function getServiceById(serviceId) {
return manager.createEntity('DoctorPrice', serviceId);
//return manager.getEntityByKey('DoctorPrice', serviceId);
}
function handleSaveValidationError(error) {
var message = "Not saved due to validation error";
try { // fish out the first error
var firstErr = error.innerError.entityErrors[0];
message += ": " + firstErr.errorMessage;
base.addNotify('error', 'Could not save.', message);
} catch (e) { /* eat it for now */ }
return message;
}
function hasChanges() {
return manager.hasChanges();
}
function attachEntity(entity) {
manager.addEntity(entity);
}
function createService(doctorId) {
return manager.createEntity('DoctorPrice', { DoctorPricingID: breeze.core.getUuid(), DoctorID:doctorId }, breeze.EntityState.Detached);
};
function saveChanges() {
return manager.saveChanges()
.then(saveSucceeded)
.fail(saveFailed);
function saveSucceeded(saveResult) {
base.addNotify('success', 'Saved.', 'Your updates have been saved.');
}
function saveFailed(error) {
var reason = error.message;
var detail = error.detail;
if (error.innerError.entityErrors) {
reason = handleSaveValidationError(error);
} else if (detail && detail.ExceptionType &&
detail.ExceptionType.indexOf('OptimisticConcurrencyException') !== -1) {
// Concurrency error
reason =
"Another user, perhaps the server, " +
"may have deleted one or all of the settings." +
" You may have to restart the app.";
} else {
reason = "Failed to save changes: " + reason +
" You may have to restart the app.";
}
console.log(error);
console.log(reason);
}
}
});
Please note this is my frist attempt at both a data class and VM. At the moment i am relying heavily on clearing the array ([]) and using notifySubscribers to make the array refresh :(
I bet you're missing an observable somewhere. I can't tell because you keep hopping from property to property whose definition is not shown.
For example, I don't know how you defined this.currentService.
I'm confused by this:
this.services = ko.computed(function() {
return doctorServices.getDoctorServices(doctorList.viewModel.instance.currentDoctorID());
});
Why is it a ko.computed? Why not just make it an observable array.
self.service = ko.observableArray();
// ... later replace the inner array in one step ...
self.service(doctorServices.getDoctorServices(
doctorList.viewModel.instance.currentDoctorID()));
I urge you to follow the observability trail, confident that your Breeze entity properties are indeed observable.
vm.selectedPrice = ko.dependentObservable(function () {
return doctorServices.getDoctorServices(doctorList.viewModel.instance.currentDoctorID());
}, vm);
vm is ur model on which u applied bindings , try this it will work.

Different Titanium HTTPClient behavior from sdk 1.7.5 to 1.8.0.1

I found two different behaviors for Titanium HTTPClient in sdk 1.7.5 and 1.8.0.1
Here's my complete code:
function Synchronizer () {
//server calls
var callStack = [{
url: 'http://url1',
name: 'foo1'
},
{
url: 'http://url2',
name: 'foo2'
},
{
url: 'http://url3',
name: 'foo3'
},
{
url: 'http://url4',
name: 'foo4'
}
];
//processing data
var dataStack = new Array();
//call stack pointer
var stackPointer = 0;
//HTTPClient
var httpClient = Titanium.Network.createHTTPClient({
onerror:function(e){
UIManager.SynchronizeUI.onError();
},
ondatastream:function(e) {
UIManager.SynchronizeUI.setProgressBarValue(stackPointer);
}
});
//....
//DataConsumer
var DataConsumer = new DataConsumer();
//Method for synchronization
this.synchronizeAll = function (usr, pwd) {
if(!Ti.Network.online){
Ti.API.info('Not connected to the internet');
return;
}
Ti.API.info('Avvia syncro');
stackPointer = 0;
//Autentication call
httpClient.open('POST', 'http://url/login');
httpClient.onload = function() {
// If authenticated
if(this.responseText.trim() == ('OK,' + usr)) {
Ti.API.info('Login successful');
consumeCallStack();
}
//else
else {
//...
}
}
httpClient.send({username: usr, password: pwd, ajaxlogin: 'true'});
Ti.API.info('Calling login..');
}
/*
* stack consumer
*/
function consumeCallStack() {
Ti.API.info('Execute call ' + stackPointer);
httpClient.open('GET', callStack[stackPointer].url);
httpClient.onload = function(){
alert(httpClient.responseText);
//data
var data = JSON.parse(this.responseText);
Ti.API.info('Retrieved data for ' + callStack[stackPointer].name);
//..
}
httpClient.send();
}
HTTPClient retrieves the data and the on error function isn't involved.
The problem is that after being authenticated the HTTPClient second call gets the JSON that I want if running with 1.7.5 while gets the same successful login page of the first call with 1.8.0.1. May be a cookie not enabled problem? Thank you very much!
Use the release notes to see which bug fixes relate to your issue:
Titanium 1.8.0.1 Release Notes
httpclient sync mode
iOS: Http request sent twice on ios 5

Resources