Firebase auth.$createUserWithEmailAndPassword not working - angularjs

I have been following a course on Firebase, but quickly discovered a lot of things have changed. https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-users-and-authentication-createusercredentials
these docs are completely outdated.
Here I declare my firebase variables
var ref = firebase.database().ref();
var firebasedata = $firebaseObject(ref);
var auth = $firebaseAuth();
Then I try to call this function
this.register = function() {
auth.$createUserWithEmailAndPassword({
email: this.user.email,
password: this.user.password
}).then(function(regUser) {
$log.log(regUser);
}).catch(function(error) {
$log.log(error);
});
};
But it throws this error:
code
:
"auth/argument-error"
message
:
"createUserWithEmailAndPassword failed: First argument "email" must be a valid string."
I have searched for answers to this problem but all I can find is updating my angularfire or firebase (which are both the latest version) or that this.user.email is not a string. When I do a
console.log(this.user.email);
I can see it is a string containing a valid e-mail.
Any help into the right direction would be welcome!

For anyone experiencing this issue:
the old
auth.$createUser()
function took an user-object as parameter.
While:
auth.$createUserWithEmailAndPassword()
takes 2 strings as parameters, not an object.

Change your code from
auth.$createUserWithEmailAndPassword({
email: this.user.email,
password: this.user.password
})
to
auth.createUserWithEmailAndPassword(user.email, user.password);

Change the function parameters as follows:
this.register = function() {
auth.$createUserWithEmailAndPassword(this.user.email,this.user.password).then(function(regUser) {
$log.log(regUser);
}).catch(function(error) {
$log.log(error);
});
};

$scope.register = function() {
firebase.auth().createUserWithEmailAndPassword($scope.email, $scope.password)
.then(function(user) {
console.log(user);
})
.catch(function(error) {
console.log(error);
});
//}
}
here, you can use it this way.

Related

Ionic $http.post catch errors

I have a submit function, which posts some data into a server and then the server returns a response. The function is working fine. I would like, though, to catch a couple of errors during the post process. For example, if there is no connectivity to the server, return an error to the user to inform him what's going on. instead of just pressing the button and do nothing. I know I can create a function to somehow ping the server and check if it's alive but that's not what I need. I would like to have a statement in the error function and catch most of the possible errors and output an explanation to the user.
$scope.submit = function() {
var link = 'http://app.example.com/api.php';
$http.post(link, {
username: $scope.data.username,
password: $scope.data.password
}).then(function(res) {
$scope.response = res.data;
$localStorage.token = res.data;
console.log($localStorage.token);
})
.catch(function(error) {
console.error(error);
})
.finally(function() {
//do something
});
};
Solution:
$http.post(link, {
username: md5.createHash($scope.data.username),
password: md5.createHash($scope.data.password),
}).then(function(res) {
//Success Scenario
})
.catch(function(error) {
if (error.statusText == ""){
$scope.response = "Unexpected error. Make sure WiFi is on."
//When the device is not connected on the internet the response error is -1 (or any number) and the statusText is empty. So we caching that one as-well.
}
else {
$scope.response = "Error - "+error.status + " ("+error.statusText+")";
//else we display the error along with the status, for example error 500 Internal Server error.
}
})
.finally(function() {
//This function will always be called at the end. Take advantage of it :)
});
I hope it's gonna be useful for someone.

On Auth State changed AngularFire

Trying to authenticate an user using firebase. Started my app using firebase 2.xx but even after upgrading to Firebase 3.xx, throwing
error "onAuthStateChanged is not a function".
This is how my login function looks like-
.controller('HomeCtrl', ['$scope','$location','CommonProp','$firebaseAuth', '$firebaseObject',function($scope,$location,CommonProp,$firebaseAuth,$firebaseObject) {
var firebaseObj = $firebaseObject(rootRef);
var loginObj = $firebaseAuth(firebaseObj);
$scope.SignIn = function($scope, user) {
event.preventDefault(); // To prevent form refresh
var username = user.email;
var password = user.password;
loginObj.$signInWithEmailAndPassword({
email: username,
password: password
})
.then(function(user) {
// Success callback
console.log('Authentication successful');
$location.path("/welcome");
CommonProp.setUser(user.password.email);
}, function(error) {
// Failure callback
console.log(error);
});
}
}]);
Your problem is that you are passing a $firebaseObject to $firebaseAuth().
So make sure you are initializing your [$firebaseAuth][1] object like the following and then your code should work properly.
var loginObj = $firebaseAuth();
Working jsFiddle for demonstrating.
You can check here the documentation for AngularFire2

Dynamic URL queries with AngularJS and NodeJS, MongoDB

