How to create an invitation system in Laravel PHP - laravel

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();

Related

Checking for user permissions with Spatie package fails in routes and in controller

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

Add the inserted id to the pivot table

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

Creating two relationships from the same controller method in laravel

I am trying to allow users to post pictures and comment on pictures. The pictures are related to the users through a one to many relationship and the comments are related to the pictures through a one to many relationship. I am now trying to simultaneously relate both users and pictures to comments whenever a comment is made. Currently, I am able to relate comments to either the picture or the user but not both.
Below is the controller method which handles comment uploads:
public function postComment(Request $request, $picture_id)
{
$this->validate($request, [
"comment" => ['required', 'max:1000'],
]);
$picture = Picture::find($picture_id);
$picture->status()->create([
'body' => $request->input('comment'),
]);
Auth::user()->statuses()->update([
'body' => $request->input('comment'),
]);
return redirect()->back();
}
I have tried creating one relationship and then creating the other relationship using update(). This did not work and resulted in the value remaining null.
Thank you for your help.
If i am understanding your database model correctly, when creating the status model for your picture all you need to do is to also include the user id like so:
public function postComment(Request $request, $picture_id)
{
$this->validate($request, [
"comment" => ['required', 'max:1000'],
]);
$picture = Picture::find($picture_id);
$picture->status()->create([
'body' => $request->input('comment'),
'user_id' => Auth::id()
]);
return redirect()->back();
}
Also make sure to add user_id to the $fillable property in the Status model to allow it to be assigned through the create method
protected $fillable = [
'body', 'user_id',
];
This should link the status you just created to both the picture and user class. You can then retrieve it elsewhere with something like Auth::user()->statuses

laravel 5.2 auth Conditions for email verify

i want to edit auth and add Additional Conditions
for check user for active or ...
where can edit authcontroller code?
First you need a status column in users table to mark the user as active or inactive.
To check the user status during login you need to modify this file:
project_folder\vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php
You can change validateLogin() method. I assume, for active user the status code is 1 and 0 for inactive user. Your code should look like this:
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->loginUsername() => 'required', 'password' => 'required', 'status' => 1,
]);
}
In Auth\AuthController.php, add this function ( I assume the column name for user status is "is_active" ):
public function authenticated($request, $user) {
if ($user->is_active != 'Y') {
Auth::logout();
return redirect('login')->withErrors([
$this->loginUsername() => 'Your '.$this->loginUsername().' is not active. Please contact Administrators'
]);
}else {
return redirect()->intended($this->redirectPath());
}
}

Cartalyst Sentinel Laravel - How do you create roles?

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.

Resources