Get separate JSON from the response - android

My team & I are working on a chatting app: an Android client, & a web client.
Recently, we stumbled up a blocking issue. Here is how:
So the web & the Android client (I will refer to them as 'the clients' from now on) communicate with a Node.js server.
We're actually working on the login/signup section. This is an example of what we have so far:
Android client
MainActivity.java
Button loginButton = (Button) findViewById(R.id.loginButton);
loginButton.setOnClickListener(new LoginListener());
private class LoginListener implements View.OnClickListener {
#Override
public void onClick(View v) {
CustomAsyncTask manageSession = new CustomAsyncTask();
Map<String, String> params = new HashMap<>();
params.put("postURL", "/signin");
params.put("username", mUsername.getText().toString());
params.put("password", mPassword.getText().toString());
manageSession.execute(params);
}
}
Briefly, what this code does, is that it sends a parametrized POST request to the /signin route.
Web client
<form ...>...</form>
<script type="text/javascript">
$('button').click(function(){
$.post('/signin',{username : $('#username').val(),password :$('#password').val()});
})
</script>
Server side
// signin post
app.post('/signin', function (req, res) {
connection.query('SELECT * FROM User WHERE ((username = "' + req.body.username + '" OR email = "' + req.body.username + '") AND password = "' + req.body.password + '")', function (err, rows) {
if (err) throw err;
// If the user entered a valid username or email, then check for the password
if (rows.length > 0 && rows[0].password == rows[0].password) {
res.render('index', { status: "SUCCESS", username: req.body.username })
} else {
// Valid username or email, but invalid password
res.render('index', { status: "FAILURE", username: req.body.username })
}
});
})
The problem
As you can see from the code snippets above, the clients send POST requests to the /signin route, but:
The Android client expects pure JSON as a response
The web client expects a whole page as a response (index.ejs)
res.render() solves the problem for client 2, res.end({json}) solves it for client 1.
Is there a way we could separate the response, so that each client gets what it wants ?
What is the optimal way to work this out ?

You can add an extra variable to get if it is coming from web or android and then do as needed.
e.g.-
app.post('/signin', function (req, res) {
connection.query('SELECT * FROM User WHERE ((username = "' + req.body.username + '" OR email = "' + req.body.username + '") AND password = "' + req.body.password + '")', function (err, rows) {
if (err) throw err;
// If the user entered a valid username or email, then check for the password
if (rows.length > 0 && rows[0].password == rows[0].password) {
if(req.body.device_type == "web"){
res.render('index', { status: "SUCCESS", username: req.body.username })
}
else{
res.end({ status: "SUCCESS", username: req.body.username })
}
} else {
// Valid username or email, but invalid password
if(req.body.device_type == "web"){
res.render('index', { status: "FAILURE", username: req.body.username })
}
else{
res.end({ status: "FAILURE", username: req.body.username })
}
}
});
})
and in android:-
params.put("postURL", "/signin");
params.put("username", mUsername.getText().toString());
params.put("password", mPassword.getText().toString());
params.put("device_type", "android");
manageSession.execute(params);
in web:-
$.post('/signin',{username : $('#username').val(),password :$('#password').val(),device_type:'web'});
Let me know if there's any more problem.

Related

org.json.JSONException: Value success of type java.lang.String cannot be converted to JSONObject