I really do not understand how to handle URLs with queries appended to it.
I have endpoints that accept several parameters like:
?max_length=50,
?min_length=1,
?active=true,
?only_today=true,
?etc...
Via AngularJS how can I set those value dynamically only if the user has checked for those values?
Actually I'm just building an object {} appending those parameters when the $scope is not null. But I don't think it is a good idea.
Same for NodeJS and MongoDB...
How can I get the correct object based on the query string on the URL?
What I'm doing here as well is to split up the URL and checking for the words, etc... I'm sure there is a better way and I can not find it in both documentations and wondering to bigger and bigger URL parameters it start to be hell.
I know this is a real low level question but I don't really understand how to handle it.
Thanks
You can use the $location service for that.
https://docs.angularjs.org/api/ng/service/$location
You can use $resource to easily map your endPoints to your services. You should map your params to what is expected in your api. And if you have conditional parameters, you need to handle undefined params in your backend and ignore these params. For mapping your endpoints in nodeJS check out Restify
For example:
angular.module("myApp", []).factory("myFactory", function($resource) {
var YourResource = $resource('/rest/yourResource');
var factory = {
retriveMyResources: function(paramsQuery) {
return YourResource.query(paramsQuery).$promise;
}
};
return factory;
}).controller("myCtrl", function($scope, myFactory) {
myFactory.retrieveMyResources({
maxLength: $scope.maxLength,
sortBy: $scope.sortBy
}).then(function(result) {
$scope.result = result
})
})
Your node server
//App.js you initialize your server, and include your route files
(function() {
var restify = require("restify");
var server = restify.createServer({
name: "test-server"
});
server.pre(restify.CORS());
server.use(restify.gzipResponse());
server.use(restify.acceptParser(server.acceptable));
server.use(restify.queryParser());
server.use(restify.bodyParser());
server.use(restify.jsonp());
require("./routes/your_resource_route.js")(server);
server.listen("1921", function() {
console.log('%s listening at %s environment: %s', server.name, server.url, process.env.NODE_ENV);
});
})();
Example Route file
module.exports = function(server) {
var yourResourceService = require("services/your_resource_service.js");
server.get("rest/yourResource",
function(req, res, next) {
return yourResourceService.findResources(req.params.maxLength, req.params.sortBy).then(function(resources) {
res.send(200, resources);
next();
}).catch(function(err) {
res.send(500, err);
next();
}).done();
}
);
}
And your service file
module.exports = function(app_context) {
var exampleService = {
findItems: function(maxLength, sortBy) {
var sortObject = {};
sortObject[sortBy || DEFAULT_SORT] = -1;
return Q(brandMongooseCollection.find({}).sort(sortObject).limit(maxLength || DEFAULT_MAX_LENGTH).lean().exec());
}
};
return exampleService;
};

Set RestAngular default request parameters after login

I'm hitting an API which requires all authenticated actions to include an auth token in the request, however, I do not have the auth token until I login.
I've only seen examples of setting default request parameters in Restangular in app.config.
Is it possible to set this until after the user has logged in and User.auth_token is set?
So basically instead of:
app.config(function(RestangularProvider) {
RestangularProvider.setDefaultRequestParams({
auth_token: 'thisistheauthenticationtoken'
});
});
I need:
app.config(function(RestangularProvider) {
RestangularProvider.setDefaultRequestParams({
auth_token: User.auth_token
});
});
Why would you set token as part of the response versus in the header? Like so.
Restangular.setDefaultHeaders({ authentication: 'bearer ' + token.authentication });
I know this is an old thread but this SO question kept appearing when I was Googling (yes, I just used Google as a verb... deal with it :P) for a resolution, so I thought I should provide my solution. Hopefully it will help the OP or anyone else that may come across this page.
angular.module("app").factory("UserService", [
"$rootScope",
"$state",
"$q",
"Restangular",
function ($rootScope, $state, $q, Restangular) {
var UserSvc = {};
var Identity;
/*
This creates a scoped copy of Restangular
Normally this is where you would use setDefaultRequestParams,
but it would only affect this scope and not ALL API requests in your app
*/
var UsersAPI = Restangular.withConfig(function (RestangularConfigurer) {
RestangularConfigurer.setBaseUrl("api/1.0/users");
});
UserSvc.login = function (credentials) {
var $defer = $q.defer();
UsersAPI.all("start-session").post(credentials).then(function(respData){
if (respData.apikey) {
Identity = respData.plain();
/*
User is authenticated and API key is obtained from server response
Note how I do NOT use the setDefaultRequestParams function:
If we do the withConfig/setDefaultRequestParams, it only affects local scope, not global
This method modifies the ROOT Restangular object and
will then propegate through all future use of Restangular in your app
*/
Restangular.configuration.defaultRequestParams.common.apikey = Identity.apikey;
if ($rootScope.toState && $rootScope.toState.name != "login") {
$state.go($rootScope.toState.name, $rootScope.toStateParams || {});
} else {
$state.go("app.dashboard");
}
$defer.resolve(Identity);
}
else {
Identity = undefined;
$defer.reject(Identity);
}
},function (respData) {
$defer.reject(respData);
});
return $defer.promise;
};
return UserSvc;
}
]);
In my case, I use
Restangular.setDefaultRequestParams({token: localstorage.get('token')});
This works with me. Please have a look my snippet here.
https://github.com/fugokidi/ng-snippets/blob/master/rest.js
If you want to do something like this, you need to remove your code from app.cofig and move to when you find user is logged in.
You can set defaultRestParams for restangular at any point of application using Restangular service.
For more info refer https://github.com/mgonto/restangular#setdefaultrequestparams.
A more Angular-ish example from a project that I've been working on:
angular.module('app', [ 'restangular' ])
.factory('API', function(Restangular){
return Restangular.withConfig(function(config){
config
.setBaseUrl('https://api.example.com')
// etc etc etc
; // END config
});
})
.factory('Auth', function(API){
return {
login: function(credentials){
// Assuming I just POST /session/new to get an OAuth token,
// which is totally not a thing that OAuth should do.
API.one('session').post('new', credentials)
.then(function(auth){ // Assuming `auth = { access_token: '...' }`
API.setDefaultHeaders({
Authorization: 'bearer ' + auth.access_token
// Assuming OAuth Bearer Token
});
})
},
logout: function(){ /* . . . */ }
};
})
.controller('MainController', function(API, Auth){
var self = this;
self.user = { };
this.login = function(credentials){
Auth.login(credentials).then(function(){
self.user = API.one('user').$object;
});
});
})
; // END module(app)
The following code will read the token from storage for every request.
app.config(function(RestangularProvider) {
//Injext $cookies manually (there might be better ways to do this)
var $cookies;
angular.injector(['ngCookies']).invoke(['$cookies', function(_$cookies_) {
$cookies = _$cookies_;
}]);
RestangularProvider.setDefaultHeaders({
Authorization: function() {
return $cookies.get('token');
}
});
});
I too struggled with this.
Instead of using
RestangularProvider.setDefaultRequestParams({
auth_token: 'thisistheauthenticationtoken'
});
try using
Restangular.setDefaultRequestParams({auth_token:'thisistheauthenticationtoken'});

