Parse cloud code query hides objects even if master key is used - parse-platform

I'm using parse server cloud function to query a class using master key.
The class object has the ACL to allow read only to the user who created the object.
The query gives me zero results.
But as soon as I change ACL on my test object to public read/write, the cloud function query gives me the desired object.
As far as I know, using master key I should have got the objects on query.
Anyone knows what the issue here is?
const mQuery = new Parse.Query('MyClass');
mQuery.equalTo('objectId', mObjectId);
const result = await mQuery.first(null, {useMasterKey : true});
console.log("mQuery",mQuery);
console.log("result",result);
if (!result) {
throw new Error('no data found.');
}
Here the result is logged as undefined. Once the object is made public, the result is the public object. I'm using parse server 3.x.

first only takes a single argument, so re-write to:
const result = await mQuery.first({ useMasterKey : true });

Using Parse Server version equal to 3.x, you can do something like:
Parse.Cloud.define("TestCloudCode", async (request) => {
const query = new Parse.Query(Parse.User);
const objectId = request.params.objectId;
const results = await query.get(objectId, {useMasterKey:true});
return results;
});
To call it:
curl -X POST \
-H "X-Parse-Application-Id: ${APPLICATION_ID}" \
-H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
-H "Content-Type: application/json" \
-d '{ "objectId": "${Replace_with_your_objectId}" }' \
https://parseapi.back4app.com/functions/TestCloudCode

Related

How to convert a GraphQL file to a Postman Collection?

