Im new to Cartalyst Sentinel and this concept of ACL. I've managed to create a user, perform activation and login and logout.
I'd like to take my learning to the next level. I would like 2 types of Users on this laravel app. 1 is Administrator another is Subscriber. I'm assuming my account creation method should by default create the user a subscriber.
public function postCreate() {
/* Validation */
$validation = Validator::make(Input::all(), [
'email' => 'required|email|max:50|unique:users',
'username' => 'required|min:3|max:20|unique:users',
'password' => 'required|min:6',
'password_repeat' => 'required|same:password',
]);
if ($validation->fails()) {
return Redirect('login')->withErrors($validation)->withInput();
} else {
$credentials = Input::all();
$user = Sentinel::register($credentials);
$activation = Activation::create($user);
$activation_code = $activation->code;
if ($user) {
Mail::send('emails.auth.activate', ['link' => URL::route('account-activate', [$user->id, $activation_code]), 'username' => $user->username], function($message) use ($user) {
$message->to($user->email, $user->username)->subject('Activate your account');
});
return Redirect::route('home')->with('global', 'Thank you for registering! We have sent you an email to activate your account');
}
}
}
Do i alter the code like so
$user = Sentinel::register($credentials);
$user = Sentinel::findById(1);
$role = Sentinel::findRoleByName('Subscribers');
$role->users()->attach($user);
The thing is i have not even created any roles to begin with. Where do we write that functionality? Right now i have the following Controllers
AccountController - handles activation
AuthController - handles login/logout
RegistrationController - handles registration of user
RolesController - i've not written anything inside here yet. Im a bit lost.
Please guide me. Any help is greatly appreciated.
You do not need to do a search for your user if you already registered them, the register method returns the user.
You can do the following to attach a role to a user:
$user = Sentinel::register($credentials);
$role = Sentinel::findRoleByName('Subscribers');
$role->users()->attach($user);
// OR
$user->roles()->attach($role);
you have both a user and a role object and they have a many to many relation so it doesn't matter which one you use.
You will need to create a db seeder or a method to create your permissions. But to create your Subscribers Role you will need to do the following:
Sentinel::getRoleRepository()->createModel()->create([
'name' => 'Subscribers',
'slug' => 'subscribers',
'permissions' => [
'user.view' => true,
'user.delete' => false,
// any other permissions you want your Subscribers to have
]
]);
A similar call can build your Administrator roles as well.
Your Roles Model and Controller are already built for you, you just need to access them through Sentinel, which you already have Sentinel::findRoleByName('Subscribers'); call.
Cartalyst has some pretty decent documentation about setting up roles and permissions for your users:
https://cartalyst.com/manual/sentinel#roles
https://cartalyst.com/manual/sentinel#permissions
It's just a matter of figuring out what you want each role to do or not do.
Also, you can set specific permissions per user to override the role permissions.
Related
I tried to use spatie/laravel-permission (https://spatie.be/docs/laravel-permission/v5/installation-laravel) to set up permissions and Laravel Breeze to create a login functionality (https://laravel.com/docs/9.x/starter-kits)
This is a database seeder which creates 2 users and sets permissions/roles
public function run()
{
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
Permission::create(['name' => 'manage posts']);
// Create user with "premium" role
$user = User::create([
'name' => 'regular user',
'email' => 'user#domain.com',
'password' => Hash::make('123123'),
]);
$premium = Role::create(['name' => 'premium'])
->givePermissionTo(['manage posts']);
$user->assignRole($premium);
// Create super admin
$user = User::create([
'name' => 'superadmin user',
'email' => 'admin#domain.com',
'password' => Hash::make('123123'),
]);
$super_admin = Role::create(['name' => 'super-admin']);
$user->assignRole($super_admin);
}
This is how I'm testing it inside a controller, something seems off but I think I do it correctly (https://spatie.be/docs/laravel-permission/v5/basic-usage/role-permissions)
// Both of these is giving me false for some reason when I'm logged in for both users
$user = Auth::user();
// $user->assignRole('super-admin'); // this also doesn't change anything
var_dump('has role super-admin', $user->hasRole('super-admin'));
var_dump('can manage posts', $user->can('manage posts'));
// But both of these queries correctly fetches usernames which correspond to seeded data, so that part should be ok
$users = User::permission('manage posts')->get();
foreach ($users as $user) {
var_dump($user->name);
}
$users = User::role('super-admin')->get();
foreach ($users as $user) {
var_dump($user->name);
}
Routes also doesn't work, I get a message "User does not have the right roles" when I'm logged in as super-admin
Route::group(['middleware' => ['role:super-admin']], function () {
Route::resource('posts', \App\Http\Controllers\PostController::class)->middleware(['auth']);
});
Model for User
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
use HasRoles;
...
}
Laravel and Spatie package are latest version. What am I missing?
step by step
every time you run command check the table in database and be sure what the data inserted you got it ?
first we insert permission i prefer to write the premission in this way as example "read_tags"
in your example
Permission::create(['name' => 'manage_posts']);
then
create role
$role = Role::firstOrCreate(['name' => 'super-admin']);
and make sync permissions to role
$role->syncPermissions(Permission::all());
call the first user or whatever u create the user here
$user = User::first();
then give the user this role
$user->syncRoles($role);
try to make it as following
and don't forget to show the database and be sure the tables have the data
Im new in laravel and I'm watching a youtube playlist to build my 1st project....
now I'm trying to implement an inv only system
so the register form looks like
username:
inv code:
password:
I've already created a migration which has
user_id - this is user id of the user who created the invite
code - the code which will get validated at time of registration and then deleted
{timestamps}
so the issue im having is:
how do I verify that the invite entered by user exists in the table "inv_codes" and matches the column "code" and then delete it after registration is complete
here is a minimal reproducible example
lass RegisterController extends Controller
{
public function __construct()
{
$this->middleware(['guest']);
}
public function index()
{
return view('auth.register');
}
public function submit(Request $request)
{
$this->validate($request, [
'username' => 'required|max:6',
'password' => 'required',
]);
User::create([
'username' => $request->username,
'password' => Hash::make($request->password),
]);
auth()->attempt($request->only('username', 'password'));
return redirect()->route('dashboard');
}
}
Suppose that you have code column in both users and inv_codes tables. Now during registration, you can use validation. Something like this:
$request->validate([
'code' => 'required|exists:inv_codes,code',
// ... rest of registration fields
]);
Then you can delete that row in inv_codes table by something like this:
You can read more at: https://laravel.com/docs/8.x/validation#quick-writing-the-validation-logic
DB::table('inv_codes')->where('code', $request->code)->delete();
You can read more at: https://laravel.com/docs/8.x/queries#delete-statements
Ideally you would create a table to hold the invitations and an accompanying Eloquent model. On register, you can check if the invitation code the user entered is valid by using a couple of ways.
Manually
Invitation::where('code', request()->inv_code)->firstOrFail();
Validation
request()->validate([
'inv_code' => ['exists:inv_codes,code'],
]);
In either case, you need to fetch the invitation and then delete it after registering the user.
$invitation->delete();
I have a users, items, user_item tables. I need to populate the user_item table with a user_id and item_id when a user is created.
so far, I have a basic registration function
public function register(Request $request) {
$user = User::create([
'name' => $request->name,
'user_type' => $request->user_type,
'email' => $request->email,
'password' => bcrypt($request->password)
]);
$token = auth()->login($user);
return $this->respondWithToken($token);
}
So far it saves only to the users table ofcourse.
I've looked at some documentations on using attach(), however, I got stuck on this one..
In the register function, i added a $item array:
$item = Item::create([
'user_id' => !!!!, -> How do I get the id of the inserted user
'instrument_id' => $request->instrument_id
]);
$user->role()->attach($item)
Also, what is role()? is it a built-in laravel function?
Note that I haven't tried running this function since I got stuck on these problems. So I don't event know if it's gonna work.
Anyone help me on this one? I'm a laravel newbie and got really confused on the documentations.
the method create return the model it self after loading it's attributes from db,
so when you want the user id just use $user->id after create() method.
for the default permission that shipped with laravel it is
spatie/laravel-permission
and to assign role to a user you can use:
$user->assignRole('writer'); // just set role name
I ran the following test and I am receiving a failed_asserting that false is true. Can someone further explain why this could be?
/** #test */
public function a_user_logs_in()
{
$user = factory(App\User::class)->create(['email' => 'john#example.com', 'password' => bcrypt('testpass123')]);
$this->visit(route('login'));
$this->type($user->email, 'email');
$this->type($user->password, 'password');
$this->press('Login');
$this->assertTrue(Auth::check());
$this->seePageIs(route('dashboard'));
}
Your PHPUnit test is a client, not the web application itself. Therefore Auth::check() shouldn't return true. Instead, you could check that you are on the right page after pressing the button and that you see some kind of confirmation text:
/** #test */
public function a_user_can_log_in()
{
$user = factory(App\User::class)->create([
'email' => 'john#example.com',
'password' => bcrypt('testpass123')
]);
$this->visit(route('login'))
->type($user->email, 'email')
->type('testpass123', 'password')
->press('Login')
->see('Successfully logged in')
->onPage('/dashboard');
}
I believe this is how most developers would do it. Even if Auth::check() worked – it would only mean a session variable is created, you would still have to test that you are properly redirected to the right page, etc.
In your test you can use your Model to get the user, and you can use ->be($user) so that it will get Authenticate.
So i written in my test case for API test
$user = new User(['name' => 'peak']);
$this->be($user)
->get('/api/v1/getManufacturer')
->seeJson([
'status' => true,
]);
it works for me
i am using " romanbican - bicon roles ", i don't see sufficient information for the " Creating Roles ",
code is available but i don't know where i paste this code, please suggest quick steps to implement permissions.
I used this same laravel package and simply created a new controller and route pointing to the the following controller methods:
public function getRoleAdmin()
{
$adminRole = Role::create([
'name' => 'Admin',
'slug' => 'admin',
'description' => 'System Administrator', // optional
'level' => 1, // optional, set to 1 by default
]);
}
public function getRoleModerator()
{
$moderatorRole = Role::create([
'name' => 'Forum Moderator',
'slug' => 'forum.moderator',
'description' => 'Forum Moderator',
'level' => 1,
]);
}
I then created a simple view with a button for each calling the appropriate route/controller/method to create either a new moderator or administrator role. You will see that calling Role::create simply creates a new record in the roles table with these attributes which you could easily perform with a standard DB call to insert into the table. I used the same approach for creating/deleting permissions.