How to override laravel auto redirection if session exists - laravel-5.7

Hello i am new in laravel and i am working on laravel 5.7 i have 2 different auth tables one is users and other is companies first is how can i check that from which table is user logged in and second when i close and open browser laravel auto redirects to home if session exist but i also want to add check their to redirect user on certain page means if user logged in from user table redirect to abc view and if company is logged in from company table redirects to xyz view how can i override ?

Here is what i do for multiple auth tables :
Go to config > auth.php
Add Guard
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
'hash' => false,
],
'company' => [
'driver' => 'session',
'provider' => 'companies',
'hash' => false,
],
],
Add Provider
'providers' => [
'admins' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'companies' => [
'driver' => 'eloquent',
'model' => App\Companies::class,
],
],
Add Password
'passwords' => [
'admins' => [
'provider' => 'admins',
'email' => 'auth.emails.password',
'table' => 'password_resets',
'expire' => 60,
],
'companies' => [
'provider' => 'companies',
'email' => 'auth.emails.password',
'table' => 'password_resets',
'expire' => 60,
],
],
GO to App\Http\Middleware\RedirectIfAuthenticated
Update handel method
public function handle($request, Closure $next, $guard = null)
{
if ($guard === 'admin' && Auth::guard($guard)->check()) {
return redirect('/admin');
}
if ($guard === 'company' && Auth::guard($guard)->check()) {
return redirect('/company');
}
return $next($request);
}
Now i'm asumming you've different controller for users and companies in that case you can add middleware in you're controller
public function __construct()
{
// For Admin Users
$this->middleware('auth:admin');
// For Companies Users
//$this->middleware('auth:company');
}
Or you can add middleware in the route as well
Example
Route::group([
'namespace' => 'Companies',
'middleware' => 'auth:company'
], function () {
// Authentication Routes...
Route::get('login', 'Auth\LoginController#showLoginForm')->name('login');
});
I Hope this helps.

Related

Api Platform - NotFoundHttpException when calling an itemOperations endpoint

I have created a custom endpoint using API Platform:
#[ApiResource(
collectionOperations: [
'get' => [
'normalization_context' => ['groups' => ['product:list']]
],
'post' => [
'denormalization_context' => ['groups' => ['product:list']]
]
],
itemOperations: [
'get_by_user' => [
'method' => 'GET',
'path' => '/products/user/{id}',
'read' => 'false',
'controller' => ProductController::class,
'normalization_context' => ['groups' => ['product:list']],
'openapi_context' => [
'summary' => 'Retrieves the Product collection for a specific user ID',
'description' => 'Retrieves the Product collection for a specific user ID'
]
],
], )]
and the controller method:
public function __invoke(int $id): array
{
$prod = $this->productRepository
->findBy(
['user' => $id],
);
return $prod;
}
And the error when I try to call this endpoint is:
Not Found - api/vendor/api-platform/core/src/EventListener/ReadListener.php
Has anyone any ideas what might be the issue?

API Platform - How to add response code in Swagger UI using decorator to add 400, 404, 500 response code so client know the response in adwance

