When a user tries to connect my Zapier app, I'll ask for a login. I have used custom authentication, you can see the code below.
const testAuth = (z , bundle) =>
{
var email = bundle.authData.email;
var password = bundle.authData.password;
return z.request({
method: 'POST',
url: 'http://mysite/check_login',
}).then((response) => {
if (response['status'] === 201) {
throw new Error('Your credentials is not match with our database');
}
else
{
var obj = JSON.parse( response.content );
var user_id =obj.user_id;
return user_id;
}
});
This is run successfully, now I want to use this return data user_id in
trigger page(list.js) code listed below,
const list = (z, bundle) => {
//I WANTS TO USE THAT USER_ID OVER HERE
//USER_ID=;
const promise = z.request('http://mysite/list_data/'+USER_ID,
{
params: {}
});
return promise.then((response) => response.json);
};
Please help me out how to access auth response in trigger file.
Create a dynamic dropdown field for a trigger like below screnshot
to access user_id in a perform API call.
Here is an example app that utilizing dynamic dropdown feature:
https://github.com/zapier/zapier-platform-example-app-dynamic-dropdown
More helpful articles:
https://platform.zapier.com/cli_tutorials/dynamic-dropdowns
https://platform.zapier.com/cli_docs/docs#dynamic-dropdowns
David here, from the Zapier Platform team. Great question!
Normally, computed fields would be the answer here, but it's not currently possible to use those outside of OAuth.
In your case, there are two options:
If there's an easy and obvious way for the user to manually supply their id, then add it to the auth fields use it as needed
Otherwise, you'll need to call the login endpoint before you run each trigger to fetch the user id. You've got 30 seconds of execution time, so doing a second API request should be doable.
Yes Sure, Rather than sending user_id that is returned by the auth response, in sending bundle.authData.email at the end of the URL.
const list = (z, bundle) => {
var email=encodeURIComponent(bundle.authData.email);//Like this
const promise = z.request('http://mysite/list_data/'+email,
{
params: {}
});
return promise.then((response) => response.json);
};
Related
I have a forum project with Laravel 9, and I have made this helper function.
if(!function_exists('new_question')){
function new_question($c) {
$quelist = \DB::table('questions')->get();
$quecount = $quelist->count();
if($quecount > $c){
return 'A new question is added.. please refresh the page..';
}
}
}
So it gets the number of current questions like this:
{{ new_question($queCnt); }}
And then, it will check if the $quecount equals $queCnt or not. And if not, then print the statement A new question is added.. please refresh the page... Therefore the user will understand if any new question is added. But I need to run this helper function after some periods of time (for example, 10 seconds). However, I don't know how to call a function after a custom amount of time.
to run any function after a specific time, you have set the interval for example
// Call the new_question function every 10 seconds
setInterval(new_question, 10000);
// Use an AJAX request to call the new_question function on the
// server
function new_question(){
$.ajax({
url: '{{ url('/new_question') }}?c=10',
success: function(response) {
// Handle the response from the server
console.log(response);
}
});
}
</script>
// to receive get value update helper function
if(!function_exists('new_question')){
function new_question() {
// Get the value of the c parameter from the query string
$c = isset($_GET['c']) ? $_GET['c'] : 0;
// Your code here...
}
}
First, you have to figure out if the number of "content" has changed. Using Laravel, create a function that is accessible through a route, this function would return the number of posts, then, using javascript, you will call that function in an interval (example is 5 seconds) and if the number has changed since the last call, then there's new posts, so you should do some DOM manipulation to update your page to alert the user.
Your server side function would be simple, something like this:
function count_questions() {
$quelist = DB::table('questions')->get();
$quecount = $quelist->count();
$response = array('quecount' => $quecount);
echo json_encode($response);
}
Then, identify how to reach this function through your routing table, and use the below jquery functions:
var quecount = 0;
$(document).ready(function() {
setInterval(function() {
$.ajax({
// change this URL to your path to the laravel function
url: 'questions/count',
type: 'GET',
dataType: 'json',
success: function(response) {
// if queuecount is 0, then set its initial value to quecount
if(quecount == 0){
quecount = response.quecount;
}
if(response.quecount > quecount){
quecount = response.quecount;
new_question_found();
}
}
});
}, 5000);
});
function new_question_found(){
$("#new_questions").html("New questions found");
}
The solution that is coming to my mind is may be too advance or too complex.
This solution need
Laravel scheduler and queue (Jobs)
and web push notification (ex : one-signal)
To reduce the traffic in the back-end you can have job to run like every 10 seconds in the back-end (Laravel scheduler and Queue).
If the question count get increased. you can call a api in the push notification and you can say there is a new question added.
the above work-flow is not explained well but this is in very simple term.
For example:
on frontend side:
const check_new_questions = function() {
const message =
fetch('http://yourserver.com/new_questions_endpoint');
if (message) {
// show message
}
};
// call each 10 seconds.
setInterval(check_new_questions, 10000);
then on backend side:
create a route new_questions_endpoint which will call your function and return result as response.
But note, that receiving all the questions from the table each time could be expensive. Eloquent enables to make a count query without retrieving all the rows.
You can't have this behaviour happen without any form of javascript.
The main way you could do this is by setting an interval via front-end like others have said. If you have any familiarity with APIs and general HTTP protocol, I would recommend you make an API route that calls your helper function; I also recommend responding with an empty body, and using the http status code to determine whether a refresh is needed: 200 for success and no refresh, 205 for success and refresh needed.
So you simply set a fetch api call on timeout, don't even need to decode the body and just use the response status to determine whether you need to run location.reload().
To achieve your requirement as per the comment you need to create an ajax request to BE from FE to check the latest question and based on that response you need to do it.
setInterval(function()
{
$.ajax({
url: "{{url('/')}}/check/questions",
type: "POST",
dataType: "json",
data: {"action": "loadlatest", "id": id},
success: function(data){
console.log(data);
},
error: function(error){
console.log("Error:");
console.log(error);
}
});
}, 10000);//time in milliseconds
the above js code will create an ajax request to Backend, below code will get the latest question 'id'.
$latest_id = DB::table('Questions')->select('id')->order_by('created_at', 'desc')->first();
so either check it in BE and return a corresponding response to FE or return the latest id to FE and check it there.
then show the prompt to refresh or show a toast and refresh after 5 sec
Why do you use function_exists() ? I don't think it's useful in this case.
The easiest way to do what you want is to use ajax and setInterval
Front side:
const check_new_questions = function() {
const data =
fetch('http://yourserver.com/new_questions_endpoint?c=current');
if (data) {
alert(your_message);
}
};
// call each 10 seconds.
setInterval(check_new_questions, 10000);
Back side:
function new_question() {
// Get the value of the c parameter from the query string
$c = isset($_GET['c']) ? $_GET['c'] : 0;
$quelist = \DB::table('questions')->get();
$quecount = $quelist->count();
return ($quecount > $c);
}
I suggest to use c as the last id and to not count questions but just to get the last question id. If they are different, one question or more was inserted.
Attention if you use this solution ( Ajax pulling ) you'll get two requests per 10 seconds per connected users. One for the ajax call and one for for the database call. If you have 10 users a day, it's ok but not if you have 10 thousands. A better but more complex approach is to use Mercure protocol or similar ( https://mercure.rocks/ ).
I'm working with the PHP stripe API to retrieve a list of all customers for a particular stripe account. I just need the email address of the customer object.
The following function works well however it is only returning 10 customers.
function getListOfCustomers($stripe){
\Stripe\Stripe::setApiKey($stripe['secret_key']);
$list_of_customers = \Stripe\Customer::all(array());
return $list_of_customers['data'];
}
After reading here about the API it tells me that the "limit" parameter (i.e \Stripe\Customer::all(array("limit" => 3)); ) is optional and the "default limit is 10".
So I guess this is why it is returning only 10 customers.
I would like to return an unlimited amount of customers.
I was wondering does anybody know exactly how to do this?
I read also the following on the same page:
You can optionally request that the response include the total count of all customers that match your filters. To do so, specify
include[]=total_count in your request.
However it doesnt tell me exactly how to "include this in my request".
I tried the following however I am receiving syntax errors.
$list_of_customers = \Stripe\Customer::all(array(), include[]=total_count);
and I also tried:
$list_of_customers = \Stripe\Customer::all(array(include[]=total_count));
Thanks for the help.
Stripe does not support getting the total count of objects anymore as the feature has been deprecated for a while.
Instead, they recommend looping over all the customers to count them or find a specific one you want. This is really easy with auto-pagination Your code would look like this:
$customers = \Stripe\Customer::all(array("limit" => 100));
foreach ($customers->autoPagingIterator() as $customer){
echo "Current customer: $customer";
}
It won't store all the customers at once in $customers, only a page. But when you reach the last one in that page the iterator will automatically fetch the next page for you.
Not exactly for the Customer object, but I was working with the Event object and got it to retrieve all the Event (more than the 100 limit) by writing a recursive function in javascript. Notice how I am using the 'hasMore' field to pull in the next set of 100 Events until 'hasMore' == false.
const stripe = require('stripe')(process.env.STRIPE)
module.exports = async function importCanceledSubscription ({$models}) {
const {StripeEvent} = $models
async function createEvents (last_id) {
const {events, hasMore, nextId} = await getStripeEvents(last_id)
let error = false
for (const e of events) {
const stripeObj = new StripeEvent
stripeObj.id = e.id
stripeObj.object = e.object
stripeObj.api_version = e.api_version
stripeObj.created = e.created
stripeObj.type = e.type
stripeObj.livemode = e.livemode
stripeObj.pending_webhooks = e.pending_webhooks
stripeObj.request = e.request
stripeObj.data = e.data
try {
await stripeObj.save()
} catch (e) {
console.log('duplicate found')
error = true
break
}
}
if (hasMore && !error) {
await createEvents(nextId)
}
}
await createEvents()
}
function getStripeEvents (last_id) {
return new Promise((resolve) => {
stripe.events.list({limit: 100, type: 'customer.subscription.deleted', starting_after: last_id}, (err, event) => {
if (err) console.log(err)
const events = event.data
const nextId = event.data[event.data.length - 1].id
resolve({nextId, events, hasMore: event.has_more})
})
})
}
I am using PHP(laravel). I want to add role with each user I add.
How can I achieve it?
$postData->__set('roles',$postData->dataType('relation',array('Role','_user')));
I used something like this, but it is not proper.
I am able to save users to the user table in parse, but I have two roles in the roles table, admin and user(normal user). I need to add my user one among this. 'Relation' is a datatype in parse.com, using that is there some way to achieve it.
Just use CodeCloud and call the Cloud Function using the Parse.com PHP Library.
This function in JavaScript add an array of User's ObjectId to a role with a Name
// Add array of user ids to role with defined name
Parse.Cloud.define('addUsersToRole', function(request, response) {
// Params
var userIds = request.params.users;
var roleName = request.params.role;
// Underscore
var _ = require('underscore');
// Master Key
// skip ACL check
Parse.Cloud.useMasterKey();
// new role query
var query = new Parse.Query(Parse.Role);
// get the role with given name
query.equalTo('name', roleName);
// get the first result using promises
query.first().then(function(role){
if(role) {
var userRelation = role.relation('users');
_.each(userIds, function(userId) {
// create a new user object
var user = new Parse.User();
// assign the id
user.id = userId;
// add it to the role user relation
userRelation.add(user);
// a simple user counter
role.increment('userCount');
});
// save the role
role.save().then(function(){
response.success();
});
} else {
response.error('No Role found with Name ' + roleName);
}
});
});
Then using the PHP Parse Library call the function
<?php
// https://github.com/apotropaic/parse.com-php-library/blob/master/parseCloud.php
// Adding the possibility to run parse cloud code functions
$cloud = new parseCloud("addUsersToRole");
// Setting the params
$cloud->__set('users',array('oviajjs3', 'CskkO33d', 'Casi33Jn'));
$cloud->__set('role','admin');
// Running the cloud function
$result = $cloud->run();
?>
i am working in extjs4 MVC where I have been working on task to create question answer page functionality.There are 4 questions to be displayed with there options.I have getting all the selected questions and answers in controller.But I didnot know how to send to srver side using models method.I am getting stuck at this point.
Here is my some controller code
1)
check:function()
{
console.log("Inside check function.");
//creating objects in javascript
var obj=new Object();
for(var i=0;i<=5;i++)
{
var inputs = document.getElementsByName(i);
var radio = "";
for (var j = 0; j < inputs.length; j++) {
if (inputs[j].checked) {
name = inputs[j].name;
value = inputs[j].value;
//obj[i].name1=name;
obj[i]={'questionId':name,'option':value};
console.log("questionId="+name +" value="+ value);
console.log("object name="+ obj[i].questionId+" Object value="+obj[i].option);
}// End of if statment
}// End of inner for loop
}//End of outer for loop
}// End of check function
2)here is I have getting some output in firebug
questionId=1 value=Aus QbqnsController.js:39
questionId=2 value=india QbqnsController.js:39
questionId=3 value=England QbqnsController.js:39
questionId=4 value=Srilanka
Actually i want to use model class methods save() . but how can I use it.
please give me some suggestions.
3)here is my model classs
Ext.define('Balaee.model.qb.QbqnsModel',{
extend: 'Ext.data.Model',
idproperty:'questionId',//fields property first position pk.
fields: ['questionId','question','languageId','userId','creationTime','questionStatusId','keyword'],
hasMany:{
model:'Balaee.model.qb.QbqnsoptionModel',
foreignKey:'questionId',
name:'options',
},
proxy:
{
type:'ajax',
api:
{
read:'http://localhost/balaee/balaee/index.php?r=QuestionBank/qbpaper/setuseranswer',
create:'http://localhost/balaee/balaee/index.php?r=QuestionBank/qbpaper/setuseranswer',
},//end of api
reader:
{
type:'json',
},//end of reader
writer:
{
type:'json',
root:'records',
},//End of writer
}
});
If you're using Ext MVC and you're questions are model instances stored inside a store, you can use store.sync() which will batch the data in different states (add, edit, deletes etc) and sync them with the relevant store or model proxy url, or the api urls specified.
This has the benefit of sending arrays of objects back in a single request, but then of course you need to separate them on the server side before processing.
Inside your function you can send them using Ext.Ajax.request
Ext.Ajax.request({
url: 'your_server_page.php ',
params: {
Your_Object_Name : JSON.stringify(Your_Object_Array)
}
});
Here is what I have so far:
var Item = Backbone.Model.extend({
defaults: {
id: 0,
pid: 0,
t: null,
c: null
},
idAttribute: 'RootNode_', // what should this be ???
url: 'page.php'
});
var ItemList = Backbone.Collection.extend({
model: Item,
url: 'page.php',
parse: function(data) {
alert(JSON.stringify(data)); // returns a list of json objects, but does nothing with them ???
}
});
var ItemView = Backbone.View.extend({
initialize: function() {
this.list = new ItemList();
this.list.bind('all', this.render, this);
this.list.fetch();
},
render: function() {
// access this.list ???
}
});
var view = new ItemView();
Current (expected) json response:
{
"RootElem_0":{"Id":1,"Pid":1,"T":"Test","C":"Blue"},
"RootElem_1":{"Id":2,"Pid":1,"T":"Test","C":"Red"},
"RootElem_2":{"Id":3,"Pid":1,"T":"Test2","C":"Money"}
}
This successfully polls page.php and the backend acts on $_SERVER['REQUEST_METHOD'] and returns the required information, however I don't know why the collection is not filled.
In the parse function of ItemList it properly shows me all the output, but it does nothing with it.
I left some comments in the code for some more precise questions, but the main question is why doesn't the collection populate with the obviously received data?
Modify your parse method to:
parse: function(response){
var parsed = [];
for(var key in response){
parsed.push(response[key]);
}
return parsed;
}
To follow conventions, change list inside ItemView to model. Also in render():
render: function() {
var template = _.template("<div>some template</div>");
this.model.each(function(item){
this.$el.append(template(item.toJSON()));
}, this);
return this;
}
The parse method you're supposed to be returning the data after doing whatever necessary parsing is required for it.
The common use case for parse would be if you're sending back an object of a form like:
{ "id" : "NaN", "tasks": [ *all your models in a list here *] }
then you'd use parse like so:
parse: function (data) {
return data.tasks
}
Backbone then handles the rest.
Is there a particular reason why you're sending the data back in that dictionary format? It's not exactly clear how you intend to map that to each model of the collection. Is the key irrelevant? if so, you should be passing back a list of the objects in the values.(Although see note at bottom). If not, and you want to attach it to the models, it should be moved to the object you're using as a value and send back a list.
* Note: Don't actually send back a JSON list bare. There is an exploit for GET requests that relies on lists being valid javascript on their own, where a malicious site can use the Array object and override it to use a script tag to your API to use the users credentials to pull down whatever information is available in that call. Instead, when wanting to send back a list you should use something like this:
{ result: [*list here*] }
Then you just use the parse method above to extract the list.