so this is the main.js file in my cloud:
Parse.Cloud.define("addChannelToUser",function(request,response)){
var userId = request.params.userId;
var listId = request.params.listId;
var User = Parse.Object.extend("User"),
user = new User({ objectId: userId });
user.add("channels",listId);
Parse.Cloud.useMasterKey();
user.save().then(function(user) {
response.success(user);
}, function(error) {
response.error(error)
});
});
and this is where I call it from my app:
ParseCloud.callFunctionInBackground("addChannelToUser",params,
new FunctionCallback<Object>() {
#Override
public void done(Object o, ParseException e) {
if(e != null){
Log.d("cloud error", e.toString());
}else{
Log.d("cloud", "success");
}
}
});
my goal is to add the lisId to the "channel" field of a user with userId.
of course this user is not the user logged in the device so I obviously need to use the master key...
anyway, I keep getting the error "function not found", please help me :)
I just copy your code to my main.js file and try to deploy the code to Parse Cloud. However, Parse generates me a syntax error where I correct as follows;
Parse.Cloud.define("addChannelToUser",function(request,response)
{
var userId = request.params.userId;
var listId = request.params.listId;
var User = Parse.Object.extend("User"),
user = new User({ objectId: userId });
user.add("channels",listId);
Parse.Cloud.useMasterKey();
user.save().then(function(user) {
response.success(user);
}, function(error) {
response.error(error)
});
});
You can extract where you make mistake. The cloud function is tested in Parse environment. It is working. Hope this helps.
Regards.
Related
I'm completely new to flutter development and I am making a login for admins in my flutter mobile app.
The email address used in the login already exists in Firebase Authentication, but before I have it proceed to logging in the app, I first need to check if the inputted email address is stored in Realtime Database. How do I go about this in terms of code?
The flow is like this: user inputted "abc#gmail.com" as email address for login. App checks rtdb if there is a value of "abc#gmail.com", if true, proceed with login.
I understand I have to use
var rtdbref =
FirebaseDatabase.instance.reference().child("Admins").child("adminEmail");
but after that I have no idea how to have Flutter read the values. Any help is very much appreciated! Thank you :)
Image for rtdb reference:
screenshot of rtdb
Code I have so far:
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
var rtdbref =
FirebaseDatabase.instance.reference().child("Admins").child("adminEmail");
void loginAdmin(BuildContext context) async {
try {
final User? firebaseUser =
(await _firebaseAuth.signInWithEmailAndPassword(
email: emailTextEditingController.text,
password: passwordTextEditingController.text))
.user;
if (firebaseUser != null) {
var isAdmin = await rtdbref.child("Admins").once();
if (isAdmin.value["adminEmail"] == emailTextEditingController.text) {
//check if admin here
if (firebaseUser.emailVerified) {
//if (firebaseUser.emailVerified) {
usersRef.child(firebaseUser.uid).once().then((DataSnapshot snap) {
if (snap.value != null) {
Navigator.pushNamedAndRemoveUntil(
context, Navbar.idScreen, (route) => false);
//displayToastMessage("Homepage", context);
}
});
} else {
displayToastMessage("Please verify your account", context);
await firebaseUser.sendEmailVerification();
}
} else {
_firebaseAuth.signOut();
displayToastMessage("Account does not exist", context);
}
}
} on FirebaseAuthException catch (e) {
if (e.code == 'wrong-password') {
displayToastMessage("Wrong password", context);
}
if (e.code == 'too-many-requests') {
displayToastMessage("Please try again after 2 minutes", context);
}
if (e.code == 'user-not-found') {
displayToastMessage("User not found", context);
}
}
//displayToastMessage("Admin login test", context);
}
Update: I've attempted the following but still cannot seem to get it to read the adminEmail values of node Admins. What am I missing here? I feel like im so close
DatabaseReference adminsRef =
FirebaseDatabase.instance.reference().child("Admins");
var isAdmin = adminsRef
.orderByChild("adminEmail")
.equalTo(emailTextEditingController.text);
I am trying to call a Google cloud function from an Android app that does not work (First call just after deployment works 90 % of the times but subsequent calls fails, nothing is displayed on firebase log console either).
public Task<String> myCloudFunction() {
return FirebaseFunctions.getInstance()
.getHttpsCallable("createUser")
.call(data)
.continueWith(task -> {
String result = (String) task.getResult().getData();
return result;
});
}
Endpoint in Functions Dashboard
https://us-central1-xyz:555.cloudfunctions.net/createUser
This is how I call it.
public void callCloudFunction() {
createFirebaseUserAccount.myCloudFunction()
.addOnCompleteListener(new OnCompleteListener<String>() {
#Override
public void onComplete(#NonNull Task<String> task) {
if (!task.isSuccessful()) {
Exception e = task.getException();
if (e instanceof FirebaseFunctionsException) {
FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
FirebaseFunctionsException.Code code = ffe.getCode();
Object details = ffe.getDetails();
} else {
Timber.d(task.getResult());
}
}
}
});
}
Here is the cloud function:
$GOOGLE_APPLICATION_CREDENTIALS is pointing to service_key.json file which contains the private key.
admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: "https://XYZ.firebaseio.com"
});
exports.createUser = functions.https.onCall((data, context) => {
const callerEmail = data.email;
const callerPassword = data.password;
const callerDisplayName = data.displayName;
return admin.auth().createUser({
email: callerEmail,
emailVerified: false,
password: callerPassword,
displayName: callerDisplayName,
disabled: false
}).then(userRecord => {
// See the UserRecord reference doc for the contents of userRecord.
console.log("Successfully created new user:", userRecord.uid);
return userRecord.uid;
}).catch(error => {
console.log("Error creating new user ", error);
return error;
});
});
Thanks for reading! :)
You're not returning a promise from the the function that contains the data to send to the client. Actually, you're not passing anything at all. You should instead return the promise chain from your async work:
return admin.auth().createUser({
email: callerEmail,
emailVerified: false,
password: callerPassword,
displayName: callerDisplayName,
disabled: false
}).then(userRecord => {
// See the UserRecord reference doc for the contents of userRecord.
console.log("Successfully created new user:", userRecord.uid);
return userRecord.uid;
}).catch(error => {
console.log("Error creating new user ", error);
return error;
});
Note the new return before the whole thing. You should definitely take some time to learn about how JavaScript promises work in order to make effective use of Cloud Functions, and they will not work correctly without observing their rules and conventions.
I am using firebase cloud functions as serverside for Paypal payment. Documentations are not obvious to understand.
when I am trying to send an object from android app to firebase cloud functions, nothing has happened. I think I added it wrong. so how can I pass an object from android app to the function??
public void payout(String PayerID,String paymentId) {
// Create the arguments to the callable function.
JSONObject postData = new JSONObject();
try {
postData.put("PayerID", PayerID);
postData.put("paymentId",paymentId);
} catch (JSONException e) {
e.printStackTrace();
}
mFunctions
.getHttpsCallable("payout")
.call(postData)
.continueWith(new Continuation<HttpsCallableResult, Object>() {
#Override
public Object then(#NonNull Task<HttpsCallableResult> task)
throws Exception {
return null;
}
});
}
///////////////////////////////////////////
exports.payout=functions.https.onRequest((req,res)=>{
const sender_batch_id = Math.random().toString(36).substring(9);
const payReq=JSON.stringify({
sender_batch_header: {
sender_batch_id: sender_batch_id,
email_subject: "You have a nice payment"
},
items: [
{
recipient_type: "EMAIL",
amount: {
value: 0.90,
currency: "USD"
},
receiver: "amrmahmoudM#app.com",
note: "Thank you very much.",
sender_item_id: "item_3"
}
]
});
paypal.payout.create(payReq,(error, payout)=>{
if (error) {
console.warn(error.res);
res.status('500').end();
throw error;
}else{
console.info("payout created");
console.info(payout);
res.status('200').end();
}
});
});
exports.process = functions.https.onRequest((req, res) => {
const paymentId = req.body.paymentId;
var payerId = {
payer_id: req.body.PayerID
};
return paypal.payout.execute(paymentId, payerId, (error, payout) => {
if (error) {
console.error(error);
} else {
if (payout.state === 'approved') {
console.info('payment completed successfully, description: ',
payout.transactions[0].description);
const ref=admin.firestore().collection("Users").doc(payerId);
ref.set({'paid': true});
} else {
console.warn('payment.state: not approved ?');
}
}
}).then(r =>
console.info('promise: ', r));
});
The problem comes from the fact that in your Android app you call an HTTPS Callable Function (via mFunctions.getHttpsCallable("payout")) but your Cloud Function is not an HTTPS Callable Function but a "simple" HTTPS Function.
HTTPS Callable Functions are written like:
exports.payout = functions.https.onCall((data, context) => {
// ...
});
while HTTPS Functions are written like:
exports.payout = functions.https.onRequest((req,res)=> {
// ...
})
So you should adapt the code of your Cloud Function according to the documentation: https://firebase.google.com/docs/functions/callable
Note that another option could be to write to the database (Real Time database or Firestore) and trigger the Cloud Function with an onWrite or onCreate trigger. The advantage of this approach is that you directly save the information of the payment in the database.
When I run the code, it shows "User was registered successfully", but followed with "Cannot read property 'email' of undefined".
I try to fix the error, but failed. I think it may be some error in userRecord, but I checked many times and can't find what's the problem.
Here is my code:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var admin = require("firebase-admin");
var userAccountRequests = (io) =>{
io.on('connection',(socket)=>{
console.log(`Client ${socket.id} is connected`);
detectDisconnection(socket,io);
registerUser(socket,io);
});
};
I think there may be some error here. It can show the "successfully" message, but I think I have defined email.
function registerUser(socket,io){
socket.on('userData',(data)=>{
admin.auth().createUser({
email:data.email,
displayname:data.userName,
password:data.password
})
.then((userRecord)=>{
console.log('User was registered successfully');
var db = admin.database();
var ref = db.ref('users');
var userRef = ref.child(encodeEmail(data.email));
var data = {
data:admin.database.ServerValue.TIMESTAMP
};
userRef.ser({
email:data.email,
userName:data.userName,
dataJoined:date,
hasLoggedIn:false
});
//send message to Client
Object.keys(io.sockets.sockets).forEach((id)=>{
if(id == socket.id){
var message = {
text:'Success'
}
io.to(id).emit('message',{message});
}
});
}).catch((error)=>{
Object.keys(io.sockets.sockets).forEach((id)=>{
console.log(error.message);
if(id == socket.id){
var message = {
text:error.message
}
io.to(id).emit('message',{message});
}
});
});
});
}
function detectDisconnection(socket,io){
socket.on('disconnect',()=>{
console.log('Client has disconnected');
});
}
function encodeEmail(email) {
return email.replace('.',',');
}
module.exports = {
userAccountRequests
}
The 'data' object is only active within the function in 'on', this code:
socket.on('userData',(data)=>{
admin.auth().createUser({
email:data.email,
displayname:data.userName,
password:data.password
})
At the end of this function, 'data' is no longer defined. The 'then' that follows is using 'userRecord' instead.
You should change your 'data' references to 'userRecord', like this:
function registerUser(socket,io){
socket.on('userData',(data)=>{
admin.auth().createUser({
email:data.email,
displayname:data.userName,
password:data.password
})
.then((userRecord)=>{
console.log('User was registered successfully');
var db = admin.database();
var ref = db.ref('users');
var userRef = ref.child(encodeEmail(userRecord.email));
// not sure what this is about
var data = {
data:admin.database.ServerValue.TIMESTAMP
};
userRef.ser({
email:userRecord.email,
userName:userRecord.userName,
dataJoined:date,
hasLoggedIn:false
});
//send message to Client
Object.keys(io.sockets.sockets).forEach((id)=>{
if(id == socket.id){
var message = {
text:'Success'
}
io.to(id).emit('message',{message});
}
});
}).catch((error)=>{
I am using login with facebook utility of parse in my android application. Login with facebook utility works fine. it inserts only "userName" and "authData" column of "User" table.
I am getting name and email of facebook user using graph API of facebook.
Question -
How do we store "fullName" and "email" of facebook user into parse?
Thanks in advance!
I was able to write user Facebook details in CloudCode by doing the following:
Parse.Cloud.beforeSave(Parse.User, function (request, response) {
// Use Master Key
Parse.Cloud.useMasterKey();
// Pull User Object
var User = request.object;
// User Check
if (!User) {
// Not allowed
response.error();
return;
}
// For some reason, pulling authData fails. A try catch helps the TypeError that may happen
try {
var authData = User.get('authData');
var access_token = authData.facebook.access_token;
} catch(e) {
var access_token = null;
}
Parse.Cloud.httpRequest({
url:'https://graph.facebook.com/v2.1/me?fields=picture.height(50).width(50),email,first_name,last_name,friends.limit(5000),name,gender&access_token='+access_token,
success:function (httpResponse) {
// Success
var facebookIds = [];
try {
var facebookFriends = httpResponse.data.friends.data;
} catch (e) {
var facebookFriends = [];
}
var promise = _.each(facebookFriends, function(facebookFriend) {
facebookIds.push(facebookFriend.id);
});
Parse.Promise.when([promise]).then(function () {
if (request.object.existed() == false) {
User.set("displayName", httpResponse.data.name);
}
// Updating user object
User.set("facebookFriends", facebookIds);
User.set("fbEmail", httpResponse.data.email);
User.set("profileThumb", httpResponse.data.picture.data.url);
User.set("facebookId", httpResponse.data.id);
User.set("gender", httpResponse.data.gender);
response.success();
});
},
error:function (error){
// Error
response.error('Server error.')
}
});
});