Acl not working Getting error that ID is empty - php

I have an Acl that i am trying to implement on my site which is database driven. I have used this code here creating ACL with database. I am using a module based structure and this example happens to not be. So i placed everything that is supposed to go in application model, in the core module model. This script authenticates everyone that views the site and if they do not have a account it logs them in as guest. My issue is that it authenticates the user as Guest but i am getting an error on the mapper getbyId, it has the user id as 1 (guest) why is it returning and error? Is it something with the module based structure i am using?
I tried posting on the site itself but have not gotten an answer yet, it was developed a while ago - blog might be dead.
thank you for your help!
Updated 6:44 EST May 2nd:
I think my problem lies here:
private static function getAuthAdapter($loginField='login')
{
$dbAdapter = Zend_Db_Table::getDefaultAdapter();
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
$authAdapter->setTableName('users')
->setIdentityColumn($loginField)
->setCredentialColumn('password')
->setCredentialTreatment('MD5(CONCAT(?,salt))');
return $authAdapter;
}
I already have an established data connection through my application.ini and Bootstrap.
protected function _initDatabases()
{
$this->bootstrap('multidb');
$resource = $this->getPluginResource('multidb');
$databases = Zend_Registry::get('config')->resources->multidb;
foreach ($databases as $name => $adapter)
{
$db_adapter = $resource->getDb($name);
Zend_Registry::set($name, $db_adapter);
}
}
So now the question would be - How do i change the getAuthAdapter to use what i already have?
thanks again
Updated 9:38 EST May 3rd:
The above now is not an issue. actually it never was. As i dug further, when i created the Guest User it did not encrypt the password and did not add salt. So now i am logged in but still have same error.
This error comes from not getting the role_id.
if (!$auth->hasIdentity()){
$auth = Zend_Auth::getInstance();
$role_id = $auth->getIdentity()->role_id;
echo "Role Id =" . $role_id; exit;
} else {
echo "No Identity"; exit;
}
The above returns - Role Id =
So i have Identity why can i not get role_id - where role_id is the column name.
thanks again.
Updated 10:17 May 3:
For every ones knowledge. This is fixed. I have not explanation other than it was in some kinda of funk. I cleared the identity and it logged back on as Guest and the site came up.
So problem solved for me. This is a really great script so if you are looking for a data driven ACL dont hesitate to use the link above.
thanks

Related

Using user plugin session in another plugin within OctoberCMS

I’m new to Laravel and OctoberCMS, there is a lot of documentation on both but because I don’t have much of an understanding of either I would really appreciate some help. It's also quite confusing trying to understand both at the same time, especially as there is way more documentation about laravel than October.
Currently, I wish to extend a plugin (Link to their extending plugin documentation). I need to use the session (username or email) from the rainlab user plugin (Link to their Git) and insert it into another plugin.
I'm upgrading the other plugin that currently relies on users entering their name via a form and replacing this with their username or email address once logged in.
My Layout contains the user plugin session:
{% component 'session' %}
The user plugin session works fine on the rest of my pages but I have gotten a 'value not found' error with my previous attempts using it with the plugin.
I know I need to either link the plugins or create a new one, and retrieve the username (or email) from the users database and insert it into another table, just can’t quite work out how to do this. To make matters worse I don’t have experience with MVC either!
Added this function (from an example I found) to the second plugin's Plugin.php page:
Plugin.php
public function boot()
{
Event::listen('rainlab.user.register', function($user) {
// Code to register $user->email to mailing list
});
}
But I got 'Undefined' error.
I've also tried adding a Routes.php file as I thought there may be an issue with middleware.
Routes.php
Route::get('/test', function () {
dd(
Auth::getUser(),
BackendAuth::getUser()
);
})->middleware('web');
Received this error:
"Call to undefined method RainLab\User\Facades\Auth::getUser()"
I’ve been banging my head against the wall for a week now and any tips or explanations would be greatly received. If you require any other bits of code please let me know. I haven't added any more bits of code as I know those pieces didn't work (being going around in circles and it would be a bit erratic and not much use) and I don't want to spam code on this page. I've shown the bits above to try and explain some previous thought processes. Also, it's the start of my project and not much code has changed from the generic code available to you from the OctoberCMS and User Plugin Gits.
I believe an explanation and some help here would benefit a lot of people, I can see I’m not the only one to have issues, partly down to the changes in the latest version of laravel.
Any thoughts and explanations would be much appreciated.
UPDATE:
To make it clearer where I need my session to appear I've included the code below. $name needs to be replaced by a new variable like email or username (from session).
components\Chat.php
$name = 'anonymous';
if ($n = Input::get('name')) {
$name = strip_tags($n);
}
$message = new Message(['text'=>$text, 'user_id'=>$user_id, 'name'=>$name]);
$message->save();
return $this->getMessagesOutput($message->id, [$message]);
}
It will be really Easy if you are adding session in layout {% component 'session' %}
now on entire page you can use {{ user.email }} directly in twig to get user email
if you need to use using PHP you can use Auth facade
this code must me in component which are included in page which is using that layout or in its life-cycle methods
// Returns the signed in user
$user = Auth::getUser();
echo $user->email;
you can not directly use route because route is separate from page execution so Auth will not work there.
"I need to use the session (username or email) from the rainlab user plugin (Link to their Git) and insert it into another plugin."
just create new component which have this code and include it in page.
can you share details what you need to do and how you are doing to get details and on which time you need to use that details so i can answer it precisely.
UPDATE
// by default name
$name = 'anonymous';
$user_id = 0; // if user is not logged in
// if user is logged in then use session
if($sessionUser = \Auth::getUser()) {
// if user didn't set name then you can assign some default value here or email
$name = $sessionUser->name != '' ? $sessionUser->name : $sessionUser->email;
$user_id = $sessionUser->id;
}
// not needed but if user want to edit its name then we use that one
if ($n = Input::get('name')) {
$name = strip_tags($n);
}
$message = new Message(['text'=>$text, 'user_id'=>$user_id, 'name'=>$name]);
$message->save();
return $this->getMessagesOutput($message->id, [$message]);

