Maintain Angular Service through page change - javascript

I am creating a web portal using Angular on the front end and Java Servlets in the back end. The page starts with a login page, It takes the input and sends it to the servlet. The server validates and responds with a JSON object which has the username and his permissions. I set the values to a Service which is injected into the Controller. Then I use $windows.location to change the web page to the home page which is the dashboard. Now I want to use this Service in the controller of the homepage. But I am not able to maintain the $scope due to the page change.
So I thought of redirecting to the home page in the backend using response.redirect() . But I don't know how to get the user details in the homepage after redirection. Like how do I pass the User object to the Home.java servlet
This is my LoginCtrl.js
if (isValid) {
$http({
method : 'POST',
url : 'login',
data : JSON.stringify($scope.user),
headers : {
'Content-Type' : 'application/json'
}
}).success(function(data) {
if (!("failure" == data)) {
console.log(data);
var user = {};
user.name = data.name;
user.permissions = data.permissions;
MyService.setUser(user); // set the values for user
$window.location.href = 'main.jsp';
} else {
$scope.information = "Invalid username/password!"
}
}).error(function(data) {
console.log(data);
});
This is my Login.java servlet
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
Gson gson = new Gson();
JsonParser parser = new JsonParser();
JsonObject obj = (JsonObject) parser.parse(request.getReader());
String username = "";
String password = "";
if (obj.get("name") != null & obj.get("password") != null) {
username = obj.get("name").getAsString();
password = obj.get("password").getAsString();
}
System.out.println("Username :" + username);
System.out.println("Password :" + password);
// Passing username and password to Context and validate.
// If authentication successful, set user object with details and return
// it
// User user = (User) Context.Authorized(username,password)
// for testing
User user = new User();
user.setName(username);
user.setPermission("crwd");
user.setAuthorized(true);
response.setContentType("text/html");
if (user.getAthorized()) {
String responseJSON = gson.toJson(user);
response.getWriter().write(responseJSON);
} else {
response.getWriter().write("failure");
}
}
Please tell me if my requirement can be achieved in Angular or if it can be done using Java, then how ?

If you redirect to another page, there will be completely different Angular application, and you will lose service state.
You can make single page application and use $routeProvider and ng-view for both login page and homepage navbar.
Or your app can consist of different pages, but then in every page you must call server to get user info

Related

nodejs redirect user with data

The client will log in by sending a POST request to my server. My server will check this. If it works, I want to send the welcome page to the client but insert some data into it via a templating engine. I have everything but the redirect part figured out. This is what I have (I am using handlebars as a templating engine):
app.post("/loginAttempt",function(req, res)
{
var username = req.body.username;
var password = req.body.password;
//if credentials are incorrect, data is false
//otherwise, data is a html file as a string
var data = await checkCredentials(username,password);
if(data === false)
{
res.send("fail");
}
else
{
//not a real function, just using this to simplify code for this post
var temp = compileWithHandlebars("./front-end/welcome.html",{myData: data});
res.send(temp);
}
});
The problem with this is it sends a html file as a string instead of redirecting. This means the user sees no change in url, so they cannot hit the back button to go back to the login page.
I am guessing the temp is a string!
app.post("/loginAttempt",function(req, res)
{
var username = req.body.username;
var password = req.body.password;
//if credentials are incorrect, data is false
//otherwise, data is a html file as a string
var data = await checkCredentials(username,password);
if(data === false)
{
res.status(404).send("fail"); //<==
}
else
{
//not a real function, just using this to simplify code for this post
//var temp = compileWithHandlebars("./front-end/welcome.html",{myData: data});
res.redirect("./front-end/welcome.html",{data:myData});
}
});

How to get response from Paynet.js load form?

I was trying to integrate Paynet.js for payment Integration They are having few custom HTML on page Load they are invoking below API on response I am getting session ID.
export function getPaymentSessionId(data) {
data = JSON.stringify(data);
let url = "/paynetj/auth?type=CF"
let BASE = "https://pts-api.paynet.com.tr/v1"
let actualurl = BASE + url;
Api._callAPI(actualurl, 'POST', data, (type, dt) => {
if (type == 'success') {
dispatcher.dispatch({
type: 'SessionId',
data: dt,
})
}else{
}
});
}
ON page Load getting Session ID
How to get that Session Id.
In the component I was calling action
let data1 = {
token:"pbk_pcs_wCtr5nd31EhNm7DhjUarQpgxQasTb2pa",
amount:150000,
add_commission:false,
pos_type:5,
domain:"https://www.paynet.com.tr",
tds_required:false,
show_tds_error:true,
merge_option:false,
save_card:false
}
UserAction.getPaymentSessionId(data1);
Showing in response unAuthorized what ever the keys and values given in API doc the same i was sending, do i need to send that token from my end and what is that token, can anyone please explain.
Else Do i need to call same API from my Application, Is there any alternate to get Session Id from the API that is getting Invoked on Page Load

