Laravel 4 Auth with Facebook (no password authentication) - facebook

I'm trying to set up an authentication system with Laravel 4 with a Facebook login. I am using the madewithlove/laravel-oauth2 package for Laravel 4.
Of course, there is no password to add to my database upon a user loggin in with Facebook. I am, however, trying to check to see if a user id is in the database already to determine if I should create a new entity, or just log in the current one. I would like to use the Auth commands to do this. I have a table called "fans".
This is what I'm working with:
$fan = Fan::where('fbid', '=', $user['uid']);
if(is_null($fan)) {
$fan = new Fan;
$fan->fbid = $user['uid'];
$fan->email = $user['email'];
$fan->first_name = $user['first_name'];
$fan->last_name = $user['last_name'];
$fan->gender = $user['gender'];
$fan->birthday = $user['birthday'];
$fan->age = $age;
$fan->city = $city;
$fan->state = $state;
$fan->image = $user['image'];
$fan->save();
return Redirect::to('fans/home');
}
else {
Auth::login($fan);
return Redirect::to('fans/home');
}
Fan Model:
<?php
class Fan extends Eloquent {
protected $guarded = array();
public static $rules = array();
}
When I run this, I get the error:
Argument 1 passed to Illuminate\Auth\Guard::login() must be an instance of Illuminate\Auth\UserInterface, instance of Illuminate\Database\Eloquent\Builder given
EDIT: When I use: $fan = Fan::where('fbid', '=', $user['uid'])->first();
I get the error:
Argument 1 passed to Illuminate\Auth\Guard::login() must be an instance of Illuminate\Auth\UserInterface, null given, called in /Applications/MAMP/htdocs/crowdsets/laravel-master/vendor/laravel/framework/src/Illuminate/Auth/Guard.php on line 368 and defined
I do not know why it is giving me this error. Do you have suggestions on how I can make this work? Thank you for your help.

You have to implement UserInterface to your model for Auth to work properly
use Illuminate\Auth\UserInterface;
class Fan extends Eloquent implements UserInterface{
...
public function getAuthIdentifier()
{
return $this->getKey();
}
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->password;
}
}
getAuthIdentifier and getAuthPassword are abstract method and must be implemented in you class implementing UserInterface

To login any user into the system, you need to use the User model, and I bet inherited classes will do the trick as well but I'm not sure.
Anyway, your Fan model does not associate with the User model/table in any way and that's a problem. If your model had a belong_to or has_one relationship and a user_id field then you could replace Auth::login($user) with Auth::loginUsingId(<some id>).
Original answer:
You are missing an extra method call: ->get() or ->first() to actually retrieve the results:
$fan = Fan::where('fbid', '=', $user['uid'])->first();
Alternatively, you can throw an exception to see what's going on:
$fan = Fan::where('fbid', '=', $user['uid'])->firstOrFail();
If you see different errors, update your question with those errors.

Related

filter records in popup list view if assigned user is login SUITECRM

