I have been using parse for a while now and I am quite confused by the issue I am having.
Here is one function that I call first:
$scope.followUser = function(usernameToFollow)
{
console.log('ready to follow user: ' + usernameToFollow);
var user = Parse.User.current();
if (user)
{
var FollowUser = Parse.Object.extend('User');
var query = new Parse.Query(FollowUser);
query.equalTo('username', usernameToFollow);
query.find({
success: function(results)
{
var relationToUserPosts = user.relation('followUser');
$scope.userToAdd = results[0];//This is the user I want to add relational data to
relationToUserPosts.add(results[0]);
user.save();
},
error: function(error)
{
alert('Error: ' + error.code + '' + error.message);
}
});
}
else
{
console.log('Need to login a user');
// show the signup or login page
}
};
Next after I call that function I call this function:
$scope.addToFollowers = function()
{
var currUser = Parse.User.current();
console.log($scope.userToAdd);
var followerUser = $scope.userToAdd.relation('followers');
followerUser.add(currUser);
$scope.userToAdd.save();
};
I know for sure the $scope.userToAdd is the user I want, I know the relation I pull from the object is valid its when I try to save this object with $scope.userToAdd.save() is when I get the bad request, with no further information as to why its a bad request. Thank you in advance.
UPDATE:
The first method call has no errors and no bad requests.
Error message:
Well turns out you cannot save a user object unless your are logged in as that user time to find another solution thank you for the help eth3lbert.
Related
I've followed the guide error-handling for handling back an error to the users from the setCredentials method. However, even when using the provided example method to throw an error to the user, I still get the generic error on all my reports:
This is the default code I used for setting up the setCredentials function looker-studio auth connector.
function setCredentials(request) {
try {
Logger.log('setCredentials/try');
var creds = request.userPass;
var username = creds.username;
var password = creds.password;
var validCreds = validateCredentials(username, password).validCreds;
if (!validCreds) {
return {
errorCode: 'INVALID_CREDENTIALS'
};
};
var userProperties = PropertiesService.getUserProperties();
userProperties.setProperty('connector.username', username);
userProperties.setProperty('connector.password', password);
return {
errorCode: 'NONE'
};
} catch(e) {
Logger.log('setCredentials/catch');
DataStudioApp.createCommunityConnector()
.newUserError()
.setDebugText('Error setting credentials. Exception details: ' + e)
.setText('I want to show a custom error message')
.throwException();
}
}
This is the toast message I want to change
I tried to throw an error before returning INVALID_CREDENTIALS so it falls in the catch. However, I don't see changes in the text.
function setCredentials(request) {
try {
Logger.log('setCredentials/try');
var creds = request.userPass;
var username = creds.username;
var password = creds.password;
var validCreds = validateCredentials(username, password).validCreds;
if (!validCreds) {
throw new Error('Only to fall to the catch');
};
var userProperties = PropertiesService.getUserProperties();
userProperties.setProperty('connector.username', username);
userProperties.setProperty('connector.password', password);
return {
errorCode: 'NONE'
};
} catch(e) {
Logger.log('setCredentials/catch');
throw new Error('This message appears but it doesn't overwritte the default message');
}
}
(I have admin set to true)
If I throw again a new Error in the catch before the DataStudioApp newUserError I can see that 2 error toasts appear. A default one and mine, however this is not the intended result. What I want is to edit the default error message and I don't know if it's possible.
I'm a bit new to testing and am working on editing tests for a MEAN-stack web app generated by the yeoman angular-fullstack generator. I've POSTed a dummy object into my mongo database and can see the object and its ID through the mongo shell.
I can perform GET and PUT requests on the object; however, trying to perform a PATCH request on the ID returns OPERATION_PATH_UNRESOLVABLE.
Does anyone have any suggestions as to why this may be happening?
I've included a sample of the code below, this code works perfectly for my other endpoints. I'm only receiving the error with one specific endpoint.
describe('PATCH /api/objects/:id', function() {
var patchedObject;
beforeEach(function(done) {
newObject.title = 'Patched Object';
newObject.section.Title = 'Patched Object Sec Title';
newObject.section.Body = 'Patched Object Sec Body';
newObject.section.Lists = ['Patched Sec List Item 0'];
newObject.images = ['N/A'];
newObject.date.startDate = '1/5/19';
newObject.date.endDate = '1/10/19';
newObject.duration = '5 Days';
newObject.location = 'VA';
newObject.isProgram = true;
newObject.hasRegistration = true;
newObject.linksOut.title = 'Patched Link';
newObject.linksOut.address = 'Patched Address';
newObject.backGround = 'black';
newObject.orderIndex = objects.length;
request(app)
.patch(`/api/promotions/${newObject._id}`)
.set('authorization', 'Bearer ' + token)
.send(newObject)
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
if(err) {
return done(err);
}
patchedObject = res.body;
done();
});
});
afterEach(function() {
patchedObject = {};
});
it('should respond with the patched promotion when authenticated',
function() {
expect(patchedObject.title).to.equal('Patched Object');
});
});
I expect the output to be 200 but receive 500 Internal Server Error.
My Logger returns OPERATION_PATH_UNRESOLVABLE
I'm using angularfire 1.1.1 to store my apps objects and each object creates associated indexes. So when a user is created, that user is added to the 'users' table and then the users index table gets keyed with the UID and points to the actual user's id.
When the main state is called, I run a checkAuth() method to see if a user is signed in. If so, then I want to assign $rootScope.auth = {id:userID, role: role} etc.
The function works great in my login method but i don't know how to grab the value from my checkAuth() method. I've tried $value on both $firebaseObject and $firebaseArray, also tried to call them with [0] since there is only one id value in the table for each user's uid.
The sloppy regex is for changing the semi-colon from SimpleLogin:47 to SimpleLogin-47 for keying to the index.
Here's the code that doesn't work:
function authCheck(){
var getAuth = $firebaseAuth(Data.ref);
console.log('signed in as', getAuth.$getAuth().uid);
var uid = getAuth.$getAuth().uid.toLowerCase().replace(/'+/g, '').replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "-").replace(/^-+|-+$/g, '');
var userIndexRef = Data.ref.child('index/users/uid/'+uid);
var userIndexArray = $firebaseArray(userIndexRef);
var userIndexObject = $firebaseObject(userIndexRef);
console.log(userIndexArray, userIndexObject);
var realId = '';
angular.forEach(userIndexObject, function(key, id){
realId = id;
$rootScope.auth = realId;
return realId;
});
}
Here's the login code that does work:
function login(email, pass) {
ref.authWithPassword({email:email,password:pass}, function(error, authData){
if (error) {
console.log(error);
} else {
console.log('signed in as',authData.uid);
var uid = authData.uid.toLowerCase().replace(/'+/g, '').replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "-").replace(/^-+|-+$/g, '');
angular.forEach(Data.dataObject.index.users.uid[uid],function(id, key){
$rootScope.role = Data.dataObject.users[id].role;
$rootScope.auth = {authData:authData, id:id, role:Data.dataObject.users[id].role};
});
}
});
}
If anyone sees where I've messed up, I'll be happy to know. Here's the repo https://github.com/irthos/medviz if it helps. Thank you very much!
In my project I am writing e2e tests in node.js and I have a test firebase I am using. So I create a token in node before each describe in the test runs and then I send it to the front end(angular.js) and then I use the authWithCustomToken function to authenticate the person.
The problem is for some reason it isn't even calling the function because I put a console.log statement in the callback and every time my code runs it enters the if $location.search condition but the console.log doesn't print out anything. I dont seem to know what the problem is.
var Firebase = require('firebase');
var FirebaseTokenGenerator = require('firebase-token-generator');
var rootRef = new Firebase('https://xxxxx');
var data = require('./data_helper.js');
rootRef.child('users').set(data.users[0]);
var credentials = {
nonAdmin: {
uid: 'google',
email: 'xxxx'
},
admin: {
uid: 'google',
email: 'xxxxx'
}
};
var logInAndThen = function(options) {
var secret = 'sdmdfmdsjwdsjwjwwewewe';
var tokenGenerator = new FirebaseTokenGenerator(secret);
var token = tokenGenerator.createToken(credentials[options.userType || 'admin']);
browser.get('/login?token=' + token);
var alertDiv = by.className('alert');
//browser.wait(function(){});
var waitOnFirebase = browser.wait(function() {
return browser.isElementPresent(alertDiv);
});
waitOnFirebase.then(function(data) {
console.log('-------', data);
options.cb(data);
});
};
module.exports = logInAndThen;
--------- FRONT END ANGULAR CODE PUT IN APPLICATION.RUN---------------------
if($location.search().token) {
console.log(Refs.root.toString());
Refs.root.authWithCustomToken($location.search().token, function(err, authData) {
console.log(err,authData);
}, {scope: 'email'});
}
I would appreciate it if someone could help me with this
Try getting the token like this (put this in your .run):
var loc = $location.path();
if(loc.search('login?token') > 0) {
token = loc.splice(13)
//now incorporate the 'token' into whatever auth functions you need to.
}
Not entirely sure if this is the most technically 'correct' way of grabbing the token, but it should work for you.
Ok, so I'm working with AngularJS and Firebase and trying to create a simple exchange between two users. Right now my data structure is set up under "users/uId/" and then their email, date they joined, and gold.
Under gold (users/uId/gold) I have "sent" which captures the amount, time and to whom (email). This is the code snippet below. It also updates their total gold.
Now I'm stuck updating the person they're sending the gold to. I capture the email address, but everything under scope relates to the current logged in user. How would I update the new users users/uId/gold/received with the amount, time and email who it was from, along with updating their total gold?
I feel like I might be going about this the wrong way, any help would be appreciated, thanks!
ledger.controller('TransferController', function (
$scope, $firebase, $routeParams, $location, $rootScope, FIREBASE_URL) {
$scope.whichuser = $routeParams.uId;
$scope.goldsends = goldsendList;
var ref = new Firebase(FIREBASE_URL + '/users/' + $scope.whichuser + '/gold/' + '/sent/');
var hopperRef = new Firebase(FIREBASE_URL + '/users/' + $scope.whichuser + '/gold/');
var usersRef = ref.child("users");
var goldsendList = $firebase(ref).$asArray();
$scope.sendGold = function () {
var sendgoldObj = $firebase(ref); //this var has to match the sendgoldObj.$push var down below, and that's it
var myData = {
amount: $scope.user.amount,
email: $scope.user.email,
date: Firebase.ServerValue.TIMESTAMP
};
sendgoldObj.$push(myData).then(function () {
// $location.path('/myledger/'); //page redirect
}); //data sent to firebase.
if ($scope.currentUser.gold.total - Math.abs($scope.user.amount) > 0) { //
var hopperRefff = hopperRef.child("gold");
hopperRef.update({
"total": $scope.currentUser.gold.total - $scope.user.amount
}); //update total gold
var receive = new Firebase(FIREBASE_URL);
ref.child('users').orderByChild('email').equalTo(emailAddress).once('value', function (snap) {
console.log(snap.name() + (snap.val() === null ? ' DOES NOT' : ' does') + ' exist');
}); //trying to find user to send gold to
} //if user has enough gold statement
else {
return {
scope: {
errormessage: 'You don\'t have enough money',
}
};
console.log("not enough money!");
} //else note enough gold statement
} //sendgold
}); //TransferController
You could store the users by email where the # is replaced by _ and a . is replaced with -
So you have a JSON structure like this in Firebase
users: {
"bob_hoskins-com": {
email: "bob#hoskins.com",
date: "09-09-1999",
gold: {
...
}
}
}
However, I don't think this is a great approach for this problem.
I would create a node service that is observing a requests Firebase location on each user for added children. The node service will then do the calculations and write the data to the correct paths, then can delete the request once processed.
So you would have rules on your Firebase like this
{
"rules": {
"$userId": {
"requests": {
".read": "auth != null && $userId == auth.id",
".write": "auth != null && $userId == auth.id"
},
"responses": {
".read": "auth != null && $userId == auth.id",
".write": "auth != null && $userId == auth.id"
}
}
}
Here is some request code
var Firebase = require('firebase');
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
function guid() {
return s4() + s4() + s4() + s4();
}
var _ref = new Firebase('https://YOUR_FIREBASE.firebaseio.com/');
//Log me in
var guid = guid();
var FirebaseTokenGenerator = require("firebase-token-generator");
var tokenGenerator = new FirebaseTokenGenerator("YOUR_TOKEN");
var TOKEN = tokenGenerator.createToken({uid: guid, user: "node server"},{admin: true});
_ref.authWithCustomToken(TOKEN, function (error) {
if(error) {
console.log("Login Failed!", error);
} else {
console.log("Login Succeeded!", guid);
}
});
_ref.on('child_added', function (user) {
var requests = user.ref().child('requests');
requests.on('child_added', function(req) {
handleRequest(req);
});
});
var handleRequest = function (request) {
// Process the request
// Write stuff back to Firebase
// Delete the request
request.ref().remove();
};
Setting a value to the user is just a variation of checking if that user exists. Once you have a snapshot, you can get back to a ref by calling ref
ref.child('users').orderByChild('email').equalTo(emailAddress).once('value', function (snap) {
snap.ref().update({ "total": snap.val().total + amount });
});
Not that this is just a sample, so you'll probably have to update it for your actual data structure.
Update
The above will get you the value of the users node.
You either need to capture the once('child_added' or forEach over the on('value'. I'll give an example of both.
Listening to child_added:
ref.child('users').orderByChild('email').equalTo(emailAddress).once('child_added', function (snap) {
snap.ref().update({ "total": snap.val().total + amount });
});
An example of looping over the value:
ref.child('users').orderByChild('email').equalTo(emailAddress).once('value', function (snap) {
snap.forEach(function(childsnap) {
childsnap.ref().update({ "total": snap.val().total + amount });
});
Here's a jsbin with both samples: http://jsbin.com/fenavu/1/edit?js,console. Note that the code here writes out the ref.toString(), which gives you the full URL of the node (since every piece of data in Firebase has its own unique URL). That can be a handy way to figure out what URL your node maps to.