Scope variable not recognized in second view with same Angular controller

I am trying to implement a login functionality that redirects a valid user to a personalized HTML view welcoming them with their name.
My first view is a login view. When the user clicks the button labeled "Log In" ng-click is supposed to call my controller's $scope.login which is supposed to validate the user, set the $scope.needsLoggingIn variable, and redirect to the second view (welcome page that shows the value of $scope.needsLoggingIn).
My problem is that the second view (which uses the same Angular Controller and Module) does not show the $scope.needsLoggingIn variable when I try to set it in the $scope.login function. It only shows the $scope.needsLoggingIn when I hard-coded the value like this in the controller, outside a scope function:
$scope.needsLoggingIn = "Betty";
This is the $scope.login function in my controller which tries to set the $scope.needsLogging in and is accepted in the first view but not accepted by the second view:
$scope.login = function (username, password) {
$http({
method: 'GET',
url: ('/login/' + username + '/' + password)
}).then(function successCallback(response) {
if (JSON.stringify(response.data) === '[]')
{
$scope.needsPasswordMessage = true;
if ($scope.needsPasswordMessage)
$scope.needsPasswordMessage = false;
console.log("No match");
} else {
$scope.needsLoggingIn = username;
$scope.issuccessMessage = true;
if ($scope.isfailureMessage)
$scope.isfailureMessage = false;
$window.location.href = '../indextest.html';
return response;
}
}, function errorCallback(response) {
});
};
Does anyone have any suggestions how I can get my $scope.needsLoggingIn recognized by both HTML views, without hard-coding it into the controller? I would really like to be able to have my $scope.login function set the variable value and have it recognized by all views that use this particular controller.
Data that you want to have live across different views and controller instances should be handled via a service.
Basically you would create a service something like:
function userService($http) {
let service = {}
service.needsLoggingIn = ""
service.login = login
return service
function login() {
return $http.... (your login code)
}
}
Then inject the service into your control, set properties as appropriate and since the service is a singleton, those property values will be available everywhere you inject the service.

ASP.NET MVC & Angular: After session expires, Angular Factory returns HTML of Login Page instead of JSON object

If the user is on a page for a long time and the session ends, if they proceed to make an AJAX call after the session is already expired.. instead of receiving the JSON object, it instead receives the HTML of the login page.
Ideally I'm trying to make it so that it will redirect to a log in page.
Is there any way i can detect this?
I already have an ActionFilterAttribute that works for non-AJAX calls like so:
public class VerifySessionAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var userId = filterContext.HttpContext.Session["UserId"];
var userName = filterContext.HttpContext.Session["UserName"];
if (userId == null || userName == null)
{
filterContext.Result = new RedirectResult(string.Format("/Account/Login"));
return;
}
base.OnActionExecuting(filterContext);
}
}
But that doesn't get hit for the scenario above during AJAX calls.
I've also tried an Interceptor.. something like this:
app.factory('httpAuthInterceptor', function ($q) {
return {
'responseError': function (response) {
// NOTE: detect error because of unauthenticated user
if ([401, 403].indexOf(response.status) >= 0) {
// redirecting to login page
//$state.go('home');
$window.location.href = '/Account/Login';
return response;
} else {
return $q.reject(rejection);
}
}
};
})
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('httpAuthInterceptor');
});
But in the same scenario it doesn't seem to hit there as well during the expired session / AJAX call
Is there anything I can do to detect this? When the session is expired I just want to redirect to the login page.. Thanks for any help
EDIT: here's how I make my calls
app.factory('HeadlinesFactory', ['$http', function ($http) {
var HeadlinesFactory = {};
HeadlinesFactory.getShowsForClient = function (clientId) {
return $http({
method: 'POST',
url: '/Show/GetShowsForClient',
data: { clientId: JSON.stringify(clientId) }
});
};
//etc
EDIT2: how all my controllers look like. Except my Account Controller where I put the VerifySession in front of everything except the Login page to prevent loop redirects:
[Authorize]
[CustomFilters.VerifySession]
public class ShowController : Controller
{ ... }
Ajax requests will not process redirect requests for security reasons. In addition, since you are returning a redirect result, a 401/403 status code is not thrown but rather a 302 is returned.
What you could do is expand your filter to conditionalize logic based on whether or not the request is an ajax request. In addition, based on your comments, it seems like creating a new Authorize attribute instead would be the right way to go since that way you can simply replace the default Authorize attribute with your own logic.
public class VerifySessionAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.HttpContext.Response.StatusCode = 401;
filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect =
true;
}
else
{
filterContext.Result = new RedirectResult(string.Format("/Account/Login"));
return;
}
}
}
}
This would allow your Angular interceptor to pick up the request and handle it appropriately.
Since IsAjaxRequest looks explicitly for the "X-Requested-With": "XMLHttpRequest" and AngularJS no longer provides that header with Ajax requests, you can add a configuration to the $httpProvider to always include the header.
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
}]);