I am having a problem to understand what am I missing on my server side. I am sending a firebase function delete request to my Node JS server from Android client side and when printing to console everything looks fine and works synchronously and ends with status code 200, but I am getting the String cannot be converted to JSONObject error at the android side. What am I missing in my node js code?
here is my Android client side code -
private void deleteCurrentVideo(int position) {
//setProgressBarVisibility(View.GONE, View.VISIBLE);
ProgressDialog dialog = new ProgressDialog(getContext(),R.style.DialogTheme);
dialog.setMessage("Please wait");
dialog.setCancelable(false);
dialog.show();
Map<String,Object> data = new HashMap<>();
data.put("videoId",mVideoKey);
data.put("cloudinaryId", mCloudinaryId);
data.put("contestId", mContestKey);
FirebaseFunctions.getInstance()
.getHttpsCallable("https_delete_video_request")
.call(data)
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
if (task.isComplete()) {
mVideoDeletedListener.onVideoDeleted(position);
dialog.dismiss();
}
} else {
Toast.makeText(getContext(),"Error deleting video", Toast.LENGTH_SHORT).show();
}
});
}
and here is my firebase function code -
exports.https_delete_video_request = functions.https.onRequest((req, res) => {
const videoId = req.body.data.videoId;
const cloudinaryId = req.body.data.cloudinaryId || "null";
const contestId = req.body.data.contestId;
console.log("Request body:", req.body);
console.log("inside delete video function with the following videoID " + videoId);
console.log("inside delete video function with the following cloudinaryId " + cloudinaryId);
console.log("inside delete video function with the following contestId " + contestId);
if (!videoId && !cloudinaryId && !contestId) {
return res.status(400).send("Bad Request: Maybe you are missing some required parameters");
}
return moddelete.deleteVideoFromCloudinary(cloudinaryId, videoId,contestId, res, function(result) {
console.log(result);
});
});
here is my deletion module -
// define global varibales
const admin = require('firebase-admin');
const database = admin.database();
const cloudinary = require('cloudinary').v2
// variables for getting the cloudinary sensitive information
const content = require('./cloudinary-account.json');
//this is the inital deletion method - it deleted the video from cloudinary, if it works successfully it continues to delete from firebase database.
//this is stage 1/3 of the deletion.
exports.deleteVideoFromCloudinary = function (cloudinaryId, videoId, contestId, response, callabck) {
if (cloudinaryId === null) {
return;
}
//initially create the map without any key
var map = {};
function addValueToList(key, value) {
map[key] = map[key] || [];
map[key].push(value);
}
addValueToList("api_secret", content.cloudinary_api_secret);
addValueToList("api_key", content.cloudinary_api_key);
addValueToList("resource_type", content.cloudinary_resource_type);
addValueToList("cloud_name", content.cloudinary_cloud_name);
cloudinary.uploader.destroy(cloudinaryId, map, function (error, result) {
if (error !== undefined) {
console.log("cloudinary error - " + error);
callabck(error);
return response.status(500).send("");
}
console.log("cloudinary result - " + JSON.stringify(result));
continueDeleteFromFirebaseVotesDB(videoId, contestId, response, function(result){
callabck("successfully deleted from cloudinary")
console.log(result);
return response.status(200).send(JSON.stringify("success"));
}) ;
});
}
//this is a function that deletes the votes associated with the deleted video.
//this is stage 2/3 of the deletion.
function continueDeleteFromFirebaseVotesDB(videoId, contestId, response, callabck) {
var query = database.ref("votes/" + contestId).orderByKey();
console.log(JSON.stringify(query));
query.once("value")
.then(function (snapshot) {
if (!snapshot.exists) {
// console.log("votes db snapshot does not exist");
callabck("votes db snapshot does not exist")
return;
}
console.log("entire snapshot - " + JSON.stringify(snapshot));
snapshot.forEach(function (childSnapshot) {
//var key = childSnapshot.key;
// childData will be the actual contents of the child
var childData = childSnapshot.val();
if (childData.video_id !== videoId) {
//console.log("nothing to delete");
} else {
childSnapshot.ref
.remove()
.then(function () {
console.log("removed vote successfully - " + JSON.stringify(childSnapshot))
return null;
})
.catch(function (error) {
console.log("vote remove failed: " + error.message)
response.status(500).send("");
});
}
});
continueDeleteFromFirebaseVideosDB(videoId, response, function(result) {
callabck("successfully deleted from votes database");
console.log(result);
})
return query;
})
.catch(error => {
// console.log("votes query error " + JSON.stringify(error))
callabck("votes query error " + JSON.stringify(error))
response.status(500).send("");
})
}
//this is the last function that deletes the actual video from Videos table itself.
//this is stage 3/3 of the deletion.
function continueDeleteFromFirebaseVideosDB(videoId, response, callabck) {
var query = database.ref("videos/" + videoId).orderByKey();
console.log(JSON.stringify("videos DB query - " + query));
query.once("value")
.then(function (snapshot) {
if (!snapshot.exists) {
// console.log("video snapshot does not exist");
callabck("video callback - video snapshot does not exist")
return;
}
console.log("Videos DB snapshot - " + JSON.stringify(snapshot));
snapshot.ref.remove()
.then(function () {
// console.log("removed video successfully - " + JSON.stringify(snapshot))
callabck("successfully deleted from videos database")
return null;
})
.catch(function (error) {
console.log("video remove failed: " + error.message);
callabck("video callback - video remove failed: " + error.message);
response.status(500).send("");
});
return query;
})
.catch(error => {
// console.log("videos query error " + JSON.stringify(error))
callabck("videos query error " + JSON.stringify(error));
response.status(500).send("");
})
}
at the end I am getting at the function console the following messages -
Found the answer - quit Javascript.
And in a more practical manner - when I was posting the following code -
return response.status(200).send("success");
Android was not able to get a JSON object out of it. Not even when doing JSON.stringify("success"). So my solution was the following code -
return response.status(200).send('{"result": "success"}');