AngularJS reload data after PUT request

Should be a fairly easy one here for anyone who knows Angular. I am trying to update the data that is displayed after I make a PUT request to update the object. Here is some code:
Post service (services/post.js)
'use strict';
angular.module('hackaboxApp')
.factory('Post', function($resource) {
return $resource('/api/posts/:id', {id : '#id'}, {
'update': { method: 'PUT' }
})
});
Server side controller function that gets executed when trying to update data (lib/controllers/api.js)
exports.editsave = function(req, res, next) {
var posty = req.body;
console.log(posty._id.toString() + " this is posty");
function callback (err, numAffected) {
console.log(err + " " + numAffected);
if(!err) {
res.send(200);
//res.redirect('/forum');
}
}
Post.update(posty, { id: posty._id.toString() }, callback);
};
This is the console output for the above code:
53c54a0d4960ddc11495d7d7 this is posty
null 0
So as you can see, it isn't affecting any of the MongoDB documents, but it also isn't producing errors.
This is what happens on the client (Angular) side when a post is updated:
$scope.saveedit = function() {
console.log($scope.post._id + " post id");
// Now call update passing in the ID first then the object you are updating
Post.update({ id:$scope.post._id }, $scope.post, function() {$location.path('/forum')});
};
After the redirect, $location.path('/forum'), none of the data is displayed as being updated...when I look in the database...nothing has changed either...it is like I am missing the step to save the changes...but I thought that update (a PUT request) would do that for me.
I use ng-init="loadposts()" when the /forum route is loaded:
$scope.loadposts = function() {
$http.get('/api/posts').success(function (data) {$scope.posts = data});
};
Shouldn't all the new data be loaded after this? Any help would be appreciated. Thanks!
Your server side output indicate that the update query doesn't match any document in the database.
I'm guessing that you are using Mongoose in NodeJS server side code to connect to mongodb.
If that the case, your update statement seems incorrect.
Instead of { id: .. } it should be { _id: .. }
Also the conditions object and updated object are swapped.
The statement should be like this:
Post.update({ _id: posty._id.toString() }, posty, callback);
If you are not using Mongoose, please eloborate more on which library you are using or better than that, show the code where the Post variable is defined in your server side code.
Ok I got it.
the problem is that you are not using the Angular resource api correct.
This code need to be changed:
$scope.saveedit = function() {
console.log($scope.post._id + " post id");
Post.update({ id:$scope.post._id }, $scope.post, function() {$location.path('/forum')});
};
Into:
// Update existing Post
$scope.saveedit = function() {
var editedpost = new Post($scope.post); //New post object
editedpost.$update(function() {
$location.path('/forum');
}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
};
And as for the server code (taken from my own working module):
exports.update = function (req, res) {
var post == req.post;
post = _.extend(post, req.body);
post.save(function (err) {
if (err) {
return res.send(400, {
message: getErrorMessage(err)
});
} else {
res.jsonp(post);
}
});
};

Resources