Get logged in user by searching cakephp 2.x session table - php

I wanted to use the session table to get a list of all logged in users. To do this I attempted to use the following code to query the cake_sessions table:
$this->loadModel('CakeSession');
$sessions = $this->CakeSession->find('all', array('fields' => 'data'));
// next I process session data to find logged in users
But running this code I get the following error:
Call to undefined method CakeSession::find()
If I use the following code to directly access the table it works just fine:
$db = ConnectionManager::getDataSource("default");
$sessions = $db->fetchAll("SELECT data from cake_sessions");
// next I process session data to find logged in users
Is accessing the session table restricted? My current solution works just fine but I am confused why I cant use the the CakeSession->find().

Because CakeSession is not a model class. See
http://api.cakephp.org/2.8/class-CakeSession.html
The class you refer to is a datasource as the "namespace" tells you as well: Cake\Model\Datasource. In Cake2 session access was implemented as datasource. "Model" is a layer not just a single type of files.
Create a proper session model class in your apps Model folder. See http://book.cakephp.org/2.0/en/models.html
You might have to name it different to avoid conflicts because Cake2 is not using real php namespaces unlike Cake3.

Related

How to invalidate particular session in Laravel (with user using remember me feature)

Using Laravel 5.1 & 'file' Session Driver,
I'm trying to provide facility to user to track their sessions and invalidate them anytime they wish by keeping a record of their session_id within the database. With Database, I mean, I maintain a table called user_sessions which associates user_id with their session_id (obtained by Session::getId()).
So, to invalidate Session, I tried the following code,
$sessionId = Session::getId();
Session::setId($sessionId);
Session::invalidate();
and it works perfectly fine, for the case where, where user does not uses Remember Me feature.
For the case where user uses Remember Me feature, this above code does not work, So, I additionally, tried setting remember_token field to null as specified here in this answer, but with this, all sessions of the user get destroyed including the current one.
You can simply use
use Illuminate\Support\Facades\Session;
Session::forget('YOUR_SESSION_ID');
If you want to get the current session Id:
Session::driver()->getId();
I hope it helps
Sessions are meant to be short-lived. If you want something a bit more permanent you can use some sort of a long term user settings table.
Create a table user_settings:
id (PK), user_id(FK users table), settings(BLOB?), created_at, updated_at
Add a model:
class UserSetting extends Model {
public function user() {
return $this->belongsTo(User::class);
}
}
You can also associate the user with these via :
class User extends Model {
//...
public function settings() {
$this->hasMany(UserSetting::class);
}
}
You can then get all user sessions via:
User::find($u)->settings();
When a user logs in regularly or automatically via a remember token a Login event is fired.
You can listen to this in your event service provider:
\Event::listen(\Illuminate\Auth\Events\Login::class, function ($event) {
// Here you can load the last settings in the session if you want e.g.
session(['current_settings' => $event->user->settings()->latest()->value('id') ]);
// or you can just make a new entry:
$settings = new UserSettings();
$event->user->settings()->save($settings);
session(['current_settings' => $settings->id ]);
});
Note that you will have to manually persist things that need persisting instead of just putting them in the session.

Laravel - storing into session from service provider?

I am using GeoIP package to get the user's IP and translate it into a zipcode. I don't want to do that for every request that the user is making but rather do a one time IP to zipcode, store it into session and then when I need to use it just check if the zipcode exists inside the session.
I tried to place the code inside AppServiceProvider#boot but it does not work. It is not remembered into the session. I tried inside routes but not working as well.
edit
The code inside boot method of appserviceprovider. This is just a test.
If (! Session()->has ('zipcode'))
Session(['zipcode' => geocodeZipcode()]);
The problem is that this runs everytime since the zipcode is not persisted in the session. The if is never false from my tests so far.
Where do I need to put the code to store the zipcode into the session and have it remembered even if the user is not logged in?
I basically need something like this:
1- User accesses a page on the server for the first time (any page)
2- I get the user IP and translate it to a zipcode
3- I store the zipcode into the session
4- For every other request the user makes I check if the zipcode exists into the session. If not I execute step 2.
5- Use the zipcode for its purpose
Where should I place the step 2 and 3?
In Laravel the session is initialized via middleware, and all the middlewares execute after the service providers boot phase
This is the reason why in your service provider you can't access the session: it has not been initialized yet
You should place your steps 2 and 3 in a middleware:
class ZipCodeMiddleware
{
public function handle( Request $request, Closure $next )
{
//ZIP CODE NOT FOUND IN SESSION: CREATE IT AND STORE
if ( ! Session::has( 'zipcode' ) )
{
//get ip and translate to zip
//store zip in the session
}
//use zip code here or access it later from Session
return $next($request);
}
}
Once you've stored the zip code in the session, you can access it from a controllers directly from the session, or, you could instance a class in the middleware and re-access it later with:
//use zip code here or access it later from Session
$zipClass = new ZipClass( $zipCode );
App::instance( ZipClass::class, $zipClass );
This way you can auto-inject the ZipClass depencency in your controllers and Laravel will give you back the $zipClass instance you built previously in the middleware

What data should in I store in a session variable in Laravel 5

