Language choser - laravel-5.1

I want to make a Language chooser in Laravel 5.1, but i know how I can make it, but I want that it remembers the selected language (so if I visit the page again, that I have still the samen language). But how can I do it? And have I need to store it in the DB?
Better explained here:
So if a visitor joins the site for the first time, then the language will be "English" and then he can choose his language that he/she want's. If the same person leaves and joins at another time, then the language would be the same as the person selected earlier.

I’ve written a blog post about this, see Detect and change language on the fly with Laravel for details but basically you need a Middleware to attribute a default locale:
/**
*
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Session::has('locale')) {
$locale = Session::get('locale', Config::get('app.locale'));
} else {
$locale = substr($request->server('HTTP_ACCEPT_LANGUAGE'), 0, 2);
if ($locale != 'fr' && $locale != 'en') {
$locale = 'en';
}
}
App::setLocale($locale);
return $next($request);
}
And a method (along with a form) to store a language change:
/**
* Change session locale
* #param Request $request
* #return Response
*/
public function changeLocale(Request $request)
{
$this->validate($request, ['locale' => 'required|in:fr,en']);
\Session::put('locale', $request->locale);
return redirect()->back();
}

Related

How to edit $request-url in middleware in Laravel 5.8 before it hits route API

I'm developing an API. I want to edit the incoming $request->url so it hits different routes based on the authorization. It should work for any kind of request (POST, GET , DELETE etc...).
By now I 've come this far. The middleware get hit, but $request->server->set('REQUEST_URI','http://...'); doesn 't have any effect. The incoming $request url stays at it is. This is the simplified middleware code of the class RedirectToUrl:
<?php
namespace App\Http\Middleware;
use Closure;
use Auth;
use Illuminate\Http\Request;
class RedirectToUrl
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
if($request->user()->role()->first()->role === "admin"){
$request->server->set('REQUEST_URI','http://rest-api-with-session-httponly:8888/api/admin');
}elseif($request->user()->role()->first()->role === "basic"){
$request->server->set('REQUEST_URI','http://rest-api-with-session-httponly:8888/api/basic');
}else{
$request->server->set('REQUEST_URI','http://rest-api-with-session-httponly:8888/api/basic');
}
return $next($request);
}
}
I`ve put the middleware RedirectToUrl::class at the end of the middleware priority:
protected $middlewarePriority = [
\App\Http\Middleware\AddAuthHeader::class,
\Illuminate\Auth\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
\App\Http\Middleware\CheckRole::class,
\App\Http\Middleware\RedirectToUrl::class,
];
Any hint appreciated.
Thx!

Problem to get logged in with Laravel and docker on production

I have a Laravel application and I am currently working on integrating docker. The app runs perfectly locally but on production I simply can't log in. Every time I submit the log in form I get redirected to the log in form without any message of success nor failure.
I have realized that the request it reaches the controller it should but it does not reach the action. I put a die command in the constructor and it worked but it didn't when I did the same in the first line of the controller's action.
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Monolog\Logger;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class AuthController extends Controller
{
/*
|---------------------------------------------------------------------
| Registration & Login Controller
|---------------------------------------------------------------------
|
| This controller handles the registration of new users, as well as the
| authentication of existing users. By default, this controller uses
| a simple trait to add these behaviors. Why don't you explore it?
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login / registration.
*
* #var string
*/
protected $redirectTo = '/';
/**
* Create a new authentication controller instance.
*
* #return void
*/
public function __construct()
{
// die('something') works here
$this->middleware('guest', ['except' => ['logout', 'register', 'showRegistrationForm']]);
// die('something') works here too
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'rut' => 'required|max:30',
'apellidos' => 'required|max:255',
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|confirmed|min:6',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
}
public function login(Request $request)
{
//die('something'); doesn't work here
$this->validateLogin($request);
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
}
I don't know if you still need it, but I had the same problem. You need to modify the paths in bootstrap/cache/config.php with the path that you set it for WORKDIR in Dockerfile.

zend-authentication - setting identity to custom object with rbac roles loaded

In a ZF2 project i am using the AuthenticationService to validate a users log in credentials. This is working fine, except it only stores in the session a string containing the users name.
What i would like would be for subsequent calls to AuthenticationService::getIdentity to return a custom Identity object, that is populated with the users database id, roles and permissions (popualted from an RBAC service), so that the object in the session is a bit more useful.
I am able to create this object, but am unsure of the best way to keep it in the session; ideally i would like to override the entry with the key Zend_Auth, but this does not seem to be working.
My code so far:
<?php
namespace Authentication\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\Authentication\AuthenticationService;
use Authentication\Form\Login\LoginForm;
use Zend\Form\Form;
use Authentication\Model\Identity\AuthenticatedIdentity;
class AuthenticationController extends AbstractActionController
{
/**
*
* #var AuthenticationService
*/
protected $authenticationService;
/**
*
* #var LoginForm
*/
protected $loginForm;
/**
*
* #param AuthenticationService $authenticationService
* #param LoginForm $loginForm
*/
public function __construct(AuthenticationService $authenticationService, LoginForm $loginForm){
$this->authenticationService = $authenticationService;
$this->loginForm = $loginForm;
}
public function indexAction(){
$form = $this->loginForm;
$viewModel = new ViewModel();
$viewModel->setVariables([
'loginForm' => $form
]);
if($this->getRequest()->isPost() === false){
return $viewModel;
}
$form->setData($this->getRequest()->getPost());
if($form->isValid() === false){
return $viewModel;
}
$data = $form->getData();
$authenticationAdapter = $this->authenticationService->getAdapter();
$authenticationAdapter->setIdentity($data['credentials']['username'])
->setCredential($data['credentials']['password']);
$authenticationResult = $this->authenticationService->authenticate($authenticationAdapter);
if($authenticationResult->isValid() === false){
$viewModel->setVariable('validCredentials', false);
return $viewModel;
}
/**
* Create a user model and save it to the session.
*/
$authenticationResultRow = $authenticationAdapter->getResultRowObject(null, ['password']);
$permissions = $this->rbacService->getPermissionsForUser($authenticationResultRow->user_id);
$roles = $this->rbacService->getRolesForUser($authenticationResultRow->user_id);
$identity = new AuthenticatedIdentity(
$authenticationResult->getIdentity(),
'admin',
$permissions,
$roles
);
$identity->setUserId($authenticationResultRow->user_id);
//how to store this Identity object in session so AuthenticationService will return it?
return $this->redirect()->toRoute('dashboard');
}
}
Check out https://github.com/zendframework/zend-authentication/blob/master/src/AuthenticationService.php#L75 and https://github.com/zendframework/zend-authentication/blob/master/src/Storage/StorageInterface.php
You can write the AuthenticatedIdentity object directly to the storage like so:
$this->authenticationService->getStorage()->write($identity);
However, I would advice against doing so because:
If the user's permissions/roles change during the session he/she would have to log out and back in to see any changes which is not very user-friendly.
Your AuthenticatedIdentity object and all objects it contains need to be serializable, which can become problematic to maintain.
I would (and do) fetch the user object and/or roles when needed, either from DB or some form of cache but don't store it in the session.

Middleware in laravel does not works properly

I am trying to apply middleware on my routes like this:
Route::get('twitterlogin','TwitterController#gettwitterlogin');
Route::post('twitterlogin','TwitterController#posttwitterlogin');
Route::group(['middleware'=>'auth'],function()
{
Route::get('twitternewsfeed','TwitterController#gettwitternewsfeed');
Route::post('postimage','TwitterController#postimage');
Route::post('posttweet','TwitterController#posttweet');
Route::get('twitterlogout','TwitterController#gettwitterlogout');
Route::post('editprofilepic','TwitterController#posteditprofilepic');
Route::post('searchuser','TwitterController#postsearchuser');
Route::post('edittweet{id}','TwitterController#postedittweet');
Route::get('deletetweet{id}','TwitterController#getdeletetweet');
Route::post('editprofile','TwitterController#posteditprofile');
Route::get('userprofile{email}','TwitterController#getuserprofile');
});
And when i am trying to submit my login form it does not bring me on next page. It again opens the login page....what is the exact problem in this? My authenticate middleware is as follows....
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class Authenticate
{
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new middleware instance.
*
* #param Guard $auth
* #return void
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('twitterlogin');
}
}
return $next($request);
}
}
I assume you are using the Route::post('twitterlogin','TwitterController#posttwitterlogin') route to perform your login operation - please ensure that you're logging the user in with Laravel's Auth correctly and redirecting the user to the appropriate route in the posttwitterlogin method
I feel you also may also be using a different table to store user data - in which case, kindly ensure that you have your auth.php config file setup appropriately
In case you're using a custom authentication mechanism for some reason, you'll need to replace $this->auth->guest() in your middleware with the appropriate alternative check for the user not being logged-in
For eg: if you're setting a Session variable called is_authenticated to true with \Session::put('is_authenticated', true) upon successfully logging in, you'll check for it with if(\Session::get('is_authenticated') === true) in your Middleware instead of relying on the Laravel Auth method if ($this->auth->guest())

Laravel Validator AND / require a field ONLY if both conditions are met

Using Laravel 5.1, is there a way to require a field ONLY if both conditions are met?
In the code example below, in the rules, I have field2_en and field2_de. I put 2 required_if rules for each field, the field becomes required if 1 of the 2 OR both required_if rules is/are met. It's not what I want. Here is what I want:
I would like field2_en to be required ONLY if language = en AND
radiobutton = 2
I would like field2_de to be required ONLY if language = de AND
radiobutton = 2
AddRequest.php
namespace App\Http\Requests\Post;
use App\Http\Requests\Request;
class AddRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return auth();
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'language' => ['required', 'in:en,de'],
'field1_en' => ['required_if:language,en'],
'field1_de' => ['required_if:language,de'],
'radiobutton' => ['required', 'in:1,2'],
'field2_en' => ['required_if:language,en', 'required_if:radio,2'],
'field2_de' => ['required_if:language,de', 'required_if:radio,2']
];
}
}
I have been able to do it with sometimes() like below or with extend, but I wanted to know if there was other ways of doing it since I am using laravel-jsvalidation plugin and it doesn't work with such sometimes conditional validations.
protected function getValidatorInstance()
{
$validator = parent::getValidatorInstance();
$validator->sometimes('field2_en', 'required|min:2', function($input)
{
return ($input->language == 'en' && $input->radiobutton == '2');
});
...
return $validator;
}

Resources