Unable to logout from Laravel application when using event.preventDefault. Alternative? - javascript

So I a couple of forms in my application looking like this :
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
{!! Form::open(['action'=>['AdminController#update',$upload->id,0], 'method'=>'POST']) !!}
{{Form::hidden('_method','PUT')}}
<a class="dropdown-item" href="/manage">Approve</a>
{!! Form::close()!!}
{!! Form::open(['action'=>['AdminController#update',$upload->id,1], 'method'=>'POST']) !!}
{{Form::hidden('_method','PUT')}}
<a class="dropdown-item" href="/manage">Reject</a>
{!! Form::close()!!}
</div>
I am sending these forms using the following jQuery snippet:
$(".dropdown-item").click(function(e){
e.preventDefault();
$(this).closest("form").submit();
});
I noticed that when this snippet is not commented out, I am unable to log out from my Laravel app. The log out just doesn't work.
I am using standard Laravel authentication.
This is part of how I log out:
<a class="dropdown-item" href="#" onclick="window.location='{{ route('logout') }}'">Log out</a>
First, can someone explain why this is happening? I tried to investigate, but what I read didn't make much sense, since I am new to all of this.
And what would be the workaround here? How can I send these forms without the preventdefault method? Or how can I log out while using it? I'd prefer not to change my log out functionality.

So to log out the user, you need to hit route('logout') which is a predefined route when you scaffold laravel auth system.
The logout route its definded under /src/Illuminate/Routing/Router.php line 1125. It needs to be a post request in order to logout the user, there are no required parameters to be sent expect laravel csrf token, which is the token to make sure that the requests are comming from the app itself and not any external script.
If you go to logout function which is hidden under LoginController you will see a trait(simply to keep the class cleaner) AuthenticatesUser Trait it is responsible to logout the user.
In AuthenticatesUser trait you will find a method at line 151:
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->invalidate();
return redirect('/');
}
which in simple terms it logs user out of session guard (Guards define how users are authenticated for each request.) and then destroys the session and the user its logged out with a redir to homepage.
Now as said we need a post request with csrf token to log the user out:
<a href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
Logout
</a>
Form placed under the a href tag
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
{{ csrf_field() }}
</form>
The a href tag which has event.preventDefault() which in simple terms means prevent a href tag from acting how normally it acts. That being said a href tag will not redirect to the route, instead we have document.getElementById('logout-form').submit();"> which simply gets the form logout-form and submits it whenever the user clicks on that a href tag
Or simply change 'dropdown-item' class name for your logout form , since prolly that is being frozen when both forms are active.

Related

Send Javascript Push Notification - AFTER Form POST and URL redirection

Use case (Django Project):
I want to log in on my login page -> Therefore I use this form in html (login.html):
<form class="loginform" action="" method="POST">
{% csrf_token %}
<div class="loginform">
{{form.as_p}}
</div>
<br>
<input type="submit" class="btn btn-success loginbtn" value="Login">
</form>
In case of successful log in I will redirect with DJANGO to this URL (localhost/welcome/)-> welcome.html:
LOGIN_REDIRECT_URL = "welcome"
I am able to send javascript notifications with alertify, but only when using simple things such as
click on it or mouseover:
function notification(text) {
console.log(text)
alertify.success(text);
}
I tried it with onsubmit="javascript:notification("")" in the html form tag, however this will
be displayed only BEFORE the URL redirection.
So my question is:
How is it possible to activate /send the push notification AFTER the URL redirection and in
case of successfull POST/ Log in?
I really appreciate your help! Thank you a lot!!
Javascript is client-side. That means your alertify.success(text); will be executed client-side, once server already did his render process.
The authentication process is server-side. So you have to make your server make your alertify a part of the rendered content.
Knowing that, you just have to change your LOGIN_REDIRECT_URL content page to include in it a call to notification:
<!-- your html template comes here -->
<script type="text/javascript">
notification('You are now logged in');
</script>
Be remembered that the notification will then display each time the person visits this page. You may want either to redirect him again, or to introduce a variable in Django to avoid displaying it again.

Removing a Product using button in laravel route link

I created a sample products page using laravel framework,where I added a Remove button to remove that particular product onclick. below is the laravel route code added to the button
<button onclick= "window.location= '{{ route('customer.wishlist.remove', $item->id) }}'" > Remove </button>
here the item id is automatically generated from database which can also be seen by inspecting the remove button code.
on clicking the Remove button the product is getting removed. but when i run the route link separately in the browser then also the product getting removed because the same location link is given to button also.
I want this operation work only on Remove button click. if i entered the route url directly it should'nt. How can i resist that.
please help me on this
thank you
First of all you're using get method so it can be directly accessible to the browser.
Now if you don't want to allow a user to directly access that URL then you need to make the request as POST
<button onclick="event.preventDefault(); document.getElementById('delete').submit();">Remove </button >
<form id="delete" action="{{ route('customer.wishlist.remove', $item->id) }}" method="POST" style="display: none;">
{{ csrf_field() }}
</form>
Make your route as post

Create a secure POST link in express.js

