I have a little abstraction I wrote around $http that I use to make calls from a security service. The problem I am having is that during a request that results in a 401, the deferred does not seem to propogate correctly.
I am using it like so, and even if it is a 401 it alerts good... I would expect this to alert bad.
security.login('test', 'password').then(function (r) {
alert('good');
}, function (r) {
alert('bad');
});
Http Wrapper
angular.module('app').provider('http', function () {
return {
$get: ['$http', 'url', function ($http, url) {
function http(config) {
config.headers = {
'X-Requested-With': 'XMLHttpRequest'
};
config.url = url.formatUrl(config.url);
return $http(config);
}
return {
delete: function (url, data) {
return http({ url: url, data: data, method: 'DELETE' });
},
get: function (url) {
return http({ url: url, method: 'GET' });
},
post: function (url, data) {
return http({ url: url, data: data, method: 'POST' });
},
put: function (url, data) {
return http({ url: url, data: data, method: 'PUT' });
}
};
}]
};
});
Security Service
function User() {
this.displayName = '';
this.permissions = [];
}
angular.module('app').provider('security', function () {
var _user = new User();
return {
$get: ['$rootScope', '$q', 'cookie', 'http', 'statePermissions', function ($rootScope, $q, cookie, http, statePermissions) {
function login(params) {
return http.post('SS/auth', params).then(function (response) {
cookie.set('authToken', response.data.authToken);
_user = response.data;
$rootScope.$broadcast('event:loginSuccessful', _user);
return response;
}, function (response) {
cookie.expireNow('authToken');
_user = new User();
$rootScope.$broadcast('event:loginUnsuccessful', _user);
$q.reject(response);
});
}
return {
doesAuthTokenExist: function () {
return angular.isDefined(cookie.get('authToken'));
},
getUser: function () {
return _user;
},
isUserAuthorizedForPermission: function (permission) {
var x;
for (x = 0; x < _user.permissions.length; x++) {
if (_user.permissions[x] === permission) {
return true;
}
}
return false;
},
isUserAuthorizedForState: function (stateName) {
if (angular.isDefined(statePermissions[stateName])) {
return this.isUserAuthorizedForPermission(statePermissions[stateName]);
}
return true;
},
login: function (userName, password) {
return login({ username: userName, password: password });
},
loginWithAuthToken: function () {
var authToken = cookie.get('authToken');
return login({ provider: 'token', authToken: authToken });
},
logout: function () {
return http.post('SS/auth/logout').then(function () {
cookie.expireNow('authToken');
_user = new User();
$rootScope.$broadcast('event:logoutSuccessful', _user);
return true;
});
}
};
}]
};
});
Your $http wrapper looks like it's duplicating the functionality of angular's $resource service. Check out the documentation here: http://docs.angularjs.org/api/ngResource.$resource
After a brief look at your code, it seems like the problem could be with how you're using $q. Try rewriting your login method along these lines.
With insight from here:
http://docs.angularjs.org/api/ng.$q
http://docs.angularjs.org/api/ng.$http
function login(params) {
var deferred = $q.defer();
http.post('SS/auth', params).success(function (response) {
cookie.set('authToken', response.data.authToken);
_user = response.data;
$rootScope.$broadcast('event:loginSuccessful', _user);
deferred.resolve(response);
}).error(function (error) {
cookie.expireNow('authToken');
_user = new User();
$rootScope.$broadcast('event:loginUnsuccessful', _user);
deferred.reject(error);
});
return deferred.promise;
}
Also, just curious why you are using providers here as it's not obvious to me?
Related
Upgrade to angularjs version 1.7 and this code does not compile
app.factory('LoginService', function ($http) {
return {
login: function (param, callback) {
$http.post(url, param)
.success(callback)
.error(function (data, status, headers, config) {
});
}
};
});
On the controller I make the call to the service LoginService
function LoginController($http, $location, LoginService, blockUI) {
var vm = this;
LoginService.usuario(
{login: vm.username, clave: vm.password},
function (data, status, headers, config) {
vm.resultado = data;
if (vm.resultado == "True") {
window.location = "/Home/Index";
} else {
vm.error = 'Usuario o password incorrecto';
}
});
};
I want to know how the function is called from the controller because it implemented the http.post service using .then
app.factory('LoginService', function ($http) {
return {
login: function (data) {
$http.post(url, data)
.then(function (resultado) {
debugger;
if (resultado.data === "True") {
return resultado.data;}
else {
console.log("NO");}
});
}};
});
I suggest you get familiar with a AngularJS $q service and its Promise API.
You LoginService.login(...) method should return the Promise from $http.post(...):
app.factory('LoginService', function ($http) {
return {
login: function (data) {
return $http.post(url, data)
.then(function(response) {
return response.data;
});
});
Then, your Controller can access the returned data via the resolved Promise:
function LoginController(LoginService) {
var vm = this;
LoginService.login({login: vm.username, clave: vm.password})
.then(function (result) {
// handle result here...
});
the solution would be this:
function LoginController($scope,$window,$q,LoginService) {
$scope.fnBusqueda = function () {
var promesas = [
obtenerLogin()
];
$q.all(promesas).then(function (promesasRes) {
var oArrayResponse = promesasRes;
if ((oArrayResponse.length > 0)) {
$scope.respuesta = oArrayResponse[0];
if ($scope.respuesta == "True") {
window.location = "/Home/Index";
} else {
$cope.error = 'Usuario o password incorrecto';
}
}
});
};
function obtenerLogin() {
var defered = $q.defer();
var promise = defered.promise;
LoginService.login(url_valida_login, '{login:X,clave:X}').then(function (response) {
defered.resolve(response);
}).catch(function (data) {
defered.resolve([]);
})
return promise;
}
}
Here is my code of angularjs file
$scope.httpPost = function (url, json_form_data) {
$http.post(url, json_form_data)
.then(function (response) {
$scope.responseData = response.data;
return $scope.responseData;
}, function (response) {
$scope.content = "Something went wrong";
});
};
Here is the function in which i am calling the above function
$scope.getAuthToken = function (account_type, auth_type, email, type_of_request) { // type of request means login or signUp
var account_type = account_type;
var form_data = {
'email': email,
"auth_type": auth_type,
"account_type": account_type
};
$scope.responseData = $scope.httpPost($scope.authTokenUrl, form_data);
console.log("value of res");
console.log($scope.responseData);
};
The output of the above code is
value of res
loginAndSignup.js:138 undefined
My question is that How can i access that value which function returning because i needed that value.
I tried the following solution
$scope.httpPost = function (url, json_form_data) {
return $http.post(url, json_form_data)
.then(function (response) {
return response;
}, function (response) {
$scope.content = "Something went wrong";
});
};
$scope.login = function (email, auth_token, auth_type, account_type) {
var password = $scope.password;
var form_data = {
//form data
};
var url = $scope.loginUrl;
$scope.httpPost(url, form_data)
.then(function (response) {
return response;
}, function (response) {
$scope.content = "Something went wrong";
});
using $q (A service that helps you run functions asynchronously, and use their return values (or exceptions) when they are done processing.)
click here for more detail
used this function
$scope.httpPost = function (url, json_form_data) {
var d = $q.defer();
$http.post(url, json_form_data)
.then(function (response) {
d.resolve(response);
}, function (response) {
d.reject(response);
});
return d.promise;
};
I'm trying to use Django REST Framework's token-based authentication scheme with an AngularJS client. I'm able to successfully retrieve and store a token from the server, but I'm having trouble figuring out how to attach the token to subsequent responses. Here's the service that manages logging in and saving a token:
angular.module('mymodule')
.factory('loginService', function ($http, $window) {
var api_base = "link to my api";
return {
async: function() {
return $http.get(api_base + "authentication/login/").then(function (response) {
return response.data;
}, function errorCallback(response) {
console.log("Testuser API Error: " + response);
return null;
});
},
loginUser: function(email, password) {
self.saveToken = function(auth_token) {
$window.localStorage['jwtToken'] = auth_token;
};
self.getToken = function() {
return $window.localStorage['jwtToken'];
};
console.log("...to listing " + email);
return $http.post("link to my api/authentication/login/", {
email: email,
password: password
}).then(function(response) {
if(response.config.url.indexOf("link to my api") === 0 && response.data.auth_token) {
self.saveToken(response.data.auth_token);
}
return response;
});
}
};
});
Here's the controller associated with the above service to handle logging in:
angular.module('mymodule').controller("LoginController", function(loginService, $scope) {
$scope.loginusers = [];
$scope.refresh = function() {
loginService.async().then(function(data) {
if (data == null)
return;
console.log(data[0]["email"]);
$scope.loginusers = [];
for (var loginuser in data)
$scope.loginusers.push(loginuser);
});
};
$scope.refresh();
// Test //
$scope.loginTestUser = function() {
console.log("something...");
loginService.loginUser(
$scope.email,
$scope.password
)
};
//////
});
And here's the service that I'd like to use for displaying a user's profile after the token is sent back to the server.
angular.module('mymodule').factory("profileService", function($http, loginService, $httpProvider) {
var api_base = "link to my api";
$httpProvider.interceptors.push(function($q, $window) {
return {
'request': function(config) {
config.headers['Token'] = $window.localStorage['jwtToken'];
return config;
}
};
});
return {
async: function() {
return $http.get(api_base + "authentication/me/").then(function (response) {
return response.data[0];
}, function errorCallback(response) {
console.log("Profile API Error: " + response);
return null;
});
}
};
});
How should I be approaching this?
I am trying to make a GET call to test a REST API but it keeps returning null, is there anything I am doing wrong:
Making the call in controller.js
function ConsumerSearchCtrl($scope, BusinessCategoryService) {
console.log(BusinessCategoryService);
}
127.0.0.1:8000/api/category/ works perfectly fine
Code in services.js for API
/**
*
*/
function BusinessCategoryService(WenzeyAPI, $q) {
var scope = this;
scope.categories = categories;
function categories() {
var q = $q.defer();
WenzeyAPI.get('http://127.0.0.1:8000/api/category/').then(function success (res) {
q.resolve(res.data);
}, function failure (err) {
q.reject(err);
})
return q.promise;
}
}
/**
*
*/
function WenzeyAPI() {
var scope = this,
ip = "http://127.0.0.1:8000";
scope.get = get;
scope.post = post;
function get(url, data) {
data = data || {};
var req = {
method: 'GET',
url: url,
data: data
}
var q = $q.defer();
$http(req).then(function success(response) {
q.resolve(response);
}, function failure(err) {
q.reject(err);
});
return q.promise;
}
function post(url, data) {
data = data || {};
var req = {
method: 'POST',
url: url,
data: data
}
var q = $q.defer();
$http(req).then(function success(response) {
q.resolve(response);
}, function failure(err) {
q.reject(err);
});
return q.promise;
}
}
Removing WenzeyAPI and using $http resolved it.
function BusinessCategoryService($http) {
this.getAllData = function () {
return $http({
method: 'GET',
url: 'http://127.0.0.1:8000/api/category/',
});
}
}
I have this code in my post.serv.js and in my controller I want to execute the function delete.
"use strict";
app.factory('JnttPost', function ($resource) {
var PostResource = $resource('/api/post/:_id', {
_id: "#id"
}, {
update: {
method: 'PUT',
isArray: false
}
}, {
delete: {
method: 'DELETE',
isArray: false
}
});
return PostResource;
});
I already know how to get and update a post, for example in my createpost.serv.js
"use stric";
app.factory('JnttCreatePost', function ($http, $q, JnttPost) {
return {
createPost: function (newPostData) {
var newPost = new JnttPost(newPostData);
var dfd = $q.defer();
newPost.$save().then(function () {
dfd.resolve();
}, function (response) {
dfd.reject(response.data.reason);
});
return dfd.promise;
}
};
});
and in my newpost.ctrl.js
"use strict";
app.controller('CtrlNewPost',
function ($scope, $location, JnttIdentity, JnttNotifier, JnttCreatePost) {
var email = ...;
$scope.newPost = function () {
var newPostData = {...};
JnttCreatePost.createPost(newPostData).then(function () {
JnttNotifier.notify('success', 'The post has been created');
$location.path('/');
}, function (reason) {
JnttNotifier.notify('error', reason);
});
};
});
I can't realize how to perform the delete request, I can do with a $http
In my new controller for do deletePost() function I have this:
$scope.deletePost = function () {
var pwd = JnttIdentity.currentUser.hashed_pwd;
var postidd = {
password: pwd,
id: $scope.post._id
};
var config = {
method: "DELETE",
url: '/api/post/',
data: postidd,
headers: {
"Content-Type": "application/json;charset=utf-8"
}
};
$http(config);
$location.path('/');
};
This actually already do this stuff but I want to do this without the $http like the create request, How I can do this? How do I can edit this code below for do the request?
createPost: function (newPostData) {
var newPost = new JnttPost(newPostData);
var dfd = $q.defer();
newPost.$save().then(function () {
dfd.resolve();
}, function (response) {
dfd.reject(response.data.reason);
});
return dfd.promise;
}
In my routes.js in express I have this route:
app.delete('/api/post/', posts.deletePost);
You can either call delete on the $resource class you create (JnttPost) or call $delete on a post that's returned from the $resource class.
The $resource class already has get/save/query/remove/delete functions included so you don't need to add the delete (save is create/POST, so you need to include update with PUT).
Here's a sample of using your $resource class to call delete:
angular.module('test', ['ngResource'])
.factory('JnttPost', function ($resource) {
var PostResource = $resource('/api/post/:_id', {
_id: "#id"
}, {
update: {
method: 'PUT',
isArray: false
}
});
return PostResource;
})
.run(function(JnttPost){
JnttPost.delete({id: 123123123});
});