Spring MVC back end ajax validation

For my current project Java/Spring project I have to validate a form. The webpage is a freemarker template file.
The <form> has no special attribute to send the data to the controller. The project uses Ajax to send the request. The controller doesn't receive the form at all.
When the user submits the data, a JavaScript function is called to receive all the data by collecting the elementID's. The data is put in a variable, like this (short version);
var userId = document.getElementById('input_id').value.toLowerCase();
var width = document.getElementById("width");
var height = document.getElementById("height");
The function then puts all the data into a JSON. This JSON is put in the Ajax, and then Ajax calls the right controller.
**Ajax code **
$.ajax({
url: url,
type: "POST",
dataType: "json", // expected format for response
contentType: "application/json", // send as JSON
Accept: "text/plain; charset=utf-8",
"Content-Type": "text/plain; charset=utf-8",
data: data,
success: function (response) {
// we have the response
if (response.status == "SUCCESS") {
console.log("succes");
//Redirect to the right page if the user has been saved successfully
if (type === "setupuser") {
window.location = "/setup/user/" + userId;
} else if (type === "simulatoruser") {
window.location = "/simulator/user/" + userId;
}
} else {
errorInfo = "";
for (i = 0; i < response.result.length; i++) {
errorInfo += "<br>" + (i + 1) + ". " + response.result[i].code;
}
$('#error').html("Please correct following errors: " + errorInfo);
$('#info').hide('slow');
$('#error').show('slow');
}
},
error: function (e) {
alert('Error: ' + e);
}
});
The following controller is called by the Ajax request:
#RequestMapping(method = RequestMethod.POST, value = "/adduser/{userType}")
#ResponseBody
JsonResponse addUserMapping(#ModelAttribute(value="user") User user, BindingResult result, #RequestBody String jsonString, #PathVariable String userType) {
def json = new JsonSlurper().parseText(jsonString)
String userId = json.userId
String userName = json.userName
user.setId(userId)
user.setName(userName)
log.warn("User id..... "+user.getId())
log.warn("User name..... "+user.getName())
JsonResponse res = new JsonResponse();
ValidationUtils.rejectIfEmpty(result, "id", "userId can not be empty.");
ValidationUtils.rejectIfEmpty(result, "name", "userName can not be empty");
if(!result.hasErrors()){
userService.addUser(jsonString)
res.setStatus("SUCCESS");
}else{
res.setStatus("FAIL");
res.setResult(result.getAllErrors());
}
return res;
}
As you can see, Ajax sends a JSON to the controller. The controller unpacks the JSON and puts the data into the user object. Then the user object is being validated using "rejectIfEmpty()" method...
Now I've been reading about making a userValidator class extending Validator, or simply putting Annotations in the bean class like:
#Size(min=1, max=3)
I prefer these annotations since you don't have to write special code for checking certain simple things (like the field not being empty .. #NotEmpty)
But that doesn't work because the controller doesn't take a user object the second it's called, instead it takes the JSON and then unpacks it (Validating is too late..)
TL:DR
Controller takes a JSON as a parameter instead of an Object. The JSON has to be unpacked and then validated in the controller as a java object using rejectIfEmpty as an example. I don't want a full page reload, but I still want to keep Ajax.
BTW: I want to validate the data against more things like regex etc. But the rejectifEmpty is a simple example.
Does anyone have an idea how to handle this?
I fixed the validation by parsing the JSON in the controller and setting it in the user object. The user object is then put in my UserValidator class and validated.
Link for more info using the validator:
http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/validation.html

Categories