Laravel session expiration on Carbon::setTestNow() - laravel

I'm using Carbon::setTestNow() for testing purpose on laravel 4.2 project and all the time when I make next refresh after the method call where I used Carbon::setTestNow() system log me out.
It happens because session cookie expiration date sets to Carbon::setTestNow() date. How can I override that because it's annoying to make login again all the time. Thanks, hope some one can help me to find some solution.

Just come to the same situation and here's the result:
The "official way" is to extend the Illuminate\Session\Middleware::addCookieToResponse or ::getCookieLifetime
But I find it's quite complicated and bloated.
Come to a simple solution:
Check if the provided mock time is from the past, override the session.lifetime if needed, here's the codeblock I added into app/start/global.php
// Set mock time if requested
if ( ! empty($_GET['mocktime'])) {
try {
$real_time = \Carbon\Carbon::now();
$mock_time = \Carbon\Carbon::parse($_GET['mocktime']);
\Carbon\Carbon::setTestNow($mock_time);
$diff_min = $real_time->diffInMinutes($mock_time);
if ($diff_min > 0) {
// requested mock time is from the pass
$org_lifetime = Config::get('session.lifetime');
Config::set('session.lifetime', $diff_min + $org_lifetime);
}
} catch (Exception $ex){
Log::warning('Mocktime requested but unable to set: '.$ex->getMessage());
}
}
As this answer is coming late, hope it can help someone later.

Related

Cookie-less Laravel sessions

We have a small quiz type functionality built in Laravel to be embedded in a site via an iframe served from a separate domain (to work around CMS limitations).
It uses sessions to keep track of the user's progress in the quiz. This doesn't work in Safari (Mac/iOS), I believe because Apple disable cookies issued from within an iframe.
Assuming that limitation is one we're stuck with, has anyone had any success making Laravel sessions cookie-less? I found this code on Github, which looks promising but is old enough (and incompatible with current Laravel) that I can't tell if it's going to be a solution.
In case it helps someone else, or anyone can see any silly errors in my code, this is what I did (an adaption of the Github code, to work in Laravel 9).
I extended StartSession and SessionServiceProvider (to use my new StartSession). I created an override for handleStatefulRequest in Start Session, and where it adds a cookie to the reponse (it calls addCookieToResponse) did this:
if ($request->cookies->get($session->getName())) {
$this->addCookieToResponse($response, $session);
}
else {
// Add session ID to header
$this->addIdentifierToResponse($response, $session);
}
That new function looks like this:
protected function addIdentifierToResponse(Response $response, Session $session)
{
if ($this->sessionIsPersistent($config = $this->manager->getSessionConfig())) {
$response->headers->set("X-Session-Token", $session->getId());
}
}
I also changed the getSession method to get the session ID from that newly set header (when no cookie found):
public function getSession(Request $request)
{
return tap($this->manager->driver(), function ($session) use ($request) {
if ($request->cookies->get($session->getName())) {
Log::debug('1. Set session ID from cookie');
$session->setId($request->cookies->get($session->getName()));
}
else if ($request->headers->get("X-Session-Token", $request->input("sess_id"))) {
$sessionToken = $request->headers->get("X-Session-Token", $request->input("sess_id"));
$session->setId($sessionToken);
}
});
}
I created a Github repo containing the whole thing.

laravel 4.2. user permissions and hiding link source