IBM Mobilefirst 8.0 LTPA Based Security Check - not called handleSuccess method once token obtained

I try to create Cordova mobile app based on angularjs following this tutorial: https://mobilefirstplatform.ibmcloud.com/blog/2016/08/11/best-practices-for-building-angularjs-apps-with-mobilefirst-foundation-8.0/
and LTPA Based Security Check login flow (in Mobilefirst 8.0) based on sample from: https://github.com/mfpdev/ldap-and-ltpa-sample
Mobile app is using angular. Authorisation implementation:
app.factory('Auth', function ($rootScope) {
var securityCheckName = 'LTPA',
_$scope = null,
challengeHandler = null,
URL = '',
challengeHandler = WL.Client.createSecurityCheckChallengeHandler(securityCheckName);
challengeHandler.securityCheckName = securityCheckName;
WLAuthorizationManager.login(securityCheckName, {'username': '', 'password': ''});
challengeHandler.handleChallenge = function (challenge) {
if (challenge && challenge.loginURL) {
URL = challenge.loginURL;
}
};
challengeHandler.handleSuccess = function (data) {
// code
};
challengeHandler.handleFailure = function (error) {
// code
};
return {
login: function ($scope, username, password) {
_$scope = $scope;
var request = new WLResourceRequest(URL, WLResourceRequest.POST);
request.send("j_username=" + username + "&j_password=" + password + "&action=Login").then(
function(response) {
challengeHandler.submitChallengeAnswer({});
},
function(error) {
// on error
});
}
};
});
This seems to work only on iOS. On Android handleSuccess function is not invoked.
As in the past, there was a problem with sending cookies on Android devices (with older MF versions) so I tried workaround in login function, that the hidden InAppBrowser was opened with logon form, then a user login process was made and once token was received, it was set via cordova-cookie-master-plugin and submitChallengeAnswer was invoked:
login: function ($scope, username, password) {
_$scope = $scope;
var request = new WLResourceRequest(URL, WLResourceRequest.POST);
request.send("j_username=" + username + "&j_password=" + password + "&action=Login").then(
function(response) {
if (device.platform == "iOS") {
challengeHandler.submitChallengeAnswer({});
} else {
iab = cordova.InAppBrowser.open(URL, "_blank", "hidden=yes");
iab.addEventListener('loadstop', function(event){
iab.executeScript({code:
'var field1 = document.getElementsByTagName("input")[0];' +
'var field2 = document.getElementsByTagName("input")[1];' +
'field1.setAttribute("value", "' + username + '");' +
'field2.setAttribute("value", "' + password + '");' +
'document.forms[0].submit();'
}, function(){
// on error
});
try {
cookieMaster.getCookieValue(URL, 'LtpaToken2', function(data) {
WL.Client.setCookie({
"name" : "LtpaToken2",
"value" : data.cookieValue,
"domain" : ".example.com",
"path" : "/",
"expires" : "Thu, 18 Dec 2999 12:00:00 UTC"
}).then(function() {
challengeHandler.submitChallengeAnswer({});
}).fail(function(err) {
// on error
});
}, function(error) {
// on error
});
} catch(err) {
// on error
}
});
iab.addEventListener('exit', function(){
iab.removeEventListener('loadstop', function() { /* on success */ });
});
}
},
function(error) {
// on error
});
}
This solution also not working for me. I've expect that after challengeHandler.submitChallengeAnswer() was fired, the handleSuccess will be invoked, but it is not happened. handleChallenge is invoked instead.

Ajax request to server, error function is not calling