do I have to check login session when initiating PHP class?

I used to program php in procedural way. Since I would like to learn more about OOP I have decided to program php in OOP way for my new project.
Anyways, let's say I have a project that requires user to login. Which means in login.php once user enters the correct username and password, it will be redirected to index.php and will start loading all the products from the product table and display them nicely in index.php.
Before, how I did this was, in login.php I'll have the following code:
login.php
session_start();
...
if (loggedCorrect($user, $password)) {
$_SESSION['loggedinuser'] = $user;
//redirect to index.php
}
index.php
session_start();
if (isset($_SESSION['loggedinuser']) {
//select fields from products table and display them
...
}
so in OOP it will be something like:
login.php
session_start();
$user = new User($user, $password);
if ($user->hasCorrectLogin()) {
$_SESSION['loggedinuser'] = $user->getUsername();
//redirect to index.php
}
index.php
session_start();
if (isset($_SESSION['loggedinuser']) {
$products = new Products();
//display all products
}
Product class
class Products {
private $productArray;
...
__construct() {
//select all products from mySQL table then put every product in productArray
}
...
}
My question are:
when initiating object (like Products in my case). do I have to check login session? if so, should I do it inside __contruct? or should I do it before the "class Products" line?
I also have a cronjob.php, which will be executed every x minutes. When it's executing, it will create some objects like Products and analysis them. So if login session checking is required, then I'm not sure how to make this works, as cronjob doesn't support session.
Please advise
Quick answers
No. Your domain objects themselves should not be dependent on a logged in session; however, they may need a User instance to perform certain duties, such as only showing the products that a particular user is able to see.
Because of #1, this is now trivial.
Code review
First let's consider your login page code:
$user = new User($user, $password);
if ($user->hasCorrectLogin()) {
In this code, it would seem that User interacts with the database and has knowledge how to validate credentials. That seems a bit too much responsibility for a single class.
It could perform password validation by keeping the hashed password inside the object, but you would only need to validate a password once, so there's really no need to keep that field around. Another reason not to have it done here is when you need to consider strengthening your passwords on-the-fly, which could be a site policy to scale with growing hardware (e.g. when you're using bcrypt).
It should definitely not be doing database interaction; to separate both database interaction and password verification from the User class you could consider adding an authentication service.
try {
$user = $authService->login($userName, $password);
$_SESSION['loggedinuser'] = $user;
// redirect to index.php
} catch (InvalidLoginException $e) {
// oops, username or password invalid
}
Inside the authentication service, you could add another layer of abstraction to load the user record (using a data mapper for instance).
Instead of only storing the username in the session, you can store the whole User object as well. In some cases this may lead to inconsistencies, but it saves round trips to the database.
Now, let's observe the product overview page:
$products = new Products();
In terms of naming I would say that Products is not a good candidate to describe a collection of objects. A name such as ProductList or ProductCollection is better.
As with the authentication above, it's unclear how the Products class gets populated; it should come from some storage, so let's introduce the repository that will provide the list of products:
$productRepository = new ProductRepository($db);
$products = $productRepository->getAll();
In the simplest scenario, the repository gets initialized with a database instance; more levels of abstraction can be applied when necessary.

combining cakephp's auth with hybridauth (oauth)

I suppose I'm just looking for a bit of guidance as to how to set up my User + Authentication area on my website with cakephp 2.0.
I have a basic login and register functionality set up within my UserController.php, which also contains functions for looking up and displaying other users.
I also want to use the hybridauth plugin to allow for users to login/register using their social media / oauth account (allowing for more than one social account per user in the database, so that the same user could use either their twitter or facebook details, for example). I'm only having 3 providers at this time, so I plan to just create 6 columns in my user database, with the token and outhid in the same user row. This is in another controller - HybridauthController.php.
I have the hybridauth set up so that it creates its 'hybridauth' object from the account details, which is fine - but I want to be able to merge the whole 'authentication' together, so that my cakephp session contains the hybridauth session data (object) creating my general "current user" array that I can use, and set some generic variables within, depending on whether they are from oauth or not.
I don't currently store sessions in a database, and ideally I would like for allow persistent sessions for all, whether they use an oauth account or not. I don't really understand how persistent sessions are supposed to work with hybridauth, because how in this example would the $current_user_id be filled in when the user returns the next day? Not via a cookie, surely?
http://hybridauth.sourceforge.net/userguide/HybridAuth_Sessions.html
So in summary I'm looking for a simple solution to combine all of my 'session' / 'auth' / 'user' data into one simple array in the users session. Hopefully that all makes sense!
Thanks
Late to answer, but hopefully it'll help you or someone else searching.
I had a tough time integrating HybridAuth into a preexisting CakePHP (1.3) app that was already using Cake Sessions and the Auth component. I initially tried using the Cake example that I downloaded from the HybridAuth website, but that did not work for me.
Our preexisting User controller already had a bunch of logic in it including a beforeFilter method. That's where I inserted my session_start() as opposed to above the class declaration in the HybridAuth Cake example:
class UsersController extends AppController {
...
var $components = array('Session','Auth','Email');
...
public function beforeFilter(){
// following two lines may not be necessary for your setup
$this->Auth->allow('oauth', 'oauthLogout');
$excludeBeforeFilter = array('oauth', 'oauthLogout');
if ( ! in_array($this->action, $excludeBeforeFilter) ) {
// preexisting Auth logic -- I had to bypass it because
// calling `session_start` was messing up Cake's Auth
...
} else {
/* THIS IS NECCESSARY FOR HYBRIDAUTH (OAUTH) */
/* setting the session ID made it so users could NOT log
in from a 3rd party and our site */
session_id($_COOKIE['CAKEPHP']);
session_start();
}
}
...
public function oauth($provider){
$this->autoRender = false;
// include HybridAuth
require_once( WWW_ROOT . 'hybridauth/Hybrid/Auth.php' );
try {
// I stored my provider config in a Cake config file
// It's essentially a copy from the site/Cake example
$hybridAuth = new Hybrid_Auth(Configure::read('HAuth.config'));
$adapter = $hybridAuth->authenticate($provider);
$userProfile = $adapter->getUserProfile();
// method on the User model to find or create the 3rd party user
$user = $this->User->findOrCreate($userProfile, $provider);
if ( ! $user ) {
echo 'Unable to find/create user';
} else {
// configure your fields as necessary
$this->Auth->fields = array(...);
$this->Auth->login($user);
}
} catch (Exception $e) {
echo $e->getMessage();
}
}
}
At this point the 3rd party (HybridAuth) user is accessible in the Auth Component. This way a user was only logged in one 3rd party service or the preexisting login (but not both).
I also had an issue logging out. To do that I basically destroyed all sessions/cookies to be safe. In the oauthLogout method of the UsersController:
// probably overkill/paranoia
$this->Auth->logout();
$this->Session->destroy();
session_destroy($_COOKIE['CAKEPHP']);
/* these two seemed to make the difference
especially the 4th parameter */
setcookie( 'PHPSESSID', '', 1, '/' );
setcookie( 'CAKEPHP', '', 1, '/' );
Seems super hacky -- sorry for that. Hope it helps though!

Zend_Auth and dynamically changing user details on the UI

When my users are logged in I display their details (name, email) on the UI. When they update their profile, I would like to show the updated details, without requiring the user to log out and back in.
The UI details are retrieved from Zend_Auth via a view helper. Zend_Auth is storing the 'identity' details in a session.
How should I go about updating the details in the session?:
I was considering retrieving the user's login credentials from the database and using them to call Zend_Auth->authenticate() again. The problem is that I don't know the password, only it's md5 hash. I could consider a new method, reauthenticate(), which configured the adapter to bypass the md5 and salt, but this sounds laborious.
I was considering writing directly to the Zend_Auth session namespace, but this sounds like a recipe for trouble?
Have you come across a similar problem? How did you handle it?
Your ideas are much appreciated!
You can update Zend_auth identity for the currently logged user. Very simplified action that updates only username could be as follows:
public function editAction() {
// check if user is logged, etc, and then
// show the edit user form and process the data after submission.
$userForm = new My_Form_EditUser();
if ($this->getRequest()->isPost()) {
if ($userForm->isValid($_POST)) {
// process the submitted data,
// and when you are sure that everything went ok,
// update the zend_auth identity
$authData = Zend_Auth::getInstance()->getIdentity();
// this line would depend on the format of your
// identity data and a structure of your
// actual form.
$authData->property->nickname = $formData['user']['nickname'];
$this->_helper->FlashMessenger('Your data was changed');
return $this->_redirect('/');
}
}
$this->view->form = $userForm;
}
Hope this helps.
What I really want is a method on Zend_Auth::setIdentity($user).
But in the absence of such a method, I have used a hack in which I have create an auth adapter that always returns success and sets the identity to the same user object I would have created in a "real" auth adapter. Then I just call Zend_Auth::authenticate($adapter) with that adapter and it sets the identity internally.
Now, looking mosre closely at the internals of Zend_Auth::authenticate(), I see that what we could do is just:
Zend_Auth::getInstance()->getStorage()->write($user);
Here's how I solved the problem for the time being. Not sure yet if it's the best solution:
create a wrapper for Zend_Auth
include a getAuthAdapter($raw) method
configure the adapter differently, depending on the value of $raw
if (false === $raw) {
$this->_authAdapter->setCredentialTreatment('SHA1(CONCAT(?,salt))');
} else {
$this->_authAdapter->setCredentialTreatment();
}

Separate frontend and backend users with sfDoctrineGuardPlugin

i'm starting a project adn i'm using symfony, my first time with symfony, really great actually, i already install the sfDoctrineGuardPlugin and everything is ok untill now, why?, because frontend users can login in the backend and vice versa, i dont't want that, so, i start to google, i found Symfony sfDoctrineGuardPlugin custom login query here in SO, but i don't know where i should place the function so, i haven't tested it.
As i don't want frontend users can login in the backend, i think i can use credentials, can i?? but, symfony check for users credentials after they are logged, and i don't want tha neither, so, how can i achieve this?, maybe if i could have namespaces in the session, i can check if an admin in the backend namespace and also for frontend users, so they never get fixed, i think.
I don't know really know if sfDoctrineGuardPlugin have some configuration that can manage this situation, exist such a config??
Also, in my backend, i will like to have a page to manage the frontend users, and other for backend users, because frontend users will have a profile and addresses, think this is much easier, but i don't know where to start.
need some help over here
thanks
After a few days coding, i was able to do it exactly as i wanted, i'm going to share my solution:
I started with an example i found here in SO, you can read the post here:
Symfony sfDoctrineGuardPlugin custom login query
it gave me an idea and i executed it, so, i create \lib\Util.class.php, with to functions, one for query backend users and another for frontend users
static public function retrieveCustomer($username, $isActive = true)
{
$query = Doctrine_Core::getTable('sfGuardUser')->createQuery('u')
->leftJoin('u.Groups g')
->leftJoin('g.Permissions p')
->where('u.username = ?', $username)
->addWhere('u.is_active = ?', $isActive)
->addWhere('g.name = ?', 'customers');
return $query->fetchOne();
}
static public function retrieveAdmin($username, $isActive = true)
{
$query = Doctrine_Core::getTable('sfGuardUser')->createQuery('u')
->leftJoin('u.Groups g')
->leftJoin('g.Permissions p')
->where('u.username = ?', $username)
->addWhere('u.is_active = ?', $isActive)
->whereIn('g.name', array('administrators','operators'));
return $query->fetchOne();
}
Now, in the app.yml of each app, i override the default query of the plugin
#Example for apps/backend/config/app.yml
all:
sf_guard_plugin:
retrieve_by_username_callable: Util::retrieveAdmin
untill now all was good, but i started to face another problem, so i open a new thread:
Overwriting isAuthenticated() in symfony and there i got the final step for my solution, that was setting differents session name for each app, so, in the factories.yml of each app:
#apps\backend\config\factories.yml
storage:
class: sfSessionStorage
param:
session_name: backend
and now all is set, frontend users can not log in in backend app and vice versa.
feel free to comment
The most common approach is through credentials, my backend applications security.yml looks like:
all:
is_secure: on
credentials: [login_backend]

Categories