Validation using Sentry2 in Laravel 4 - php

I want to use Sentry2 in my Laravel 4 application but I'm not sure how to use it to validate user submitted data before I interact with it. In my own models, I would write a $rules array to contain the validation rules and write a static validates() method that I could call in the controller.
But with Sentry2, how do I do this? Do I have to extend the User model that Sentry2 provides and use that instead? Or is there a way that Sentry allows me to add validation rules with extending it?
If I do extend the Sentry2 User model, do I extend it like so:
/app/models/User.php
class User extends \Cartalyst\Sentry\Users\Eloquent\User {
private static $rules = array(...);
public static validates($input, static::$rules) {...};
}
I then need to create my own config file instead of using the one that Sentry provides. I do the following in artisan:
php artisan config:publish cartalyst\sentry
and update the config file like so:
/app/config/packages/cartalyst/sentry/config.php
'users' => array()
'model' => 'User',
;
Is this correct? If so, do I just call the model to validate user submitted data like I normally would? So, for example, in the UsersController I would check input by doing:
$validator = User::validate(Input::all());

I believe you are on the right way. Sentry doesn't really do any validation when you're saving data (except for checking for a password and a login field), and if you want to use validation from directly within the Eloquent model, you can extend the current Cartalyst user model, exactly as you have done in your code.
In the config file, you may have to take your namespaces in account. To check that Sentry really is using your model, try getting the currently logged in user (Sentry::getUser()) and var_dump it (dd(Sentry::getUser()) to see that Sentry is really using your class).
After you've got that setup, you can use your Eloquent model and validation as you normally would, with the addition of having all Sentry methods and properties.
If you want to keep the validation logic separate from you model, you can have a look at using validation as a service: http://culttt.com/2013/07/29/creating-laravel-4-validation-services/

Related

Laravel - Validate inside Controller without make CustomRequest

I would like to validate the get parameter where i passed throug the route to my controller.
api/route
get /order/{id} -> OrderController::order
public function order($id) {
// validation here (rules= require,between 1 and 1000)
return Order::find($id);
}
how can I validate inside my controller without creating a separate request class?
which validation class do i have to import? (this one: Illuminate\Support\Facades\Validator ? )
Is this a good or common solution?
As #lagbox already wrote, you can check all of your questions inside the Laravel documentation.
Validation inside the controller
use Illuminate\Http\Request;
class MyController extends Controller
{
public function order(Request $request, int $id)
{
$validated = $this->validate([
// .. put your fields and rules here
]);
}
}
If your controller extends the base controller, that is shipped with every Laravel installation you have direct access to the validator via $this->validate.
With injecting the $request you have access to the fields that are send (POSTed) to your server.
If this is a good solution heavily depends on the projects size and other factors. It is definitely a good solution to start with. If your project grows and you need to have the same validation logic in various places you can again think about additional Form Request Validation.
To apply certain rules to the route parameter, f. ex. id, you can use Regular Expression Constraints.
Futher processing of request data
I personally would leave the validation inside the controller (or a form request class).
If there is any problem with the request data, then it should fail there and not continue to the service class.
You could say this is a kind of fail fast approach. Why moving more and more inside your code, if your request items might have an error (are not valid)?
$id is always present so required validation always passes.
So you only need to check between 1 and 1000 condition.
I think using regex constraints in the route is a good idea here.
Route::get('/order/{id}','OrderController#order')
->where(['id'=> '1000|^[1-9]{0,2}[1-9]$']);
If id is less than 1 or more than 1000 or any other random string it won't match the route and if there isn't any other matching routes too, it gives 404 error.
If you really want to validate the route parameter in the controller, you can use this:
$validator = \Illuminate\Support\Facades\Validator::make(['id' => $id],
[
'id' => 'required|integer|between:1,1000'
]
);
$validator->validate();

Laravel policy autodetect

today i was creating USER profile page with is controlled in ProfileController it returning views to profile page, profile settings, etc.
so i decide to make some Policy rules to Edit profile and etc.
so i found i should use Middleware / Gates / Policy, based on Laravel Doc i chose Policy because profil page is public but only specific part of it can author edit so i needed #can
So my steps:
php artisan make:policy ProfilePolicy ( without model )
Registered policy to AuthServiceProvider in $policies property
writed methods like edit inside ProfilePolicy
then i started thinking how i define it to my Controller hmmm, documentation doesnt helps me :/
so i tryed blade #can('edit', $user) method and it worked, but HOW ?, how to define specific policy to one Controller ? ( not Model ), how to define multiple Policy to single Controller
i m lost how laravel Magic done this maybe because of Naming ? ProfileController => ProfilePolicy ?
In the controller you can write this
public function edit(Profile $profile) {
$this->authorize('edit', $profile)
}
Laravel does this:
Check the type of $profile, and it's a Profile::class
Check policies registered for that class (your step 2)
Looks for the edit method in that policy, if not found, return false meaning user is not authorized
Executes the edit() function that returns true/false
In blade the #can directive does exactly the same thing.
Policies are meant to be tied to Models, it's a convenient way to write rules to handle single models, but they can be triggered in many ways (like the authorize() method in controllers and #can directive in blade).

laravel foundation files. am I doing this correctly?