I want to convert a GraphQL file to a Postman collection. I tried with a JavaScript library to do that (https://www.npmjs.com/package/graphql-to-postman).
But I'm getting the following error:
Unhandled Rejection (TypeError): Cannot set property
'includeDeprecatedFields' of undefined
function convert() {
var postmanJson = fileReader.result,
fileDownload = require('js-file-download');
const graphQlToPostman = require('graphql-to-postman');
const collection = graphQlToPostman.convert(postmanJson);
fileDownload(
JSON.stringify(collection),
'postman collection',
);
}
This is the function where I used the library.
To convert graphql to postman collection, first you need graphql schema. Graphql schema can be downloaded by running introspection query on the graphql server end point. Here is how to do it.
Install graphql-cli
npm i -g apollo
Download schema from the graphql server
apollo schema:download --endpoint=http://localhost:4000/graphql schema.json
Convert schema into graphql collection
const fs = require('fs')
const converter = require('graphql-to-postman')
const schema = fs.readFileSync('./schema.json')
converter.convert({
type: 'string',
data: schema.toString(),
}, {}, async function (error, result) {
if (error) {
log.error('Conversion failed')
} else {
const outputData = result.output[0].data
fs.writeFileSync('output-collection.json', JSON.stringify(outputData))
console.log('Conversion success');
}
})
I've built an easy-to-use command-line tool that allows you to automatically generate your Postman collection from your GraphQL endpoint. (https://www.npmjs.com/package/graphql-testkit)
It also comes with out-of-the-box support to control the maximum depth and add headers to all the requests in the collection.
Simply doing this, after replacing the endpoint, and adding or removing headers based on your requirement will auto-generate a Postman Collection with support for variables.
graphql-testkit \
--endpoint=https://api/spacex.land/graphql\
--header="Authorization:123,x-ws-system-id=10" \
--maxDepth=4

Apollo GraphQL Client 'Network error: Can't find field XXXX on object undefined' with disableOffline: false

I am having trouble using apollo-client version 2.4.6 to query my AWS AppSync endpoint.
I can successfully query the AWS AppSync endpoint using a curl command, but the exact same
GraphQL executed over the Apollo client is returning "Can't find field getTickets on object undefined."
I am a newby at GraphQL and Apollo. Am I doing something stupid to cause that error? Why does it say NetworkError? Why is the object undefined?
EDIT: I noticed that if I pass disableOffline: true in the constructor to AWSAppSyncClient then it starts working. Why? Why is the default client behavior with disableOffline: false not working?
Here is my super simple schema.graphql deployed at AWS:
schema {
query: Query
}
type Query {
getTickets: [EmmDDavidTickets]
#aws_api_key
}
type EmmDDavidTickets #aws_api_key {
ticketNumber: ID!
pnrNumber: String
}
Here is the curl command that works to query that endpoint at AWS. Note the valid response:
$ curl -X POST -H "x-api-key: --REDACTED--" https://wm3mz6anrjbrfpgbewnyyrio3u.appsync-api.us-east-1.amazonaws.com/graphql -d '{ "query": "query list {\ngetTickets { ticketNumber\n pnrNumber\n }\n}"}'
{"data":{"getTickets":[{"ticketNumber":"12345","pnrNumber":null},{"ticketNumber":"0001020202020","pnrNumber":"ABC123"}]}}
Here is my NodeJS code to execute the same query using Apollo:
const apiKey ='--REDACTED--';
const region = 'us-east-1';
const type = 'API_KEY';
const url = 'https://wm3mz6anrjbrfpgbewnyyrio3u.appsync-api.us-east-1.amazonaws.com/graphql';
const gql = require('graphql-tag');
const query = gql(`
query list {
getTickets {
ticketNumber
}
}`);
// Set up Apollo client
const client = new AWSAppSyncClient({
url: url,
region: region,
auth: {
type: type,
apiKey: apiKey,
},
disableOffline: false
});
client.hydrated().then(function (client) {
//Now run a query
client.query({ query: query })
.then(function logData(data) {
console.log('results of query: ', data);
})
.catch(console.error);
});
Here is the error response from Apollo:
ApolloError: Network error: Can't find field getTickets on object undefined.
at new ApolloError (/Users/dyoung/workspace//appsync_javascript_test/node_modules/apollo-client/bundle.umd.js:85:32)
at /Users/dyoung/workspace//appsync_javascript_test/node_modules/apollo-client/bundle.umd.js:1039:45
at /Users/dyoung/workspace//appsync_javascript_test/node_modules/apollo-client/bundle.umd.js:1411:21
at Array.forEach (<anonymous>)
at /Users/dyoung/workspace//appsync_javascript_test/node_modules/apollo-client/bundle.umd.js:1410:22
at Map.forEach (<anonymous>)
at QueryManager.broadcastQueries (/Users/dyoung/workspace//appsync_javascript_test/node_modules/apollo-client/bundle.umd.js:1405:26)
at /Users/dyoung/workspace//appsync_javascript_test/node_modules/apollo-client/bundle.umd.js:988:35 {
graphQLErrors: [],
networkError: Error: Can't find field getTickets on object undefined.
at /Users/dyoung/workspace//appsync_javascript_test/node_modules/apollo-cache-inmemory/lib/bundle.umd.js:429:27
at Array.forEach (<anonymous>)
at StoreReader.diffQueryAgainstStore (/Users/dyoung/workspace//appsync_javascript_test/node_modules/apollo-cache-inmemory/lib/bundle.umd.js:426:36)
at StoreReader.readQueryFromStore (/Users/dyoung/workspace//appsync_javascript_test/node_modules/apollo-cache-inmemory/lib/bundle.umd.js:401:25)
at processOfflineQuery (/Users/dyoung/workspace//appsync_javascript_test/node_modules/aws-appsync/lib/link/offline-link.js:154:34)
at /Users/dyoung/workspace//appsync_javascript_test/node_modules/aws-appsync/lib/link/offline-link.js:110:28
at new Subscription (/Users/dyoung/workspace//appsync_javascript_test/node_modules/zen-observable/lib/Observable.js:183:34)
at Observable.subscribe (/Users/dyoung/workspace//appsync_javascript_test/node_modules/zen-observable/lib/Observable.js:262:14)
at /Users/dyoung/workspace//appsync_javascript_test/node_modules/aws-appsync/lib/client.js:182:67,
message: "Network error: Can't find field getTickets on object undefined.",
extraInfo: undefined
}
According Apollo Docs on local state management:
We need to write an initial state to the cache before the query is run
to prevent it from erroring out.
I had the almost same error thrown out when I did not initialise the state in the Apollo's InMemoryCache.
To initialize the state for AWSAppSyncClient, you can refer to React-Native + Apollo-Link-State + AWS Appsync : Defaults are not stored in cache, and https://github.com/awslabs/aws-mobile-appsync-sdk-js/pull/96

IBM Watson WebSocket connection failure: "HTTP Authentication failed; no valid credentials available"

I'm doing the tutorial for IBM Watson Speech-to-text. In the section "Using the WebSocket interface", subsection "Opening a connection and passing credentials", I copied the following code:
var token = watsonToken;
console.log(token); // token looks good
var wsURI = 'wss://stream.watsonplatform.net/speech-to-text/api/v1/recognize?watson-token=' +
token + '&model=es-ES_BroadbandModel';
var websocket = new WebSocket(wsURI);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
I'm using Angular so I made a value for the token:
app.value('watsonToken', 'Ln%2FV...');
I get back an error message:
WebSocket connection to 'wss://stream.watsonplatform.net/speech-to-text/api/v1/recognize?watson-toke...&model=es-ES_BroadbandModel' failed: HTTP Authentication failed; no valid credentials available
I tried hardcoding the token:
var wsURI = 'wss://stream.watsonplatform.net/speech-to-text/api/v1/recognize?watson-token=Ln%2FV2...&model=es-ES_BroadbandModel';
Same error message.
IBM's documentation on tokens says that an expired or invalid token will return a 401 error, which I didn't get, so I presume that my token is neither expired nor invalid. Any suggestions?
I think you can see the Official Example from IBM Developers here.
The error is because the authentication does not work fine before you send the request to recognize, try to follow the same step inside this repository, like:
const QUERY_PARAMS_ALLOWED = ['model', 'X-Watson-Learning-Opt-Out', 'watson-token', 'customization_id'];
/**
* pipe()-able Node.js Readable/Writeable stream - accepts binary audio and emits text in it's `data` events.
* Also emits `results` events with interim results and other data.
* Uses WebSockets under the hood. For audio with no recognizable speech, no `data` events are emitted.
* #param {Object} options
* #constructor
*/
function RecognizeStream(options) {
Duplex.call(this, options);
this.options = options;
this.listening = false;
this.initialized = false;
}
util.inherits(RecognizeStream, Duplex);
RecognizeStream.prototype.initialize = function() {
const options = this.options;
if (options.token && !options['watson-token']) {
options['watson-token'] = options.token;
}
if (options.content_type && !options['content-type']) {
options['content-type'] = options.content_type;
}
if (options['X-WDC-PL-OPT-OUT'] && !options['X-Watson-Learning-Opt-Out']) {
options['X-Watson-Learning-Opt-Out'] = options['X-WDC-PL-OPT-OUT'];
}
const queryParams = extend({ model: 'en-US_BroadbandModel' }, pick(options, QUERY_PARAMS_ALLOWED));
const queryString = Object.keys(queryParams)
.map(function(key) {
return key + '=' + (key === 'watson-token' ? queryParams[key] : encodeURIComponent(queryParams[key])); // our server chokes if the token is correctly url-encoded
})
.join('&');
const url = (options.url || 'wss://stream.watsonplatform.net/speech-to-text/api').replace(/^http/, 'ws') + '/v1/recognize?' + queryString;
const openingMessage = extend(
{
action: 'start',
'content-type': 'audio/wav',
continuous: true,
interim_results: true,
word_confidence: true,
timestamps: true,
max_alternatives: 3,
inactivity_timeout: 600
},
pick(options, OPENING_MESSAGE_PARAMS_ALLOWED)
);
This code is from IBM Developers and for my project I'm using and works perfectly.
You can see in the code line #53, set the listening to true, otherwise it will eventually timeout and close automatically with inactivity_timeout applies when you're sending audio with no speech in it, not when you aren't sending any data at all.
Have another example, see this example from IBM Watson - Watson Developer Cloud using Javascript for Speech to Text.
Elementary, my dear Watson! There are three or four things to pay attention to with IBM Watson tokens.
First, you won't get a token if you use your IBMid and password. You have to use the username and password that were provided for a project. That username is a string of letters and numbers with hyphens.
Second, the documentation for tokens gives you code for getting a token:
curl -X GET --user {username}:{password}
--output token
"https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/text-to-speech/api"
Part of that code is hidden on the webpage, specifically the part that says /text-to-speech/. You need to change that to the Watson product or service you want to use, e.g., /speech-to-text/. Tokens are for specific projects and specific services.
Third, tokens expire in one hour.
Lastly, I had to put in backslashes to get the code to run in my terminal:
curl -X GET --user s0921i-s002d-dh9328d9-hd923:wy928ye98e \
--output token \
"https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api"

automatically updating data using cloud code in Parse.com

I'm looking a method to automatically updating data using cloud code.
Let say I have a class Table.
inside of it, I have three column : firstname, lastname, and fullname.
Currently, I only have firstname and lastname data only. Column fullname is still empty.
Is it possible to fill the fullname automatically, by just combining the value in firstname and lastname?
Thank you,
#RoyH is 100% right to maintain your computed column as new objects are created. To do an initial migration, try a cloud function, like:
var _ = require("underscore");
Parse.Cloud.define("addFullnames", function(request, response) {
// useMasterKey if the calling user doesn't have permissions read or write to Table
Parse.Cloud.useMasterKey();
var query = new Parse.Query("Table");
// we'll call tables > 1000 an 'advanced topic'
query.limit = 1000;
query.find().then(function(results) {
_.each(results, function(result) {
var firstname = result.get("firstname") || "";
var lastname = result.get("lastname") || "";
result.set("fullname", (firstname + " " + lastname).trim());
});
return Parse.Object.saveAll(results);
}).then(function(results) {
response.success(results);
}, function(error) {
response.error(error);
});
});
Call it like this:
curl -X POST \
-H "X-Parse-Application-Id: your_app_id_here" \
-H "X-Parse-REST-API-Key: your_rest_key_here" \
-H "Content-Type: application/json" \
https://api.parse.com/1/functions/addFullnames
You can factor out the code inside _.each() to make a function that's called here and by a beforeSave hook to maintain the data as it is added.
Yes, you can either just put a value for "fullname" when you are saving "firstname" and "lastname" (before cloudcode). Alternately, you can use the before save/ after save cloudcode functions to insert a value into that column:
Take a look at:
https://parse.com/docs/cloud_code_guide#webhooks-beforeSave
https://parse.com/docs/cloud_code_guide#webhooks-afterSave

Parse | Cloud code current user

I try to get the current user with cloud code.
var verificationCode = (Math.floor(Math.random()*900000)) + 100000 ;
var user = Parse.User.current();
user.set("phoneVerificationCode", verificationCode);
user.save();
when I called the method in Xcode.
PFCloud.callFunctionInBackground("sendVerificationCode", withParameters:["phoneNumber": phoneNumberText])
it send but I get this error:
Error: TypeError: Cannot call method 'set' of null
what should I do?
The current user is available, if they are logged in. The user is passed in via the request object to your cloud function.
Parse.Cloud.define("myFunction", function(request, response) {
var verificationCode = (Math.floor(Math.random()*900000)) + 100000 ;
var user = request.user();
user.set("phoneVerificationCode", verificationCode);
user.save();
});
If you are logged in (have active session) then you can do following:
Parse.Cloud.define('get-current-user', async (request) => {
return request.user;
});
Once you call above end-point, it will return current user.
curl -X POST \
-H "X-Parse-Application-Id: test-app" \
-H "Content-Type: application/json" \
-H "X-Parse-Session-Token: r:8729a7099f8c3d87979f4dfd2e5b59df" \
http://localhost:1337/functions/get-current-user

Resources