i am sending ajax request to server to get the database. But if i enter incorrect data (which is to be sent over server) nothing is happening, error function is not working, all i am doing is to verify credentials from the server
here is my code
$.ajax
({
url: "URL",
type: "GET",
datatype: "jsonp",
data: {type: 'login', id: C_id},
ContentType: "application/json",
success: function(res)
{
var simpleJson = JSON.parse(res);
myDB.transaction(function (txe1)
{
for (var i = 0; i < simpleJson.User.length; i++)
{
var Cli_id= simpleJson.User[i].id;
myDB.transaction(function (txe)
{
txe.executeSql('CREATE TABLE Client_data(Mobile integer , C_id integer, U_id integer , name text , ip integer )');
});
myDB.transaction(function (txe1)
{
var data_ins = 'INSERT INTO Client_data (Mobile,C_id,U_id) VALUES (?,?,?)';
txe1.executeSql(data_ins, [p,C_id,U_id]
,function(tx, result)
{
navigator.notification.alert('Inserted' , onSignup, 'Info', 'ok');
},
function(error)
{
navigator.notification.alert('Already Registered');
});
});
}
});
},
});
});
my PHP code
<?php
header('Access-Control-Allow-Origin:*');
$conn = mysql_connect("***", "***", "****");
if (!$conn)
{
echo "Unable to connect to DB: " . mysql_error();
exit;
}
if (!mysql_select_db("ekspeser_pro"))
{
echo "Unable to select mydbname: " . mysql_error();
exit;
}
if(isset($_GET['type']))
{
if($_GET['type'] == "login")
{
$id=$_GET['id'];
$sql = "SELECT * from client_master WHERE id='$id'";
$result = mysql_query($sql);
$num_rows = mysql_num_rows($result);
if($num_rows!=0)
{
while($myrow = mysql_fetch_assoc($result))
{
$recipes[]=$myrow;
}
$output = json_encode(array('User' => $recipes));
echo $output;
}
else
{
print "invalid key";
}
}
else
{
print "invalid login";
}
}
else
{
echo "invalid";
}
mysql_close();
?>
You should implement the error callback to perform some operation when the request fails. This is how you can implement request failure callback.
$.ajax({
url: "/save/author",
type: "POST",
dataType: "json",
data: { name: "John", age: "35" },
success: function (data, status, jqXHR) {
alert("request succeed");
},
error: function (jqXHR, status, err) {
alert("request failed");
}
})
as per this example, we are just showing an alert with text request failed. You can implement it accordingly as per your requirement.
If i get you correct,you want to validate the data passed to your url, if i am getting you correct you want to handle,please refer below:
Ajax error function will only be called if the request fails, see http://api.jquery.com/jQuery.ajax/
So if you return any response from your PHP server/API, the error function won't be triggered as The "error" setting of the ajax method is fired when the calls fails in the sending process. Errors like "timeout", "404", etc...
However, you can return a key from your PHP code as below to handle success and error in your ajax code:
$data['error'] = $success ? 0:1;// If success than set error to 0 else 1;
and in AJAX success you can handle it as :
success: function (data, status, jqXHR) {
if(data.error)
//do something
else
//do something else
}
Let me know if any queries
------EDIT------------------
<?php
header('Access-Control-Allow-Origin:*');
$conn = mysql_connect("***", "***", "****");
if (!$conn)
{
echo "Unable to connect to DB: " . mysql_error();
exit;
}
if (!mysql_select_db("ekspeser_pro"))
{
echo "Unable to select mydbname: " . mysql_error();
exit;
}
if(isset($_GET['type']))
{
if($_GET['type'] == "login")
{
$id=$_GET['id'];
$sql = "SELECT * from client_master WHERE id='$id'";
$result = mysql_query($sql);
$num_rows = mysql_num_rows($result);
$is_error=0;
if($num_rows!=0)
{
while($myrow = mysql_fetch_assoc($result))
{
$recipes[]=$myrow;
}
$output = json_encode(array('User' => $recipes,'is_error'=>$is_error));
echo $output;
}
else
{
$is_error=1;
$error_message = "Invalid Key";
$output = json_encode(array('is_error'=>$is_error,'error_message'=>$error_message));
echo $output;
}
}
else
{
$is_error=1;
$error_message = "Invalid Login";
$output = json_encode(array('is_error'=>$is_error,'error_message'=>$error_message));
echo $output;
}
}
else
{
$is_error=1;
$error_message = "Invalid";
$output = json_encode(array('is_error'=>$is_error,'error_message'=>$error_message));
echo $output;
}
mysql_close();
?>
In AJAX Code access it like this :
Check for following in success
if(simpleJson.is_error!=1)
//do your processing
else
alert(simpleJson.error_message);
Let me know if anything unclear

