change database connection just for 1 user - laravel

I need to use another db connection just for 1 user.
First of all I created another connection in the config/database.php file:
'mysqltest' => [
'driver' => 'mysql',
//...
],
It works. I tried it with something like this Model::on('mysqltest')->all().
Now I would like to change connection everywhere in the project, so I thought to change it after user login.
I'm trying this without success:
protected function authenticated(Request $request, $user)
{
//
if ($user->user_id == 1) {
//DB::purge('mysqltest');
//DB::reconnect('mysqltest');
DB::setDefaultConnection('mysqltest');
}
}

Create middleware for example
php artisan make:middleware SelectDB
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class SelectDB
{
public function handle(Request $request, Closure $next)
{
if (auth()->id() == 1) {
DB::setDefaultConnection('mysqltest');
}
return $next($request);
}
}
Add middleware in App\Http\Kernel
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\SelectDB::class,
\App\Http\Middleware\EncryptCookies::class,
...

Related

Do not redirect if guest?

Is there a way to use guest middleware yet, if the request->expectsJson() it does not redirect, just errors? (Like the auth middleware).
Or would I need to write custom middleware?
You can make your own middleware inspired by RedirectIfAuthenticated:
app/Http/Middleware/AbortIfAuthenticated.php
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AbortIfAuthenticated
{
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
abort(403, "Not allowed");
}
}
return $next($request);
}
}
Then replace the middleware by your own in app/Http/Kernel.php
(Or add a new one)
protected $routeMiddleware = [
...
'guest' => \App\Http\Middleware\AbortIfAuthenticated::class,
...
];

How to store each user's request IPs and Agent in Laravel log

Currently using Exceptions/Handler.php, I can log all types of errors with all details of Users.
But how to log all requests data, and through which file?
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Exception;
use Throwable;
use Request;
use Log;
.....
public function report(Exception $e)
{
Log::info($e->getMessage(),
[
'url' => Request::url(),
'all' => getallheaders(),
'Referer' => Request::server('HTTP_REFERER')
]);
$error =
[
'url' => Request::url(),
'all' => getallheaders(),
'Referer' => Request::server('HTTP_REFERER')
];
$message = $error['url'] . "\n" . json_encode($error, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
\Log::info($message);
return parent::report($e);
}
....
you can log all data for example in middleware which will run for each request.
Create middleware:
php artisan make:middleware LogRequestMiddleware
Your middleware is saved to app/Http/Middleware/LogRequestMiddleware.php
In your middleware rewrite handle method:
public function handle($request, Closure $next) {
Log::info('This is my log', ['request' => $request->all()])
return $next($request);
}
And at the top of the file add:
use Illuminate\Support\Facades\Log;
When you want to register global middleware for every request you can do it like this in your Kernel.php file:
protected $middleware = [
LogRequestMiddleware::class,
];
Where LogRequestMiddleware is your middleware :)

How to create a Custom Auth Guard / Provider for Laravel 5.7