I am new to laravel. I have been working on a laravel 5 app with different types of users. I need information about which type of user is currently logged in different sections of my views:
Currently, I have been doing something like below on various controller methods and with the user object, I can determine which type of user it is in my view:
In Controller:
public function someMethod(){
$user = Auth::user();
return view('applications.show', compact('user'));
}
In View:
if($user->is_manager)
// do this
else if($user->is_admin)
// do that
Because I need information about the user-type in various views, I have been calling Auth::user() in several places and I am beginning to think that this is adding some load on the DB. Is it better to store the user-type in a session variable and what kind of data should I be storing in my session?
It wouldn't be an issue storing it in the session.
In the is_manager function in your User class, you could do something like the following...
public function is_manager()
{
// Check if the session has been set first.
if(\Session::has('is_manager')) {
return \Session::get('is_manager');
}
// Do your necessary logic to determine if the user is a manager, ex...
$is_manager = $this->roles()->where('name', '=', 'manager')->count() == 1;
// Drop it in the session
\Session::put('is_manager', $is_manager);
return $is_manager;
}
Keep in mind if your session driver is set to database, then this obviously isn't going to help.
We have organized common model calls as follows;
Base classes for controllers, models, libraries, composers, commands and jobs which get these models. All related classes extend from these base classes thus have everything they have.
Master view composer to serve as base data gatherer for all views.
Query caching through Redis. All the above classes get the user through a cached query with timeout of an hour thus the query is executed only once per hour per user.

Symfony Session Values Lost

I'm experiencing a problem with symfony's session values handling.
Basically, the problem is this, I have a action filter activated that takes the values of the module and action executed and stores them in the session superglobal.
This is my filter's code:
<------BEGIN CODE---------------->
class getPrevModuleActionFilter extends sfFilter
{
public function execute ($filterChain)
{
//---------------Code to execute *BEFORE THE ACTION* execution---------------
if ($this->isFirstCall()) # Execute this filter only once
{
// Filters don't have direct access to request & user objects => Use context object to get them
$request = $this->getContext()->getRequest();
$user = $this->getContext()->getUser();
if($request->getParameter('action') !== "setCulture")
{
$_SESSION['prev_module'] = "M=".$request->getParameter('module');
$_SESSION['prev_action'] = "A=".$request->getParameter('action');
}
}
//---------------Execute next filter in the chain---------------
$filterChain->execute();
//---------------Code to execute *AFTER THE ACTION* execution, before the rendering---------------
//(...)
}
}
<------END CODE---------------->
The weird thing is that if I do a print_r on the front web controller at the very last minute I see that:
When an action that's not 'setCulture' all goes well (ie, the session gets previous module and action as it should)
When action 'setCulture' gets executed: Symfony stores following values in session:
Array (
[prev_module] => M=
[prev_action] => A=
(etc)
)
ie, it looses the values of session for those 2 entries.
I tried using different namespaces, I tried using symfony's setAttribute from sfUser to handle session values. At the end I tried the raw session handling of PHP. Apparently it seems that the shutdown methods of the factories related to user and storage of session values mess up the session values!
I need your help, please.
SPECS:
Symfony version: 1.4.6
PHP: 5.3
I have Symfony's cache disabled
I'm running the code with the frontend_dev.php controller
Well, I guess Symfony messes up SESSION and COOKIES when used in filters.
I ended up creating my own filter mechanism that performs actions for an entire app.
So, to clarify, my choice was:
create a class autoloaded in root lib folder, that has a static method called 'fe_app_init'
add a preExecute method to the actions of each module in FE app that uses fe_app_init from that class
Now the fe_app_init() handles the values in SESSION rightfully.
It's a shame that Symfony 1.4 has a tool such as filters but then messes up SESSION and COOKIES handling in those.

Codeigniter Datamapper save() not actually saving to database

I'm running CodeIgniter 1.7.3, Datamapper DMZ 1.7.1 (and no, upgrading is not an option), MySQL 5.1, and the Cron Job Boostrapper for an application I'm building. I'm attempting to extract information from an XML file and save it into a database. Getting the data works just fine, as does getting data from the database, so I know it's neither an issue with the database connection, nor the XML file.
$this->site = $this->site->get_by_short_name('site');
//Load the XML files into variables so we can do stuff with them.
$doctors = simplexml_load_file(realpath('../xml/doctors.xml'));
foreach ($doctors->children() as $doctor) {
$dr = new Doctor();
$attrs = $doctor->attributes();
/* See if the Doctor already exists. If so, update it.
* Datamapper won't update fields that don't change, so if nothing's
* changed, then the DB call won't be made.
*/
$dr->get_by_drkey($attrs['Key']);
$dr->drkey = $attrs['Key'];
$dr->first_name = $doctor->FirstName;
$dr->middle_name = $doctor->MiddleName;
$dr->last_name = $doctor->LastName;
$dr->long_name = $doctor->LongName;
$dr->degrees = $doctor->Degrees;
$dr->pic = $doctor->ImageURL;
$dr->save($this->site);
}
I've checked the return value of $dr->save($this->site) and it's coming back as true ("successful save"), but the data isn't saving, and there's no error. I've tried without the relation (removed the requirement for it in the database), so it should save without error, but it still doesn't save. I also double-checked the relationship setup in the models and they're fine.
I also tried bypassing Datamapper and doing a straight $this->db->insert('doctors',$data) with the data converted to an array, but the data still doesn't save. I've also tried running it from the browser (bypassing the bootstrapper) to see if the issue had to do with running from the command line, but that also didn't work. I'm also not autoloading any session or authentication libraries, so that known issue with the bootstrapper isn't being triggered.
Does anyone have any insight into why this might not be working?
I've found what was going on. It turns out that the attributes of the SimpleXML objects (the individual records) weren't getting picked up by Datamapper as strings, so they weren't getting escaped, and MySQL was choking. Typecasting them when setting the model object's values ($dr->first_name = (string)$doctor->First_Name;) fixed this problem.
I was able to get the insert query through $dr->check_last_query() after the object attempts to save.

Categories