I'm implementing rbac using yii2. But when i try to get the roles that i previously created i get an empty variable : $authorRole = $auth->getRole('admin');
The rule class, where i put the actual rule logic.
yii/console/controller/UserGroupRule.php
namespace app\rbac;
use Yii;
use yii\rbac\Rule;
/**
* Checks if user group matches
*/
class UserGroupRule extends Rule
{
public $name = 'userGroup';
public function execute($user, $item, $params)
{
if (!Yii::$app->user->isGuest) {
$group = Yii::$app->user->identity->group;
if ($item->name === 'admin') {
return $group == 1;
} elseif ($item->name === 'author') {
return $group == 1 || $group == 2;
}
}
return false;
}
}
Now defining the roles..
yii/console/controller/RbacController.php
namespace console\controllers;
use Yii;
use yii\console\Controller;
class RbacController extends Controller
{
public function actionInit()
{
$auth = Yii::$app->authManager;
$rule = new \app\rbac\UserGroupRule;
$auth->add($rule);
$admin = $auth->createRole('admin');
$admin->ruleName = $rule->name;
$auth->add($admin);
}
}
After this i was able to run ./yii rbac/init to generate the rule files:
console/rbac/items.php
console/rbac/rules.php
This is mostly identical to the documentation
yii/commom/config/main.php
'authManager' => [
'class' => 'yii\rbac\PhpManager',
'defaultRoles' => ['admin', 'author'], // your define roles
],
But in
frontend\models\SignupForm::signup()
I get an empty result when i try to get the admin role :
public function signup()
{
if ($this->validate()) {
$user = new User();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
$user->save(false);
$auth = Yii::$app->authManager;
$authorRole = $auth->getRole('admin');
$auth->assign($authorRole, $user->getId());
return $user;
}
return null;
}
here is the value of $auth :
yii\rbac\PhpManager#1
(
[itemFile] => '/advanced/frontend/rbac/items.php'
[assignmentFile] => '/advanced/frontend/rbac/assignments.php'
[ruleFile] => '/advanced/frontend/rbac/rules.php'
[*:items] => []
[*:children] => []
[*:assignments] => []
[*:rules] => []
[defaultRoles] => [
0 => 'admin'
1 => 'author'
2 => 'admin'
3 => 'author'
]
[yii\base\Component:_events] => []
[yii\base\Component:_behaviors] => null
)
It's probably because you generate the rbac in "console/rbac/items.php and
console/rbac/rules.php" but your rbac PhpManager is looking this files in advanced/frontend
You could move this files or set the correct paths
'authManager' => [
'class' => 'yii\rbac\PhpManager',
'itemFile' => '#common/rbac/items.php',
'assignmentFile' => '#common/rbac/assignments.php',
'ruleFile' => '#common/rbac/rules.php',
'defaultRoles' => ['admin', 'author'], // your define roles
],
The "#common" is yii2 alias all available aliases listed here: http://www.yiiframework.com/wiki/667/yii-2-list-of-path-aliases-available-with-default-basic-and-advanced-app/
This should help, let me know if there will be still an issue
Related
The Files I'm Using :
<?php
namespace App\GraphQl\Query\User;
use App\GraphQl\Traits\UserTrait;
use App\Models\User;
use GraphQL\Type\Definition\ResolveInfo;
use Rebing\GraphQL\Support\Facades\GraphQL;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Query;
The GraphQl UserRolesQuery File :
use Closure;
class UserRolesQuery extends Query
{
use UserTrait;
protected $attributes = [
'name' => 'user',
];
public function type(): Type
{
return GraphQL::type('UserType');
}
public function args(): array
{
return [
'id' => [
'name' => 'id',
'type' => Type::int(),
// 'rules' => ['required'] validation
],
];
}
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, Closure $getSelectFields)
{
The Resolve Function Where I Expect To Return User Role Names
$user = User::find($args['id']);
$result = $user->getRoleNames();
return $result;
}
}
I Expect The** $user->getRoleNames(); To Return The User Roles Name .. But it always returns NULL**
I'm trying to have a verification process after registration (by a randomly generated verification code), but after I verify one code, it will not verify another one even though I am using the code that is stored in the database upon registration. For instance:
verify/c42557235936ed755d3305e2f7305aa3
...works fine, but when I try and use another code (like /verify/3bc056ff48fec352702652cfa4850ac4), it generates the default layout for the application and does nothing. I don't know what is causing it.
Here is the code I have for this:
VerifyController -
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
class VerifyController extends AbstractActionController
{
public $verify;
public function indexAction()
{
$code = $this->params()->fromRoute('code');
if ($this->getVerifyInstance()->authenticateCode($code) !== false) {
$this->flashMessenger()->addSuccessMessage("Verification Successful, you can now login.");
return $this->redirect()->toRoute('verify', array('action' => 'success'));
} else {
$this->flashMessenger()->addErrorMessage("Oops! Something went wrong while attempting to verify your account, please try again.");
return $this->redirect()->toRoute('verify', array('action' => 'failure'));
}
}
public function successAction()
{
}
public function failureAction()
{
}
public function getVerifyInstance()
{
if (!$this->verify) {
$sm = $this->getServiceLocator();
$this->verify = $sm->get('Application\Model\VerifyModel');
}
return $this->verify;
}
}
VerifyModel -
namespace Application\Model;
use Zend\Db\TableGateway\TableGateway;
use Zend\Db\Sql\Sql;
use Zend\Db\Sql\Insert;
use Zend\Db\Adapter\Adapter;
class VerifyModel
{
/**
* #var TableGateway
*/
protected $table_gateway;
/**
* #var mixed
*/
protected $code;
/**
* Constructor method for VerifyModel class
* #param TableGateway $gateway
*/
public function __construct(TableGateway $gateway)
{
// check if $gateway was passed an instance of TableGateway
// if so, assign $this->table_gateway the value of $gateway
// if not, make it null
$gateway instanceof TableGateway ? $this->table_gateway = $gateway : $this->table_gateway = null;
}
public function authenticateCode($code)
{
// authenticate the verification code in the url against the one in the pending_users table
$this->code = !empty($code) ? $code : null;
$select = $this->table_gateway->select(array('pending_code' => $this->code));
$row = $select->current();
if (!$row) {
throw new \RuntimeException(sprintf('Invalid registration code %s', $this->code));
} else {
// verification code was found
// proceed to remove the user from the pending_users table
// and insert into the members table
$data = array(
'username' => $row['username'],
'password' => $row['password'],
);
$sql = new Sql($this->table_gateway->getAdapter());
$adapter = $this->table_gateway->getAdapter();
$insert = new Insert('members');
$insert->columns(array(
'username',
'password'
))->values(array(
'username' => $data['username'],
'password' => $data['password'],
));
$execute = $adapter->query(
$sql->buildSqlString($insert),
Adapter::QUERY_MODE_EXECUTE
);
if (count($execute) > 0) {
// remove the entry now
$delete = $this->table_gateway->delete(array('pending_code' => $this->code));
if ($delete > 0) {
return true;
}
}
}
}
}
the route:
'verify' => array(
'type' => 'Segment',
'options' => array(
'route' => 'verify/:code',
'constraints' => array(
'code' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Application\Controller\Verify',
'action' => 'index',
),
),
),
and the layout configurer in Module.php:
public function init(ModuleManager $manager)
{
$events = $manager->getEventManager();
$shared_events = $events->getSharedManager();
$shared_events->attach(__NAMESPACE__, 'dispatch', function ($e) {
$controller = $e->getTarget();
if (get_class($controller) == 'Application\Controller\SetupController') {
$controller->layout('layout/setup');
} else if (get_class($controller) == 'Application\Controller\MemberLoginController' || get_class($controller) == 'Application\Controller\AdminLoginController') {
$controller->layout('layout/login');
} else if (get_class($controller) == 'Application\Controller\RegisterController') {
$controller->layout('layout/register');
} else if (get_class($controller) == 'Application\Controller\VerifyController') {
$controller->layout('layout/verify');
}
}, 100);
}
Your route is defined
'options' => array(
'route' => 'verify/:code',
'constraints' => array(
'code' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
So, it should start with a letter (upper or lower case), and be followed by any (even none) number of characters (letters, numbers, underscores, and dashes).
So, valid routes:
verify/c42557235936ed755d3305e2f7305aa3 (the one you where trying)
verify/abcde
verify/N123-123
verify/Z
verify/X-1
etc.
Any of those should work. But the other code you provide in your question:
/verify/3bc056ff48fec352702652cfa4850ac4
starts with a number, so it wont be caught by your router. You need to either change how you generate your codes so they match your route, or change your route so it matches your codes. E.g.:
'options' => array(
'route' => 'verify/:code',
'constraints' => array(
'code' => '[a-zA-Z0-9][a-zA-Z0-9_-]{28,32}',
),
I'm using Dingo API to create an API in Laravel 5.2 and have a controller returning data with
return $this->response->paginator($rows, new SymptomTransformer, ['user_id' => $user_id]);
However, I don't know how to retrieve user_id value in the SymptomTransformer! Tried many different ways and tried looking into the class but I'm relatively new to both Laravel and OOP so if anyone can point me to the right direction, it'd be greatly appreciated.
Below is my transformer class.
class SymptomTransformer extends TransformerAbstract
{
public function transform(Symptom $row)
{
// need to get user_id here
return [
'id' => $row->id,
'name' => $row->name,
'next_type' => $next,
'allow' => $allow
];
}
}
You can pass extra parameter to transformer constructor.
class SymptomTransformer extends TransformerAbstract
{
protected $extra;
public function __construct($extra) {
$this->extra = $exta;
}
public function transform(Symptom $row)
{
// need to get user_id here
dd($this->extra);
return [
'id' => $row->id,
'name' => $row->name,
'next_type' => $next,
'allow' => $allow
];
}
}
And call like
return $this->response->paginator($rows, new SymptomTransformer(['user_id' => $user_id]));
You can set extra param via setter.
class SymptomTransformer extends TransformerAbstract
{
public function transform(Symptom $row)
{
// need to get user_id here
dd($this->test_param);
return [
'id' => $row->id,
'name' => $row->name,
'next_type' => $next,
'allow' => $allow
];
}
public function setTestParam($test_param)
{
$this->test_param = $test_param;
}
}
And then:
$symptomTransformer = new SymptomTransformer;
$symptomTransformer->setTestParam('something');
return $this->response->paginator($rows, $symptomTransformer);
If you are using Dependency Injection, then you need to pass params afterwards.
This is my strategy:
<?php
namespace App\Traits;
trait TransformerParams {
private $params;
public function addParam() {
$args = func_get_args();
if(is_array($args[0]))
{
$this->params = $args[0];
} else {
$this->params[$args[0]] = $args[1];
}
}
}
Then you implement the trait in your transformer:
<?php
namespace App\Transformers;
use App\Traits\TransformerParams;
use App\User;
use League\Fractal\TransformerAbstract;
class UserTransformer extends TransformerAbstract
{
use TransformerParams;
public function transform(User $user)
{
return array_merge([
'id' => (int) $user->id,
'username' => $user->username,
'email' => $user->email,
'role' => $user->roles[0],
'image' => $user->image
], $this->params); // in real world, you'd not be using array_merge
}
}
So, in your Controller, just do this:
public function index(Request $request, UserTransformer $transformer)
{
$transformer->addParam('has_extra_param', ':D');
// ... rest of the code
}
Basically, the trait is a bag for extra params.
I am new to laravel framework any help would appreciate
When i try to execute the below code i get this error
FatalErrorException in SocialController.php line 27: Class 'App\Http\Controllers\Hybrid_Auth' not found in SocialController.php line 27
when i remove the namespace from SocialController.php i get this error saying BaseController not found.
onclick this button
<i class="fa fa-facebook"></i> Facebook
SocialController.php
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
class SocialController extends BaseController
{
//this is the code for facebook Login
public function getFacebookLogin($auth=NULL)
{
if ($auth == 'auth')
{
try
{
Hybrid_Endpoint::process();
}
catch (Exception $e)
{
return Redirect::to('fbauth');
}
return;
}
$oauth = new Hybrid_Auth(app_path(). '/config/fb_auth.php');
$provider = $oauth->authenticate('Facebook');
$profile = $provider->getUserProfile();
return var_dump($profile).'Log Out';
}
public function getLoggedOut()
{
$fauth = new Hybrid_auth(app_path().'/config/fb_auth.php');
$fauth->logoutAllProviders();
return view::make('/');
}
}
fb_auth.php
<?php
return array(
"base_url" => "http://urmk.com/fbauth/auth",
"providers" => array (
"Facebook" => array (
"enabled" => true,
"keys" => array ( "id" => "APP_ID", "secret" => "APP_SECRET" ),
"scope" => "email"
)
)
);
Routes.php
Route::get('fbauth/{auth?}' ,array('as'=>'facebook', 'uses'=>'SocialController#getFacebookLogin'));
Route::get('logout',array('as'=>'logout','uses'=>'SocialController#getLoggedOut'));
You will need to add the namespace to your Hybrid Auth class. At the moment, when you are trying to instantiate the Hybrid_Auth object, it's not finding the class definition.
Here is my setup for Laravel:
app/Providers/AppServiceProvider.php
public function register()
{
$this->app->bind('Hybrid_Auth', function($app) {
return new \Hybrid_Auth(config_path('hybridauth.php'));
});
}
config/hybridauth.php
<?php
return [
'base_url' => env('APP_URL').'/auth/endpoint',
'providers' => [
'Facebook' => [
'enabled' => true,
'display' => 'popup',
'keys' => [
'id' => 'xxxx',
'secret' => 'xxx'
],
'scope' => 'email'
],
]
];
app/Http/routes.php
Route::group(['prefix' => 'auth'], function()
{
Route::get('login', 'AuthenticateController#login');
Route::get('endpoint', 'AuthenticateController#endpoint');
Route::get('logout', 'AuthenticateController#logout');
});
app/Http/Controllers/AuthenticateController.php
public function login(\Hybrid_Auth $auth)
{
$provider = $auth->authenticate('facebook');
$profile = $provider->getUserProfile();
$user = User::where('facebook', '=', $profile->identifier);
if($user->first()) {
return response()->json(['token' => $this->signin($user->first())]);
} else {
$user = new User;
$user->facebook = $profile->identifier;
$user->save();
return response()->json(['token' => $this->signin($user)]);
}
}
public function endpoint() {
\Hybrid_Endpoint::process();
}
public function logout(\Hybrid_Auth $auth) {
$auth->logoutAllProviders();
}
I am using "zizaco/confide": "~4.0#dev" and "zizaco/entrust": "1.2.*#dev".
I have set everything up as described in the two tutorials(confide migrations). Furthermore, I have created the following models:
User:
<?php
use Zizaco\Confide\ConfideUser;
use Zizaco\Confide\Confide;
use Zizaco\Confide\ConfideEloquentRepository;
use Zizaco\Entrust\HasRole;
use Carbon\Carbon;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface{
use ConfideUser;
use HasRole;
/**
* Get user by username
* #param $username
* #return mixed
*/
public function getUserByUsername( $username )
{
return $this->where('username', '=', $username)->first();
}
public function joined()
{
return String::date(Carbon::createFromFormat('Y-n-j G:i:s', $this->created_at));
}
public function saveRoles($inputRoles)
{
if(! empty($inputRoles)) {
$this->roles()->sync($inputRoles);
} else {
$this->roles()->detach();
}
}
public function currentRoleIds()
{
$roles = $this->roles;
$roleIds = false;
if( !empty( $roles ) ) {
$roleIds = array();
foreach( $roles as &$role )
{
$roleIds[] = $role->id;
}
}
return $roleIds;
}
public static function checkAuthAndRedirect($redirect, $ifValid=false)
{
// Get the user information
$user = Auth::user();
$redirectTo = false;
if(empty($user->id) && ! $ifValid) // Not logged in redirect, set session.
{
Session::put('loginRedirect', $redirect);
$redirectTo = Redirect::to('user/login')
->with( 'notice', Lang::get('user/user.login_first') );
}
elseif(!empty($user->id) && $ifValid) // Valid user, we want to redirect.
{
$redirectTo = Redirect::to($redirect);
}
return array($user, $redirectTo);
}
public function currentUser()
{
return (new Confide(new ConfideEloquentRepository()))->user();
}
public function getReminderEmail()
{
return $this->email;
}
}
Role:
<?php
use Zizaco\Entrust\EntrustRole;
class Role extends EntrustRole {
public function validateRoles( array $roles )
{
$user = Confide::user();
$roleValidation = new stdClass();
foreach( $roles as $role )
{
// Make sure theres a valid user, then check role.
$roleValidation->$role = ( empty($user) ? false : $user->hasRole($role) );
}
return $roleValidation;
}
}
Permission:
<?php
use Zizaco\Entrust\EntrustPermission;
class Permission extends EntrustPermission
{
public function preparePermissionsForDisplay($permissions)
{
// Get all the available permissions
$availablePermissions = $this->all()->toArray();
foreach($permissions as &$permission) {
array_walk($availablePermissions, function(&$value) use(&$permission){
if($permission->name == $value['name']) {
$value['checked'] = true;
}
});
}
return $availablePermissions;
}
/**
* Convert from input array to savable array.
* #param $permissions
* #return array
*/
public function preparePermissionsForSave( $permissions )
{
$availablePermissions = $this->all()->toArray();
$preparedPermissions = array();
foreach( $permissions as $permission => $value )
{
// If checkbox is selected
if( $value == '1' )
{
// If permission exists
array_walk($availablePermissions, function(&$value) use($permission, &$preparedPermissions){
if($permission == (int)$value['id']) {
$preparedPermissions[] = $permission;
}
});
}
}
return $preparedPermissions;
}
}
Furthermore, I would like to seed my database in the beginning with values, therefore I created several seeders for user, role and permission. However, I get an error in my permission seeder:
UserTableSeeder:
<?php
class UsersTableSeeder extends Seeder {
public function run()
{
DB::table('users')->delete();
$users = array(
array(
'username' => 'admin',
'email' => 'admin#example.org',
'password' => Hash::make('admin'),
'confirmed' => 1,
'confirmation_code' => md5(microtime().Config::get('app.key')),
'created_at' => new DateTime,
'updated_at' => new DateTime,
),
array(
'username' => 'moderator',
'email' => 'moderator#example.org',
'password' => Hash::make('moderator'),
'confirmed' => 1,
'confirmation_code' => md5(microtime().Config::get('app.key')),
'created_at' => new DateTime,
'updated_at' => new DateTime,
),
array(
'username' => 'user',
'email' => 'user#example.org',
'password' => Hash::make('user'),
'confirmed' => 1,
'confirmation_code' => md5(microtime().Config::get('app.key')),
'created_at' => new DateTime,
'updated_at' => new DateTime,
)
);
DB::table('users')->insert( $users );
}
}
RolesTableSeeder:
<?php
class RolesTableSeeder extends Seeder {
public function run()
{
DB::table('roles')->delete();
$adminRole = new Role;
$adminRole->name = 'adminRole';
$adminRole->save();
$standRole = new Role;
$standRole->name = 'userRole';
$standRole->save();
$modRole = new Role;
$modRole->name = 'modRole';
$modRole->save();
$user = User::where('username','=','admin')->first();
$user->attachRole( $adminRole );
$user = User::where('username','=','user')->first();
$user->attachRole( $standRole );
$user = User::where('username','=','moderator')->first();
$user->attachRole( $modRole );
}
}
PermissionsTableSeeder:
<?php
class PermissionsTableSeeder extends Seeder {
public function run()
{
DB::table('permissions')->delete();
$permissions = array(
array( // 1
'name' => 'manage_users',
'display_name' => 'manage users'
),
array( // 2
'name' => 'manage_roles',
'display_name' => 'manage roles'
),
array( // 3
'name' => 'standart_user_role',
'display_name' => 'standart_user_role'
),
);
DB::table('permissions')->insert( $permissions );
DB::table('permission_role')->delete();
$role_id_admin = Role::where('name', '=', 'admin')->first()->id;
$role_id_mod = Role::where('name', '=', 'moderator')->first()->id;
$role_id_stand = Role::where('name', '=', 'user')->first()->id;
$permission_base = (int)DB::table('permissions')->first()->id - 1;
$permissions = array(
array(
'role_id' => $role_id_admin,
'permission_id' => $permission_base + 1
),
array(
'role_id' => $role_id_admin,
'permission_id' => $permission_base + 2
),
array(
'role_id' => $role_id_mod,
'permission_id' => $permission_base + 1
),
array(
'role_id' => $role_id_mod,
'permission_id' => $permission_base + 3
),
array(
'role_id' => $role_id_stand,
'permission_id' => $permission_base + 3
),
);
DB::table('permission_role')->insert( $permissions );
}
}
This is the error I get when running db:seed:
$ php artisan db:seed
**************************************
* Application In Production! *
**************************************
Do you really wish to run this command? Y
Seeded: UsersTableSeeder
Seeded: RolesTableSeeder
[ErrorException]
Trying to get property of non-object
db:seed [--class[="..."]] [--database[="..."]] [--force]
Any recommendations what I am doing wrong in my seeding?
I appreciate your answers!
I think the problem is with:
$role_id_admin = Role::where('name', '=', 'admin')->first()->id;
$role_id_mod = Role::where('name', '=', 'moderator')->first()->id;
$role_id_stand = Role::where('name', '=', 'user')->first()->id;
You want to get id but such records don't exists so you get the error. There are probably no records with admin, moderator or user name because looking at RolesTableSeeder you create roles this way:
$adminRole = new Role;
$adminRole->name = 'adminRole';
$adminRole->save();
$standRole = new Role;
$standRole->name = 'userRole';
$standRole->save();
$modRole = new Role;
$modRole->name = 'modRole';
$modRole->save();
with names adminRole, userRole, modRole. So either change the names inside RolesTableSeeder or change them in PermissionsTableSeeder