I'm migrating from Laravel 4 to 5.7 and having trouble with my custom auth provider. I've followed various walkthroughs (e.g. 1, 2, 3) as well as quite a bit of googling.
I've attempted to get this working by the following:
Set the guards and providers and link to my target model.
'defaults' => [
'guard' => 'custom_auth_guard',
'passwords' => 'users',
],
'guards' => [
'custom_auth_guard' => [
'driver' => 'session',
'provider' => 'custom_auth_provider',
],
],
'providers' => [
'custom_auth_provider' => [
'driver' => 'custom',
'model' => App\UserAccount::class,
],
],
Register the driver defined in the above provider. I'm piggybacking off AuthServiceProvider for ease
...
public function boot()
{
$this->registerPolicies();
\Auth::provider('custom',function() {
return new App\Auth\CustomUserProvider;
});
}
...
Created my custom provider which has my retrieveByCredentials, etc. I've replaced the logic with some die() to validate if it is making it here. In Laravel 4, it used to go to validateCredentials().
class CustomUserProvider implements UserProviderInterface {
public function __construct()
{
die('__construct');
}
public function retrieveByID($identifier)
{
die('retrieveByID');
}
public function retrieveByCredentials(array $credentials)
{
die('retrieveByCredentials');
}
public function validateCredentials(\Illuminate\Auth\UserInterface $user, array $credentials)
{
die('validateCredentials');
}
For reference, App/UserAccount looks like so
class UserAccount extends Authenticatable
{
use Notifiable;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'public.user_account';
// no updated_at, created_at
public $timestamps = false;
private $_roles = [];
private $_permissions = [];
}
Finally, I am calling it via my controller.
if(\Auth::attempt($credentials){
return \Redirect::intended('/dashboard');
}
I have also tried to call the guard direct
if(\Auth::guard('custom_auth_guard')->attempt($credentials){
return \Redirect::intended('/dashboard');
}
This results in the following error: "Auth guard [custom_auth_guard] is not defined."
I've tried a few other commands to make sure there is no cache issue:
composer update
php artisan cache:clear
The results: when I call Auth::attempt($credentials) Laravel is trying to run a query on the users table. the expected result is that it would hit one of the die()'s in CustomUserProvider... or at lease try and query public.user_account as defined in the model.
I've been messing with this for some time and I must be missing something simple... hopefully someone with a bit more experience in Laravel 5 can see what I am doing wrong.
Thanks in advance!!
Managed to work it out. Couple little problems but the main one was that I was trying to piggyback on AuthServiceProvider as opposed to my own provider. Below is what I did to get a custom auth provider working in Laravel 5.7
Set the provider in config.auth.php.
'providers' => [
'user' => [
'driver' => 'eloquent',
'model' => \UserAccount::class,
],
],
Create a new provider in app/providers/ . This links the listed provider above with the correct User Provider Code.
namespace App\Providers;
use Auth;
use App\Auth\CustomUserProvider;
use Illuminate\Support\ServiceProvider;
class CustomAuthProvider extends ServiceProvider
{
public function register()
{
//
}
public function boot()
{
Auth::provider('eloquent',function()
{
return new CustomUserProvider(new \UserAccount());
});
}
}
Created my custom provider in app/auth/. This is the logic for validating the user and replaces the laravel functions for auth. I had an issue here where it was validating but not populating the user object. I originally had a test to see if the object was null and if it was, populate... however it was always populated with an empty object. removing the test allowed me to call Auth::user() functions.
namespace App\Auth;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
use Illuminate\Auth\EloquentUserProvider;
class CustomUserProvider implements EloquentUserProvider{
public function __construct()
{
$this->user = $user;
}
public function retrieveByID($identifier)
{
$this->user = \UserAccount::find($identifier);
return $this->user;
}
public function retrieveByCredentials(array $credentials)
{
// find user by username
$user = \UserAccount::where('name', $credentials['username'])->first();
// validate
return $user;
}
public function validateCredentials(\Illuminate\Auth\UserInterface $user, array $credentials)
{
//logic to validate user
}
Updated App/Models/UserAccount looks like so
use Illuminate\Foundation\Auth\User as Authenticatable;
class UserAccount extends Authenticatable
{
protected $table = 'public.user_account';
// no updated_at, created_at
public $timestamps = false;
private $_roles = [];
private $_permissions = [];
}
That's it. I can now validate via the below call
if(\Auth::attempt($credentials){
return \Redirect::intended('/dashboard');
}

Returning a controller in Laravel 5.6 route file

I am trying to route a request to a controller method. When I do this it works:
Route::get('/path', 'controller#method');
I would like to set the locale before calling the controller. I tried different options and nothing works:
Route::get('/path', function(){
desired_function();
return action('controller#method');
});
and
Route::get('/path', function(){
desired_function();
return [
'uses' => 'controller#method'
];
});
What am I missing?
1) Create a app/Http/Middleware/SetLocale.php with content:
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class SetLocale
{
public function handle(Request $request, Closure $next)
{
\App::setLocale('en'); // or get it from request
// or:
// $request->attributes->set('locale', 'en');
// in action: $request->get('locale');
return $next($request);
}
}
2) Attach it to route:
Route::get('/path', 'controller#method')
->middleware('App\Http\Middleware\SetLocale');
or to route group:
Route::group([
'middleware' => [
'App\Http\Middleware\SetLocale'
]
],
function() {
Route::get('/path', 'controller#method');
});
if You want it to be used globally everywhere:
in app/Http/Kernel.php :
/**
* The application's global HTTP middleware stack.
*
* #var array
*/
protected $middleware = [
...
'App\Http\Middleware\SetLocale' // add it to end of array
];

Laravel - How can I restrict access to admin login page based on IP address in LARAVEL?

How can I restrict access to admin login page based on IP address in LARAVEL?
I want to set a permission to the admin login page to a single IP Address.
you can use Request::ip(); and check it in middleware.. below is basic poc
middleware
class AdminAccessCheck
{
public function handle($request, Closure $next)
{
$ip = $request->ip();
if ($ip === config('admin.ip')) {
return $next($request);
}
return response()->error();
}
}
kernel.php
protected $routeMiddleware = [
...
'admin.ip_check' => \App\Http\Middleware\AdminAccessCheck::class,
];
web.php
Route::middleware(['admin.ip_check'])->group(function() {
//
});
If you prefer package, you can checkout this repo .. Firewall
Create a middleware
php artisan make:middleware IpMiddleware
Code:
<?php
namespace App\Http\Middleware;
use Closure;
class IpMiddleware
{
public function handle($request, Closure $next)
{
if ($request->ip() != "192.168.0.155") {
// here instead of checking a single ip address we can do collection of ips
//address in constant file and check with in_array function
return redirect('home');
}
return $next($request);
}
}
Register the Middleware in app/Http/Kernel.php file
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'ipcheck' => \App\Http\Middleware\IpMiddleware::class,
];
then apply middelware to routes
Route::get('/', ['middleware' => ['ipcheck'], function () {
// your routes here
}]);

Resources