I am a total newbie with Laravel and learning it now for a week. I have some basic questions that I can't find an answer to. Next week I will start with developing CRM system and I need some info from experienced developers who could tell me is the approach I am attending to make a good one.
I will need some authentication system, like 4 groups of users (Admin, Basic, Manager, Office) where Manager and Admin will add the Basic users. There will be few view and features and every groups will have defined access to each view and feature. Since few days I am searching for packages, watching the tutorials and learning. I found an interesting package for which I think it could help me with this user-group-permission things.The package is Sentry. Could this help me with my requirements?
What is the case when for example I have a user in group Basic and he deletes for example some comment with the button. On the left side down in the browser the user can see the link to this comment when he hovers the link. For example www.test.com/comments/345/delete where the id is 345. What if user types that with another id, that means he can delete another comment. I found some suggestions on how to solve this, to make it with jQuery and javascript so the link wouldn't be shown and POST would be made with for example with AJAX. But since I am a newbie, I am thinking how much time would this take and is this a good approach at all? Could package Sentry from 1. question help me with the permission on what route each group can access?
Any help or advice would be appreciated.
Sentry does what you want, yes. Here's a question with some answers explaining the permissions part.
The visible link part can be avoided by doing a POST request instead of a GET request.
When you open your form, you add a method attribute.
Form::open(array('url' => 'foo/bar', 'method' => 'post'))
A GET request will put the parameters in the URL, hence the visible ID. Using a POST request will put the parameters in the headers, thus hiding it from the URL.
An example could be deleting a comment. A GET request could look like this:
http://www.example.com/comments/delete/1
And the parameters would be defined in your method signature:
public function getDelete ($id) {
Comment::find($id)->delete();
}
Where the POST equivalent would be
http://www.example.com/comments/delete
And the parameters would be defined in your Input class, you would get them using the get method
public function postDelete() {
Comment::find(Input::get('id'))->delete();
}
1) The best package to help you with that is Sentry indeed.
2) To make sure an user can delete only his comments you can do something like this (but there are more solutions either you do it with Ajax or not):
public function destroy($id) {
$user = Sentry::getUser();
$comment = Comment::find($id);
if($comment) {
if($comment->user_id != $user->id) {
return Response::back(); // optional message: Permission denied!
}
$comment->delete();
return Response::back(); // optional with message: Deleted!
}
return Response::back(); // optional message: Comment not found!
}
You can use Sentry in this case to get the logged in user and check for user id. I think you should let user delete their own comments always but if you need special roles (Admins for example) to be able to delete any comment, or special permission comments.delete (For some Managers) - you can use Sentry as well:
public function destroy($id) {
$user = Sentry::getUser();
$comment = Comment::find($id);
if($comment) {
if($comment->user_id != $user->id && !$user->hasRole('Admin') && !$user->hasPermission('comments.delete'))) {
return Response::back(); // optional message: Permission denied!
}
$comment->delete();
return Response::back(); // optional with message: Deleted!
}
return Response::back(); // optional message: Comment not found!
}
A nicer way of making the DELETE thru a Form request check this:
Laravel RESTfull deleting

jQuery ajax post request doesn't work suddenly,

I have a jQuery ajax call in my ZF2 application. It just worked before. Suddenly it won't work anymore. Even when I put a non-existent action in the request, it doesn't give a server error like it did before. It just seems like it doesn't make the request.
There's absolutely no errors in the console. Everything works up until the point where I make the request. This is the function it's in:
$('.expand').click(function(){
var CCID = $(this).parent().attr('id');
CCID = parseInt(CCID);
console.log(CCID); // Works
if($.inArray(CCID,$expanded) > -1){
foldin(CCID);
} else {
console.log('Works up to here.'); // Works
$.post('admin/expand', {
id: CCID
},function(data){
console.log('Doesn\'t log this.'); // Doesn't work
if(data.hasOwnProperty('info')){
console.log('sup');
expand(data.info);
} else {
console.log('Can\'t find customer info.');
}
},'json');
}
});
Like I said before, absolutely no errors, and logs all the bits that I commented that do. Kind of hoping I made a stupid mistake and you can spot it. Been over it a bunch of times already, can't find it.
I'll add the action in my controller if anyone want to see it, but the post request doesn't even seem to look for it, because it doesn't give an error if I give it a bogus action.
edit: below is some extra information
So I added a failure handler at the request of a commenter, it returned:
failed [Object, "parseerror", SyntaxError]
In SyntaxError it says "unexpected token <", but there's none in the .js file and I can't find where it tells me what line/file it finds it in. That would help, probably.
This is the action I call in my controller. Doesn't seem to find it at all though:
public function expandAction(){
$request = $this->getRequest();
$response = $this->getResponse();
if($request->isPost()){
$post_data = $request->getPost();
$CCID = $post_data['id'];
$customer = $this->getCustomerTable()->getCustomer($CCID);
$response->setContent(\Zend\Json\Json::encode(array(
'info' => $customer,
)));
}
return $response;
}
Arun P Johny taught me to use the Network tab in Google Chrome developer tools to figure out the problem. From there I could see that the path 'admin/expand' should've been 'expand'.
Might be a bit of a localized answer but I feel that his advice to use the network tab was helpful enough to warrant an answer. Maybe it'll be helpful to someone else at some point.