I want to filter records so that the assigned user can only see the records that are assigned to him from the popup list view.
The reason why I'm not doing this in the roles management is because if I assigned a user to a client record then other users that have the same role wouldn't able to see it so I've set the role->list tab to "all" and added custom code in list view that only the login user can see their own records.
Here's what I've done.
<?php
require_once('include/MVC/View/views/view.popup.php');
class AccountsViewPopup extends ViewPopup
{
public function display()
{
parent::display(); // TODO: Change the autogenerated stub
require_once 'modules/ACLRoles/ACLRole.php';
$ACLRole = new ACLRole();
$roles = $ACLRole->getUserRoles($GLOBALS['current_user']->id);
if (in_array('User1', $roles)) {
global $db, $current_user;
$this->where .= " AND accounts.assigned_user_id = '$current_user->id' AND deleted=0 ";
}
}
}
But i get this error:
Undefined property: AccountsViewPopup::$where
For list view only: custom/modules/MODULE_NAME/views/view.list.php
and following is the helping code:
require_once('include/MVC/View/views/view.list.php');
class MODULE_NAMEViewList extends ViewList {
function listViewProcess() {
global $current_user;
$this->params['custom_where'] = ' AND module_name.name = "test" ';
parent::listViewProcess();
}
}
For list and popup view(both):
You need to change the logic inside create_new_list_query function which actually prepares a query. Some modules have override it a bean level(e.g. see modules/Leads/Lead.php).
If you want to override it in upgrade safe manner then create a file in custom directory e.g: custom/modules/Leads/Lead.php, then extend it from the core bean class like following:
<?php
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
require_once('modules/Leads/Lead.php');
class CustomLead extends Lead {
function create_new_list_query($order_by, $where,$filter=array(),$params=array(), $show_deleted = 0,$join_type='', $return_array = false,$parentbean=null, $singleSelect = false, $ifListForExport = false)
{
// Code from create_new_list_query in and then modify it accordingly.
}
}
Register new bean class in this location: custom/Extension/application/Ext/Include/custom_leads_class.php and registration code will look like following:
<?php
$objectList['Leads'] = 'Lead';
$beanList['Leads'] = 'CustomLead';
$beanFiles['CustomLead'] = 'custom/modules/Leads/Lead.php';
?>
I know this has been answered, but decided to post my solution anyway. I had almost the same problem some time ago (7.10.7).
PopupView has method getCustomWhereClause() which you can implement in your custom view.
It has to return containing string with the conditions.
Example:
custom/modules/Meetings/views/view.popup.php
/*class declaration and other stuff*/
protected function getCustomWhereClause()
{
global $current_user;
return " ( {$this->bean->table_name}.assigned_user_id='{$current_user->id}') ";
}
Remember to leave at least one space at the start and the end because SuiteCRM actually forgets to add it and it may result in broken query (but it's fairly easy to find in logs).

Zend duplicated rows on mysql insert

For some reason, when I do an mysql db insert from Zend, my row is dulpicated. I've tried a direct insert via phpmyadmin and it works perfect, so its not a mysql server problem.
This is the code I use:
<?php
class Model_Team extends Zend_Db_Table_Abstract {
protected $_name = 'team';
public function createUser($data) {
$user = $this->createRow();
$user->name = $data['name'];
$user->title = $data['title'];
$id = $user->save();
return $id;
}
}
?>
Thanks in advance.
EDIT:
I've found that this duplication only occurs when i call the form via AJAX (modal box), although the form post is normal, not an ajax request)
I don't know why your code is double pumping the database on save but it should'nt matter as you're using the Row object and save(). (save() inserts or updates)
You may want to restructure your createUser() function so that it can't create a new row if the row already exists.
<?php
class Model_Team extends Zend_Db_Table_Abstract {
protected $_name = 'team';
public function createUser(array $data) {
$user = $this->createRow();
//test if user has id in the array
if (array_key_exists('id', $data)){
$user->id = $data['id'];
}
$user->name = $data['name'];
$user->title = $data['title'];
$user->save();
//no need to create a new variable to return the user row
return $user;
}
}
This method will create and update a user row.
To help you further I'll need to see the controller code most of my double pumps have happened there.
Instead of using createRow() have you tried using insert()?
/**
* Insert array of data as new row into database
* #param array $data associative array of column => value pairs.
* #return int Primary Key of inserted row
*/
public function createUser($data)
{
return $this->insert($data);
}
Also - could we see the ajax code? It may be that the form is being posted as well?

Can (and should?) Zend_Auth return class as the Identity?

I have a class R00_Model_User, which, curiously enough, represents user as he is. Can $result->getIdentity() return me an object of this class? (Or maybe it's stupid?)
(There is a factory method in R00_Model_User which prevents from duplicating objects. I'd like Zend_Auth to use it instead of creating a new object, if it can)
Two options:
write your own authentication adapter subclassing the out-of-the-box-adapter that matches your scenario best
class R00_Auth_Adapter extends Zend_Auth_Adapter_*
{
/**
* authenticate() - defined by Zend_Auth_Adapter_Interface. This method is called to
* attempt an authentication. Previous to this call, this adapter would have already
* been configured with all necessary information to successfully connect to a database
* table and attempt to find a record matching the provided identity.
*
* #throws Zend_Auth_Adapter_Exception if answering the authentication query is impossible
* #return Zend_Auth_Result
*/
public function authenticate()
{
$result = parent::authenticate();
if ($result->isValid() {
return new Zend_Auth_Result(
$result->getCode(),
R00_Model_User::load($result->getIdentity()),
$result->getMessages()
);
} else {
return $result;
}
}
}
This will allow you to code
$adapter = new R00_Auth_Adapter();
//... adapter initialisation (username, password, etc.)
$result = Zend_Auth::getInstance()->authenticate($adapter);
and on successfull authentication your user-object is automatically stored in the authentication storage (session by default).
or use your login-action to update the stored user identity
$adapter = new Zend_Auth_Adapter_*();
$result = $adapter->authenticate();
if ($result->isValid()) {
$user = R00_Model_User::load($result->getIdentity());
Zend_Auth::getInstance()->getStorage()->write($user);
}
In one of my applications, I have getIdentity() return a user object, and it works pretty well for me. To use your factory method, do like this:
$auth = Zend_Auth::getInstance();
$user = R00_Model_User::getInstance(...);
$auth->getStorage()->write($user);
Then when you call getIdentity(), you will have your user object.

How does Zend_Auth storage work?

This is very simple. I write
$auth->getStorage()->write($user);
And then I want, in a separate process to load this $user, but I can't because
$user = $auth->getIdentity();
is empty. Didn't I just... SET it? Why does it not work? Halp?
[EDIT 2011-04-13]
This has been asked almost two years ago. Fact is, though, that I repeated the question in July 2010 and got a fantastic answer that I back then simply did not understand.
Link: Zend_Auth fails to write to storage
I have since built a very nice litte class that I use (sometimes with extra tweaking) in all my projects using the same storage engine as Zend_Auth but circumventing all the bad.
<?php
class Qapacity_Helpers_Storage {
public function save($name = 'default', $data) {
$session = new Zend_Session_Namespace($name);
$session->data = $data;
return true;
}
public function load($name = 'default', $part = null) {
$session = new Zend_Session_Namespace($name);
if (!isset($session->data))
return null;
$data = $session->data;
if ($part && isset($data[$part]))
return $data[$part];
return $data;
}
public function clear($name = 'default') {
$session = new Zend_Session_Namespace($name);
if (isset($session->data))
unset($session->data);
return true;
}
}
?>
It's supposed to work.
Here's the implementation of the Auth getIdentity function.
/**
* Returns the identity from storage or null if no identity is available
*
* #return mixed|null
*/
public function getIdentity()
{
$storage = $this->getStorage();
if ($storage->isEmpty()) {
return null;
}
return $storage->read();
}
Here's the implementation of the PHP Session Storage write and read functions:
/**
* Defined by Zend_Auth_Storage_Interface
*
* #return mixed
*/
public function read()
{
return $this->_session->{$this->_member};
}
/**
* Defined by Zend_Auth_Storage_Interface
*
* #param mixed $contents
* #return void
*/
public function write($contents)
{
$this->_session->{$this->_member} = $contents;
}
Are you sure you are loading the same instance of the Zend_Auth class?
Are you using
$auth = Zend_Auth::getInstance();
Maybe you are calling the write method after the getIdentity method?
Anyway, as I said before, what you are doing should work.
So on a page reload you can fetch the session, while not if redirecting? Are you redirecting on a different Domain-Name? Then it might be an issues with the Cookies and you'd need to manually set session.cookie_domain ini variable.
Check if the cookie named PHPSESSID has been properly been set and if it's being sent to the server on every page request? Is it constant or does it change on every request?
Also, you might want to check if the session data is being properly saved to the disk. The sessions can be found in the directory defined by the ini variable session.save_path. Is the file corresponding to your PHPSESSID there and does it contain a meaningful entry? In my case it contains
root#ip-10-226-50-144:~# less /var/lib/php5/sess_081fee38856c59a563cc320899f6021f
foo_auth|a:1:{s:7:"storage";a:1:{s:9:"user_id";s:2:"77";}}
Add:
register_shutdown_function('session_write_close');
to index.php before:
$application->bootstrap()->run();

Zend Framework Authentication and Redirection

What is the best method in Zend Framework to provide restricted areas and redirect users to a login page? What I want to do is set a flag on my controllers for restricted pages:
class AdminController extends Zend_Controller_Action
{
protected $_isRestricted = true;
....
and have a plugin check to see if the controller is restricted and if the user has authenticated, otherwise redirect them to the login page. If I do this directly in the controller's preDispatch I can use $this->_redirect(), but looking at Action Helpers they won't have access to that. It's also a lot of duplicate code to copy/paste the authentication check code in every controller that needs it.
Do I need an Action Controller linked to preDispatch, or a Front Controller plugin? How would I do the redirect and still preserve things like the base URL?
Use Zend_Acl (best combined with Zend_Auth)
See also Practical Zend_ACL + Zend_Auth implementation and best practices
For one project, I've extended Zend_Controller_Action, and in that class's preDispatch put a check for logged-in-ness. I can override it on a per-action basis with an init() that checks the actionname and turns off the requirement (or preDispatch() that calls it's parent for the actual checks).
In a project I was working on, I had trouble with various users experiencing timeouts from their browsers. This meant the Zend_Auth no longer existed in the registry and users lost access to required pages/functions.
In order to stop this from occuring, I setup a Plugin (as you suggest) and have this plugin perform checks in the preDispatch(). An example is below:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
public function run()
{
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new App_Controller_Plugin_Timeout());
parent::run();
}
}
with the timeout class implementing any Zend_Auth or Zend_Acl requirements, using a check via the function below.
class App_Controller_Plugin_Timeout extends Zend_Controller_Plugin_Abstract
{
/**
* Validate that the user session has not timed out.
* #param Zend_Controller_Request_Abstract $request
* #return void
* #todo Validate the user has access to the requested page using Zend_Acl
*/
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$frontController = Zend_Controller_Front::getInstance();
$controllerName = $frontController->getRequest()->getControllerName();
$actionName = $frontController->getRequest()->getActionName();
$authInstance = Zend_Auth::getInstance();
/** If the controller is not the Auth or Error controller, then check for
* a valid authorized user and redirect to the login page if none found */
if (($controllerName !== 'auth') && ($controllerName !== 'index') && ($controllerName !== 'error')) {
if (!$authInstance->hasIdentity()) {
$this->_response->setRedirect('/index/timeout')->sendResponse();
exit;
}
} else if (($controllerName == 'index') || (($controllerName == 'auth') && ($actionName !== 'logout'))) {
/** If running the Auth or Index (default) controller (and not the logout
* action), check if user already signed in and redirect to the welcome page */
if ($authInstance->hasIdentity()) {
$this->_response->setRedirect('/general/welcome')->sendResponse();
exit;
}
}
}
}
....
/**
* Test that the input user belongs to a role based on the user input and
* the values loaded into the Acl registry object setup when the site first
* loads
*
* #param mixed|Zend_Auth $userData
* #param string $userRole
* #return boolean
* #throws Zend_Exception When invalid input is provided
*/
public function isUserMemberOfRole($userData, $userRole)
{
if (empty($userData)) {
$auth = Zend_Auth::getInstance();
if($auth->hasIdentity()) {
$userData = $auth->getIdentity();
} else {
return FALSE;
}
}
if (!is_string($userRole)){
throw new Zend_Exception('Invalid input provided to ' . __METHOD__);
}
// Setup the required variables and access the registry for the Acl values
$rolesTable = new App_Model_Internal_UsersToRoles();
$registry = Zend_Registry::getInstance();
$acl = $registry->get('acl');
$roles = $rolesTable->getUserRoles($userData); // returns an array of values
foreach ($roles as $value) {
if ($value['Name'] == $userRole) {
return $acl->isAllowed($value['Name'], null, $userRole);
}
}
}
I had the user access implemented in a database table and then initialized as an "_init" function at Bootstrap->run() as follows:
protected function _initAclObjectForUserRoles()
{
$userTable = new App_Model_Internal_Roles();
$acl = new Zend_Acl();
$userRoles = $userTable->fetchAll();
$roles = $userRoles->toArray();
// Cycle through each Role and set the allow status for each
foreach($roles as $value) {
$department = $value['Name'];
$acl->addRole(new Zend_Acl_Role($department));
$acl->allow($department, null, $department);
}
// Add the new Acl to the registry
$registry = Zend_Registry::getInstance();
$registry->set('acl', $acl);
}
So, using this method you could put access restrictions via the roles loaded via from a database into an Zend_Acl object, or you could load the controller class attribute via the Timeout plugin and check it's value. Although, I've found it's easier to maintain access policies in a database than spread them throughout your code base... :-)