I'm wondering if there's any simple way to create a link to submit a POST request to the server by using some Express.js technique or plugin.
It is also a way to secure more critical actions such as deletion of users. Adding also CSRF protection.
This is quite simple to do in some PHP frameworks such as CakePHP (with its postLink helper).
The way I'm doing it right now is by creating a hidden form by myself and adding in the html link an event to submit the form:
<form action="/users/delete/{{user.id}}" method="post" name="deleteUser{{ user.id }}" style="display:none;">
<input type="hidden" name="_csrf" value="{{ csrfToken }}" />
</form>
<a href="#" onclick="if (confirm('Are you sure you want to delete this user?')) { document.deleteUser{{ user.id }}.submit(); } event.returnValue = false; return false;">
Delete
</a>
This is exactly the way it works in CakePHP framework as well.
Inorder to create link to a POST request you can make use of client side techniques like capturing the click using javascript and generate a ajax post request to the server, Inoder to avoid CSRF attacks express middlewares are available(https://github.com/expressjs/csurf)
I ended up creating my own way to deal with them by using jQuery (but could also be done with javascript as well).
In my case, any link I want to send by POST will have to:
Contain the class postLink.
Contain the destination URL in the href attribute.
Contain the CSRF token in the data-csrf attribute.
Optionally contain the data-confirm attribute to specify a message to show as a confirmation before sending the POST request.
A link in the view would look like so:
<a href="/reject/23" class="postLink" data-confirm="Are you sure you want to reject this item?" data-csrf="NdiuZynW-thVmMqYPZqFFGxGcInQZn35mDf8">
Reject
</a>
Or without the confirm attribute:
<a href="/reject/23" class="postLink" data-csrf="NdiuZynW-thVmMqYPZqFFGxGcInQZn35mDf8">
Reject
</a>
The needed jQuery code is the following:
$(document).on('click', '.postLink', function(e){
e.preventDefault();
var url = $(this).attr('href');
var csrf = $(this).data('csrf');
var confirmed = false;
if(typeof $(this).data('confirm') !== 'undefined'){
if(confirm($(this).data('confirm'))){
confirmed = true;
};
}else{
confirmed = true;
}
if(confirmed){
$('body').append('\
<form action="'+ url +'" method="post" name="postLink" style="display:none;">\
<input type="hidden" name="_csrf" value="'+ csrf +'" />\
</form>\
');
$('form[name="postLink"').submit();
}
});
Basically what it does is applying the same technique of creating a form for each POST link that I mentioned in my question. The only difference is that I don't have to be bothered to create a form every time I want to create POST link.
This way the form will be created dynamically and appended to the body. Then submitted.
To make it secure I made use of the CSRF module for express.js.
If you don't need a secure POST link, then you probably could use the postLink plugin for jQuery.

Webmatrix2 - Url Redirect depending on UserRole in Razor

In the webmatrix2 starter site once you have logged in there is a the following link; "hello" bob#example.com {logout}
Clicking on the link will take you to a manage section however I would like it to go to a custom manage user profile page or business profile page depending on the role of the member that logged in. So in essence the code will check the user role and then depending on that role redirect to url(user manager) or (admin manager)
Is there any way to do this programattically in razor.
<section id="login">
#if (WebSecurity.IsAuthenticated) {
<text>Hello, <a class="email" href="~/Account/Manage" title="Manage">#WebSecurity.CurrentUserName</a>!
<form id="logoutForm" action="~/Account/Logout" method="post">
#AntiForgery.GetHtml()
Log out
</form>
</text>
} else {
<ul>
<li>Register</li>
<li>Log in</li>
</ul>
}
</section>
You can use a conditional block to render links depending on the Role which you can determine by using the Roles.IsUserInRole() method:
#if(Roles.IsUserInRole("User Manager")){
Click
}
#if(Roles.IsUserInRole("AdminManager")){
Click
}
Or you can leave the link as it is, and the determine which role the user is in once they land on the Manage page.

JSP and JSTL with the Onclick method

I have 2 links. In a session i store some data. I want if a user click in a specific link to look into the session and if the appropriate value contained, to continue. Else an AJAX pop up block will appears.
JAVASCRRIPT pop up block
function displaymessage(title,message,close)
{
resultReturn= $.confirm({
'title' : title,
'message' : message
'buttons' : {
close/*'Yes'*/ : {
'class' : 'blue',
'caption': close,
'action': function(){}
}
}
});
}
JSP with JSTL tags:
<div class="header">
<a href="<c:url value='/home'/>">
<a href="<c:url value='/further'/>">
</div>
<c:if test="${not fn:containsIgnoreCase(data, 'mykey')}">
<a id="get" class="right keepScrollPosition"
onclick="return displaymessage('<spring:message code="access.denied.title"/>'
,'<spring:message code="access.denied.message"/>','<spring:message code="access.denied.close"/>');"
href="#" /></a>
</c:if>
For example, if in the session contained the value 'mykey',then can go into the link home, else a pop up will appears. In case, in the session contained the value 'mypassword' and select the further link can continue, but if select the home link a pop up block will appears.
I'm stuck and i need some help on how can i do this.Please help me
UPDATE
I'm trying the following script but it doesn't work:
<li><a href="<c:url value='/home/'/>"<spring:message code="home_page"/>
onclick="if(<c:if test="${not fn:containsIgnoreCase(data, 'mykey')}">){
return displaymessage('<spring:message code="access.denied.title"/>'
,'<spring:message code="access.denied.message"/>','<spring:message code="access.denied.close"/>')" href="#" ;
}
</a>
</li>
You can't use client-side JS to check a server-side value held in the session. Instead, you need to use JS to make a GET call to a request mapping which runs servers-side code to check the session. Flow could be as follows:
User clicks button/image/something on page
JS fires from click, makes AJAX call (e.g. $.get) to request mapping /check_session.do
Request mapping checks session for value, returns true or false as JSON
Client-side JS processes returned JSON, blocks or proceeds based on returned value
Alternatively, use JSTL to access the session and write the session field's value to a hidden form field on the page, which the client-side JS then reads. Example: http://www.steve-farmer.com/examples/el/ui/ses-attr-name.jsp

Categories