I want to add Response code(400,404, 500) for each route in swagger UI using , so that user know in advance what will be the response for these error code.
I am following following link but not sure how can I modify the Response object and can add the response for 400, 404, 401 so on.
https://api-platform.com/docs/core/openapi/#overriding-the-openapi-specification
I am using symfony 5.2 and apiplatfrom 2.6 while writing this question.
When you are using decorators, you are essentially extending existing service code.
First you are getting path and then set your custom operation in swagger context with the given code.
If you notice the code block:
$openApi->getPaths()->addPath('/api/grumpy_pizzas/{id}', $pathItem->withGet(
$operation->withParameters(array_merge(
$operation->getParameters(),
[new Model\Parameter('fields', 'query', 'Fields to remove of the output')]
))
));
The path item take Operation object as an argument which has withResponses method that can be used to modify any responses that your path generates.
Take this as per-cursor and you can check whole source and see what fits your requirements best. Check source : PathItem.php
You can build response according to Response object and add it to Operation and to path.
Tip: Any editor with good linter would make your coding easier as it will be able to show you available methods.
Its late to post but I got the solutions for adding response code in my Swagger Ui, it can help some looking for solution.
private function setErrorResponseDescriptions(OpenApi $openApi): OpenApi
{
$schemas = $openApi->getComponents()->getSchemas();
$schemas['Error'] = [
'type' => 'object',
'properties' => [
'type' => [
'type' => 'string',
'readOnly' => true,
],
'title' => [
'type' => 'string',
'readOnly' => true,
],
'detail' => [
'type' => 'string',
'readOnly' => true,
],
],
];
$schemas['ValidationError'] = [
'type' => 'object',
'properties' => [
'type' => [
'type' => 'string',
'readOnly' => true,
],
'title' => [
'type' => 'string',
'readOnly' => true,
],
'detail' => [
'type' => 'string',
'readOnly' => true,
],
'validations' => [
'type' => 'array',
'readOnly' => true,
'items' => [
'type' => 'object',
'properties' => [
'propertyPath' => [
'type' => 'string',
'readOnly' => true,
],
'message' => [
'type' => 'string',
'readOnly' => true,
],
]
]
]
],
];
foreach ($openApi->getPaths()->getPaths() as $path => $pathItem) {
foreach (['PUT', 'POST', 'PATCH', 'GET'] as $method) {
$item = $pathItem->{'get' . ucfirst($method)}();
if ($item) {
$item->addResponse(
new Model\Response(
description: 'Unauthorized',
content: new \ArrayObject([
'application/problem+json' => [
'schema' => [
'$ref' => '#/components/schemas/Error',
],
],
])
),
'401'
);
if ('GET' !== $method) {
$item->addResponse(
new Model\Response(
description: 'Bad request',
content: new \ArrayObject([
'application/problem+json' => [
'schema' => [
'$ref' => '#/components/schemas/ValidationError',
],
],
])
),
'400'
);
} else {
$item->addResponse(
new Model\Response(
description: 'Not Found',
content: new \ArrayObject([
'application/problem+json' => [
'schema' => [
'$ref' => '#/components/schemas/Error',
],
],
])
),
'404'
);
}
}
}
}
return $openApi;
}

Configuring api-platform to include header in OpenAPI (AKA Swagger) documentation