In Laravel 5.1 I need to pass some data to the register view.
The getRegister() function in RegistersUsers trait is responsible to return the view.
At first I modified the function to pass my data but then I realized that the modifications would be overridden in case of an update.
So I made a new controller registerController and modified the route for getRegister like this: Route::get('auth/register', 'Auth\RegisterController#getRegister')
Inside the controller I redefined the getRegister function to return the view with my additional data.
Now I am thinking.. am I doing this correctly or do I need to use some other method and use the original AuthController some other way?
Also, default auth is set to use email for post login, how do I change it to use username without touching the foundation files?
Are all these matters regarding "extending the framework" ?
Thanks
First of all, it's always a bad idea to modify vendor files as the changes would be overwritten in case of any update in vendor package.
Answering your first question:
If you want to provide some additional data in registration view, you could do 2 things.
First one is to add your own getRegister() method:
public function getRegister()
{
return view('auth.register')->with(<parameter name>, <parameter value>);
}
The drawback of this solution is that in case of any future changes in trait's getRegister method those changes will not be incorporated into your controller.
So the better approach is to reuse trait's getRegister() method in your controller and add your parameters to whatever trait returns:
In your controller do:
use RegistersUsers {
RegistersUsers::getRegister as traitGetRegister;
}
public function getRegister()
{
return $this->traitGetRegister()->with(<parameter_name>, <parameter_value>);
}
Answering your second question:
Laravel's Auth::attempt() method that is used to login users uses DatabaseUserProvider to load users from the DB and that provider is flexible enough to use any credential set you provide. However, if you want to use AuthenticatesUsers trait to login users, you have to override its postLogin method, because of the validation it does for user credentials:
$this->validate($request, [
'email' => 'required|email', 'password' => 'required',
]);
UPDATE FOR LARAVEL 5.1: Since 5.1 there is no need to override postLogin() to change the column that is used to fetch users from the database. It is enough to set username property in the controller to the name of the column:
public $username = 'login';

Login with Facebook using Sentry in Laravel

I am facing a problem as the one posted here
The problem is this piece of code
$profile = $user->profiles()->save($profile);
which results in this error
Call to undefined method Illuminate\Database\Query\Builder::profiles()
I tried to do what was suggested here
but it didn't work for me. It seems the problem has been solved in a link provided which no longer works.
I wrote my question briefly since the same question has been asked by the user in the link I gave. I will appreciate any help. Thanks
Sentry provides their own User model. If you would like to add relationships to the User, you will need to extend Sentry's User model and update the Sentry config to point to your new User model.
First, create your User model which extends the Sentry User model:
<?php
use Cartalyst\Sentry\Users\Eloquent\User as SentryUserModel;
class User extends SentryUserModel
{
public function profiles()
{
return $this->hasMany('Profile');
}
}
Next, update the Sentry config to look at your User model instead of the default Sentry User model. To do this, publish the Sentry config file:
php artisan config:publish cartalyst/sentry
Once published, open the app/config/packages/cartalyst/sentry/config.php file. Update the 'users'.'model' value to use your new User model. For example:
'model' => 'User', // assumes non-namespaced custom User model
Sentry will now use your custom User model created above, with the defined relationships.

Laravel 5 new auth: Get current user and how to implement roles?

I am currently experimenting with the new Laravel 5 and got the authentication to work (register/login).
To get the authenticated user in my controller I currently inject Guard into the controller action:
use App\Http\Controllers\Controller;
use Illuminate\Contracts\Auth\Guard;
class ClientController extends Controller {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index(Guard $auth)
{
return view('client.index', ['user' => $auth->user()]);
}
...
First Question: Is this the recommended way?
Second Question: How would I go about implementing some kind of roles/permissions? Something like client.edit, client.add, ... Does Larval 5 offer some kind of convenience here?
How would I set the necessary role/permission for a route/controller action?
I am thinking that I might need to write my own middleware for that. Any suggestions on how to approach the problem?
After spending some more time on Laravel 5 I can an answer my own question:
Is injecting Guard the recommended way? No: If you need to access Auth in your view, you can do so already like this:
#if( Auth::check() )
Current user: {{ Auth::user()->name }}
#endif
This uses the Auth facade. A list of all available facades is in config/app.php under aliases:
What if I need Auth in my controller? Injecting an instance of Guard like shown in the question works, but you don't need to. You can use the Auth facade like we did in the template:
public function index()
{
if(\Auth::check() && \Auth::user()->name === 'Don') {
// Do something
}
return view('client.index');
}
Be aware that the \ is needed before the facade name since L5 is using namespaces.
I want to have permissions/roles using the new auth mechanism in L5: I implemented a lightweight permission module using the new middleware, it is called Laraguard. Check it out on Github and let me know what you think: https://github.com/cgrossde/Laraguard
UPDATE: For the sake of completeness I want to mention two more projects. They provide everything you need to save roles and permissions in the DB and work perfectly together with Laraguard or on their own:
https://github.com/caffeinated/shinobi
https://github.com/romanbican/roles
If you want make your own custom authentification, you need to keep the User model from Laravel 5 with all the dependency. After you will be able to login your user in your controller. Dont forget to put (use Auth;) after the namespace of your controller.

Categories