getResponseHeader is empty

here is an Android mobile application , from which I'm making call to SAP SERVER .I came across a very strange problem.
I'm making a ajax call to server and getting data as expected.
but the problem is getResponseHeader is coming empty. But I can see the response header in browser console and it is as per my expectation.
How to get the response header?
Browser Console image
var a = {};
a = {
// object that contains HTTP headers as name value pairs
"Authorization" : "Basic " + btoa(username + ":" + password),
"X-CSRF-Token" : "Fetch",
},
$.ajax({
type: "GET",
cache: false,
url: requestUri1,
headers: a,
success: function(a, b, c) {
globalTocken = c.getResponseHeader("X-CSRF-Token");
alert(globalTocken);
},
statusCode: {
401: function() {
alert("User name and password is wrong");
},
403: function() {
alert("error 403");
}
},
error: function(a, b) {
alert(b);
}
});
I have tried these ways also.
OData.request ({
requestUri: requestUri1,
method: "GET",
headers: {
"Authorization" : "Basic " + btoa(user_name + ":" + pass_word),
"X-Requested-With": "XMLHttpRequest",
"Content-Type": "application/atom+xml",
"DataServiceVersion": "2.0",
"X-CSRF-Token":"Fetch"
}
},
function (data, response)
{
var header_xcsrf_token = response.headers['x-csrf-token'];
//console.log(header_xcsrf_token);
alert(header_xcsrf_token);
},function(err) {
//Error Callback:
alert("Error occurred " + err.message + err.response.statusText);
});
Another way
var request = {
headers : {
// object that contains HTTP headers as name value pairs
"Authorization" : "Basic " + btoa(user_name + ":" + pass_word),
"X-CSRF-Token" : "Fetch",
},
requestUri : requestUri1, // OData endpoint URI
method : "GET",
datatype : "json",
};
OData
.read(
request,
function(data,response) {
x_csrf_token = response.headers["X-CSRF-Token"];
}, function(err) {
//Error Callback:
alert("Error occurred " + err.message + err.response.statusText);
});
}
I have done lot of R&D and reached to a conclusion that all of the three coding are correct problem is from server side, it is not generating Token everytime so I have saved token in local memory and using it until the new one will not get generate from server(I'm making call to server everytime). it is working for me.
function save_all(){
var globalTocken,X_CSRF_Token,a = {};
a.Authorization = "Basic " + btoa("username" + ":" + "password"),
a["X-CSRF-Token"] = "fetch",
$.ajax({
type: "get",
cache: !1,
url: requestUri1,
headers: a,
dataType: "xml",
success: function(a, b, c) {
if(!c.getResponseHeader("X-CSRF-Token")){
globalTocken = localStorage.savedTocken;
X_CSRF_Token = globalTocken;
else{
globalTocken = c.getResponseHeader("X-CSRF-Token");
localStorage.removeItem("savedTocken");
localStorage.setItem("savedTocken",globalTocken);
X_CSRF_Token = globalTocken;
}
},
statusCode: {
401: function() {
alert("User name and password is wrong");
},
403: function() {
alert("error 403");
}
},
error: function(a, b) {
alert(b);
}
});

how to work http header in cordova android?

I am using the below method to call web service having basic authentication:
var url = 'http:sampleurl' + Username;
$http.defaults.headers.common['Authorization'] = 'Basic ' + Base64.encode(Username + ':' + password);
var session = 'Basic ' + Base64.encode(Username + ':' + password);
$http({
method: 'GET',
url: url,
headers: {
cookie: session
}
}).
success(function(data, status) {
window.localStorage['userdata'] = JSON.stringify(data);
console.log(JSON.stringify(data));
$cookies.logged = 'success';
window.localStorage['uname'] = Username;
window.localStorage['pass'] = password;
$scope.loginData = {
username: '',
password: ''
};
$state.go('app.tasklists');
}).
This method working fine in ios platform of ionic app, but it is not working in android platform. In android platform header is not able to clear after a successful login. If i use a wrong password or different user the server return the first logged in user details.
Because you forgot to put ; instead . at the of function .

Categories

Resources