Grails Hibernate Session or Spring Transaction destroying Domain validation errors

So my problem is that my validation errors are being deleted from my domain object before I can render them on the page. I thought I had fixed this error in the past, but it has crept up on me again.
Here is a look at my original implementation. The errors were being cleared when tripService.stepData(trip) was being called.
Edit- I should not that I only experienced this issue when the page adds to a hasMany relationship.
Controller -
Trip trip = tripService.savePrePaymentInfo(params)
if (trip.hasErrors()) {
render(view: "step4", model: tripService.stepData(trip))
}
else {
redirect(action: trip.status.action, id:trip.id)
}
Service -
Map stepData(Trip trip)
{
Map returnSet = [:]
returnSet.status = Status.findAllByActionNotEqual("review")
returnSet.trip = trip
returnSet
}
So I did some reading online and someone one on a forum post like 2 years ago said there was something in hibernate..possible bug... I don't know, but their suggestion worked. The suggestion was to wrap the controller in a withTransaction:
Trip.withTransaction {
//Controller code here
}
This has been working for me fine. The issue now is that I have a taglib in my view that calls tripService again. When that call is being made it is now clearing my validation errors. This is getting really frustrating. Does anyone have ANY idea on what I can do to resolve this?
Edit: Adding service method being called from taglib:
String findBannerName(Long pidm, String format = 'LFMI')
{
"abc"
//It really doesnt matter what is here - tried just returning this string and it produced the issue
}
Are you sure the trip.errors property is populated in the first place?
Also, which tripService method are you calling in the taglib?

Magento - many of same cache requests

today I realized that the Magento doest a lot of same requests to my memcached server, it's requesting the key Zend_LocaleC_en_GB_currencynumber_ . Do you anyone know where is it generated and how can I improve it? It's probably somehow related to rendering of price box but I dont see reason why it's 50 times in a page. Thanks, Jaro.
Edited:
So far I did quick fix
Zend_Cache_Backend_Memcached::load
public function load($id, $doNotTestCacheValidity = false)
{
if ( isset($GLOBALS[$id]) ) {
return $GLOBALS[$id];
}
$tmp = $this->_memcache->get($id);
if (is_array($tmp) && isset($tmp[0])) {
$GLOBALS[$id] = $tmp[0];
return $tmp[0];
}
return false;
}
It's not nice but seems to be working. At least many of requests agains memcached server disappeared. Jaro.
It is one of the known issues in Zend Framework community. It even was reported as an improvement for 1.0.3 release (http://framework.zend.com/issues/browse/ZF-2311).
You fix make sense for Magento where a lot of calls to Zend_Currency is performed and connection to memcached having some limitations or slow enough.
For instance on most of the projects we are using memcached and haven't experienced too big loss in page load time with this calls.
However you can fix it in Magento to make a workaround with ZF:
Rewrite core/locale model in your module
Override currency() method
public function currency($currency)
{
if (!isset(self::$_currencyCache[$this->getLocaleCode()][$currency])) {
$currencyObject = parent::currency($currency);
$currencyObject->setFormat(array(
'format' => Zend_Locale_Data::getContent($this->getLocale(), 'currencynumber')
));
return $currencyObject;
}
return parent::currency($currency);
}

Resources