I am using API-Platform with JWTs and have created a decorator to allow Swagger to display a /authentication_token endpoint as described by https://api-platform.com/docs/core/jwt/ and to a lesser degree https://api-platform.com/docs/core/openapi/. In addition to providing an email and password, I also need to provide a third parameter which is a UUID which identifies the account the user belongs to. I was able to do so by including the UUID in the body, but I would rather have it included as a header such as X-Account-UUID.
How can this be modified so that Swagger-UI includes this uuid property as a header and not in the body's JSON?
<?php
// api/src/OpenApi/JwtDecorator.php
declare(strict_types=1);
namespace App\OpenApi;
use ApiPlatform\Core\OpenApi\Factory\OpenApiFactoryInterface;
use ApiPlatform\Core\OpenApi\OpenApi;
use ApiPlatform\Core\OpenApi\Model;
final class JwtDecorator implements OpenApiFactoryInterface
{
private $decorated;
public function __construct(OpenApiFactoryInterface $decorated)
{
$this->decorated = $decorated;
}
public function __invoke(array $context = []): OpenApi
{
$openApi = ($this->decorated)($context);
$schemas = $openApi->getComponents()->getSchemas();
/*
echo(json_encode(['class'=>get_class($this), 'methods'=>get_class_methods($this)]));
echo(json_encode(['class'=>get_class($this->decorated), 'methods'=>get_class_methods($this->decorated)]));
echo(json_encode(['class'=>get_class($openApi), 'methods'=>get_class_methods($openApi)]));
echo(json_encode(['class'=>get_class($openApi->getComponents()), 'methods'=>get_class_methods($openApi->getComponents())]));
echo(json_encode(['class'=>get_class($schemas), 'properties'=>$schemas]));
$securitySchemas = $openApi->getComponents()->getSecuritySchemes();
echo(json_encode(['class'=>get_class($securitySchemas), 'properties'=>$securitySchemas]));
$headers = $openApi->getComponents()->getHeaders();
exit(json_encode(['class'=>get_class($headers), 'properties'=>$headers]));
*/
$schemas['Token'] = new \ArrayObject([
'type' => 'object',
'properties' => [
'token' => [
'type' => 'string',
'readOnly' => true,
],
],
]);
$schemas['Credentials'] = new \ArrayObject([
'type' => 'object',
'properties' => [
'email' => [
'type' => 'string',
'example' => 'john.doe#bla.com',
],
'password' => [
'type' => 'string',
'example' => 'secret',
],
'uuid' => [
'type' => 'string',
'in' => 'header',
'example' => '1234abcd-abcd-1234-abcd-123412341234',
],
],
'headers' => [
'uuid' => [
'type' => 'string',
'in' => 'header',
'example' => '1234abcd-abcd-1234-abcd-123412341234',
],
],
]);
$responses = [
'200' => [
'description' => 'Get JWT token',
'content' => [
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/Token',
],
],
]
]
];
$content = new \ArrayObject([
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/Credentials',
],
],
]);
$requestBody = new Model\RequestBody('Generate new JWT Token', $content);
$post = new Model\Operation('postCredentialsItem', [], $responses, 'Get JWT token to login.', '', new Model\ExternalDocumentation, [], $requestBody);
$pathItem = new Model\PathItem('JWT Token', null, null, null, null, $post);
$openApi->getPaths()->addPath('/authentication_token', $pathItem);
return $openApi;
}
}

I'm trying to create multi login in laravel 5.7 and this error appeared, can anyone help me?

Symfony \ Component \ Debug \ Exception \ FatalThrowableError (E_RECOVERABLE_ERROR)
Argument 2 passed to Illuminate\Auth\SessionGuard::__construct() must implement interface Illuminate\Contracts\Auth\UserProvider, null given, called in C:\laragon\www\hotel\vendor\laravel\framework\src\Illuminate\Auth\AuthManager.php on line 123
<?php
namespace App\Http\Controllers\Auth;
use App\User;use App\Admin;use App\GestionnaireReceptionniste;use App\GestionnaireResto;use App\Http\Controllers\Controller;use Illuminate\Support\Facades\Hash;use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;use Illuminate\Http\Request;
class RegisterController extends Controller
{
use RegistersUsers;
protected $redirectTo = '/home';
public function __construct()
{
$this->middleware('guest');
$this->middleware('guest:admin');
$this->middleware('guest:gestionnairereceptionniste');
$this->middleware('guest:gestionnaireresto');
}
public function showAdminRegisterForm()
{
return view('auth.register', ['url' => 'admin']);
}
public function showGestionnaireReceptionnisteRegisterForm()
{
return view('auth.register', ['url' => 'gestionnairereceptionniste']);
}
public function showGestionnaireRestoRegisterForm()
{
return view('auth.register', ['url' => 'gestionnairesto']);
}
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:6', 'confirmed'],
]);
}
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
protected function createAdmin(Request $request)
{
$this->validator($request->all())->validate();
$admin = Admin::create([
'name' => $request['name'],
'email' => $request['email'],
'password' => Hash::make($request['password']),
]);
return redirect()->intended('login/admin');
}
protected function createGestionnaireReceptionniste(Request $request)
{
$this->validator($request->all())->validate();
$gestionnairereceptionniste = GestionnaireReceptionniste::create([
'name' => $request['name'],
'email' => $request['email'],
'password' => Hash::make($request['password']),
]);
return redirect()->intended('login/gestionnairereceptionniste');
}
protected function createGestionnaireResto(Request $request)
{
$this->validator($request->all())->validate();
$gestionnaireresto =CreateGestionnaireResto::create([
'name' => $request['name'],
'email' => $request['email'],
'password' => Hash::make($request['password']),
]);
return redirect()->intended('login/admin');
}
}
models:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Admin extends Authenticatable
{
use Notifiable;
protected $guard = 'admin';
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
}
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class GestionnaireReceptionniste extends Authenticatable
{
use Notifiable;
protected $guard = 'gestionnairereceptionniste';
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
}
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class GestionnaireResto extends Authenticatable
{
use Notifiable;
protected $guard = 'gestionnaireresto';
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
}
guard:
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'gestionnairereceptionniste' => [
'driver' => 'session',
'provider' => 'gestionnaireceptionnistes',
],
'gestionnaireresto' => [
'driver' => 'session',
'provider' => 'gestionnairerestos',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
'gestionnairereceptionnistes' => [
'driver' => 'eloquent',
'model' => App\GestionnaireReceptionniste::class,
],
'gestionnairerestos' => [
'driver' => 'eloquent',
'model' => App\GestionnaireResto::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
],
],
];
ReditectIfAuthenticated:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
public function handle($request, Closure $next, $guard = null)
{
if ($guard == "admin" && Auth::guard($guard)->check()) {
return redirect('/admin');
}
if ($guard == "gestionnairereceptionniste" && Auth::guard($guard)->check()) {
return redirect('/gestionnairereceptionnister');
}
if ($guard == "gestionnairesto" && Auth::guard($guard)->check()) {
return redirect('/gestionnairesto');
}
if (Auth::guard($guard)->check()) {
return redirect('/home');
}
return $next($request);
}
}
There is a typo in your config/auth.php file.
This:
'gestionnairereceptionniste' => [
'driver' => 'session',
'provider' => 'gestionnaireceptionnistes', // <-- typo
],
should be:
'gestionnairereceptionniste' => [
'driver' => 'session',
'provider' => 'gestionnairereceptionnistes',
],

Cakephp 3.x Saving multiple tables

In my cakephp (3.3) project, How to save multiple tables in a single save. My association is as follows, also I am giving my code here.
Table1 : users
In class UsersTable extends Table
$this->hasOne('ProfileDetails', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
Table2 : profile_details
In class ProfileDetailsTable extends Table
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
What should be the data format to save multiple tables?
In my template I have added the following , for now I have used only few fields
$this->Form->input('User.username',['type' => 'text','class'=>'form-control']) ?>
$this->Form->input('User.password',['type' => 'password','class'=>'form-control']) ?>
$this->Form->input('User.email',['type' => 'text','class'=>'form-control']) ?>
$this->Form->input('ProfileDetail.first_name',['type' => 'text','class'=>'form-control']) ?>
In the controller before saving i have debuged which gives result as follows
debug($this->request->data);
$user = $this->Users->patchEntity($user, $this->request->data);
debug($user);
exit;
$this->Users->save($user)
Result of debug
\src\Controller\UsersController.php (line 39)
[
'User' => [
'username' => 'Tester',
'password' => '43434324',
'email' => 'test#gmail.com',
'role' => 'admin'
],
'ProfileDetail' => [
'first_name' => 'Tester'
]
]
\src\Controller\UsersController.php (line 41)
object(App\Model\Entity\User) {
'User' => [
'username' => 'Tester',
'password' => '43434324',
'email' => 'test#gmail.com',
'role' => 'admin'
],
'ProfileDetail' => [
'first_name' => 'Tester'
],
'[new]' => true,
'[accessible]' => [
'*' => true
],
'[dirty]' => [
'User' => true,
'ProfileDetail' => true
],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [
'email' => [
'_required' => 'This field is required'
]
],
'[invalid]' => [],
'[repository]' => 'Users'
}
Could you please suggest me how to save this data in multiple tables with single save with validation?
Looking at your debug, there is an error saying the email field is required. Maybe that is your problem..
If still not working , try this:
replace User by users
and ProjectDetail by project_details
In your form. And also remove joinType from following:
$this->hasOne('ProfileDetails', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);

Resources