I built a filter which checks some keys and ids sent and then gives the go or no go. The problem is that a filter in Laravel should return a string while I just wnat to return a boolean and let it trigger the intended route.
Filter:
Route::filter('api_checkauth', function($route)
{
//user"ok"
$user_id = (int) $route->getParameter('user_id');
$sig = $route->getParameter('sig');
$user = User::find($user_id);
if($user) {
//user email
$email = $user->email;
//user api key
$api_key = $user->api_key;
//recreate signature
$_sig = hash_hmac("sha256", $email . $user_id, $api_key);
if($_sig === $sig) {
return Response::json(array("message"=>"Request Ok"),200);
} else {
return Response::json(array("message"=>"Request Bad"),400);
}
} else {
return Response::json(array("message"=>"Request not authorized"),401);
}
});
Routes:
// Route group for API versioning
Route::group(array('prefix' => 'api/v1', 'before' => 'api_checkauth'), function()
{
Route::get('/pim/{user_id}/{sig}', 'MoreOrLessController#index');
});
So the question is, how can I still trigger the route which i defined in the group? Because what happens now is a that only a message is printed instead of a controller method that should be triggered.
Thanks
In Laravel, if a filter returns a response, that response is considered the response to the request and the route is not executed. So, in order for the route to be executed return a response only if the user is not authorized.
if($user) {
$email = $user->email;
$api_key = $user->api_key;
$_sig = hash_hmac("sha256", $email . $user_id, $api_key);
if($_sig !== $sig) {
return Response::json(array("message"=>"Request Bad"),400);
}
} else {
return Response::json(array("message"=>"Request not authorized"),401);
}
The answer is that you're returning your 200 HTTP response in the wrong place.
As you noted, you will always get a JSON string response from the filter no matter what happens, due to the structure of your if/else statement.
Instead of returning your 200 response in the filter, handle that in your MoreOrLessController#index action. So, to clarify, *do not return ANYTHING in the filter when you confirm $_sig === $sig*.
That should do it!
Related
I am new in PHP and working to modify one API. Its built with Laravel Framework. I have API function like below in my controller.
public function DeleteOneMail(Request $request)
{
$uid = $request->uid;
if (\Request::is('api/*')) {
if ($request->has('key')) {
if (in_array($request->input('key'), explode(',', env('API_KEY')))) {
if ($uid == '') {
return response()->make('Please Enter UID', 401);
} else {
$client = Client::account('default');
$client->connect();
$inbox = $client->getFolder('INBOX');
$message = $inbox->getMessage($uid);
if ($message) {
return response(['success' => 1], 200);
} else {
return response(['success' => 0, 'message' => 'No Data Found'], 200);
}
}
} else {
return response()->make('Unauthorized Access. Please enter correct API Key', 401);
}
} else {
return response()->make('Unauthorized Access. Please enter correct API Key', 401);
}
}
}
I am calling API like below
https://example.com/api/delete-one-mail?key=2221212&uid=214
Its working fine without any issue. Now I want pass multiple uid with request and so I can process that uid one by one with my api function. I am not getting idea how I can pass arrary and process it. Let me know if any expert can help me for solve my puzzle. Thanks!
Your can pass an array like this
https://example.com/api/delete-one-mail?key=2221212&uid[]=214&uid[]=111&uid[]=222
$request->uid should be an array but you can make sure (if anyone use the old url with ony one uid) by doing
$uids = Arr::wrap($request->uid);
If you want to send an array by GET request just use []
https://example.com/api/delete-one-mail?key=2221212&uid[]=1&uid[]=2
In your controller you will get an array
$uid = $request->uid;
dd($uid);
As a result you will get
[1, 2]
I'm trying to fix an if-else statement in the request for my controller. What I'm trying to do is: if the auth::user-companyID == $request-companyID then true else false; The companyID for the request is in a hidden field on the blade file.
CustomRequest
public function authorize()
{
$user = Auth::user();
if ($user->companyID == $request->companyID) {
return true;
} else {
return false;
}
}
Controller
public function edit(EquipmentRequest $request, $id)
{
$validated = $request->validated();
$user = Auth::user();
$equipment = EquipmentModel::where('id', '=', $id)->first();
$equipment->Year = $request->Year;
$equipment->Make = $request->Make;
$equipment->Model = $request->Model;
$equipment->Type = $request->Type;
$equipment->unitNumber = $request->unitNumber;
$equipment->AnnualInspectionDate = $request->AnnualInspectionDate;
$equipment->userID = $request->userID;
$equipment->companyID = $user->companyID;
$e = $equipment->save();
if ($e) {
$request->session()->flash('success', 'The equipment was successfully updated.');
} else {
$request->session()->flash('error',
'An error occurred while saving. Please refresh your browser and try again.');
}
return redirect()->route('equipmentlist');
}
This form worked before I started messing with it so I know the form is working correctly on the blade file. I'm not sure if you can pass the request data the way I'm doing it or if I have to do a construct to do it this way. I would really appreciate any advice.
use Illuminate\Http\Request;
public function authorize()
{
$user = auth()->user();
return $user->companyID === request()->companyID;
}
How to print out data within function beforeAction? I want to make some verification before each action in a controller, therefore if some condition occurs in beforeAction I should print out data and prevent further execution, for example, JSON:
[
status: "error",
msg: "access denied"
]
I try to even inner redirect to another controller, but it doesn't work.
public function beforeAction($action)
{
$request = Yii::$app->request;
if ( ! checkByToken($request->get('token')) && $this->getRoute() != 'web/abonent/token_error') {
\Yii::$app->runAction('web/abonent/token_error');
return true;
}
return parent::beforeAction($action); // TODO: Change the autogenerated stub
}
But maybe there an another concept of doing so. I just need to check the condition before any actions and print our result or let the action execute.
To prevent further execution:
public function beforeAction($action) {
return false; // key point
}
To print out data within beforeAction:
public function beforeAction($action) {
// set response format = json:
Yii::$app->response->format = Response::FORMAT_JSON;
// then, set the response data:
Yii::$app->response->data = [
'status' => 'error',
'msg' => 'access denied'
];
return false;
}
I think will be better
public function beforeAction($action)
{
$request = Yii::$app->request;
if ( ! checkByToken($request->get('token')) && $this->getRoute() != 'web/abonent/token_error') {
$action = 'error';
}
return parent::beforeAction($action); // TODO: Change the autogenerated stub
}
Action name must be 'actionError'
I am having issues passing user details after authenticating the user. The variable $newUser has the required information, but it can't be passed to the user.index view. I am using Laravel 5.1.
Route::get('user/home', ['as' => 'home', function () {
return view('user.index');
}]);
Route::get('{provider}/login', function ($provider) {
global $newUser;
OAuth::login($provider, function ($user, $userdetails) {
$newUser = $userdetails;
$email = DB::table('users')->where('email', $newUser->email)->value('email');
if( isset($email)) {
echo "Welcome " . $newUser->full_name . " <br/>";
}
else {
echo "New User! <br/>";
$user->name = $newUser->full_name;
$user->email = $newUser->email;
$user->save();
}
});
$newUser = (array) $newUser;
return view('user.index', $newUser);
});
Try:
view('user.index', compact('newUser'));
Well just wondering, why don't you use a controller and make your code more explicit so that coming back to your coding 6 months from now would be easy for you to understand.
Anyway, if your using the Auth facade, you should be able to use
Auth::user()
inside your view to retrieve it or try seeing the available method of the OAuth class. Or if you want to keep your code as it is try
return view('user.index', compact('newUser'));
Is there an efficient way to do this? Options I've looked into:
Checking the session container in the layout
Checking the session container in the module onBootstrap functions()
Handling the session container individually in each Controller/Action
Ideally I'd have this check once, is there any correct way to do this?
Something along the lines of...
$session = new Container('username');
if($session->offsetExists('username')) {
//check im not already at my login route
//else redirect to login route
}
}
You can use below code inside each controller
public function onDispatch(\Zend\Mvc\MvcEvent $e)
{
if (! $this->authservice->hasIdentity()) {
return $this->redirect()->toRoute('login');
}
return parent::onDispatch($e);
}
You can also check session on module's onBootstrap function(), you need to match the route using zf2 events:
$auth = $sm->get('AuthService');
$em->attach(MvcEvent::EVENT_ROUTE, function ($e) use($list, $auth)
{
$match = $e->getRouteMatch();
// No route match, this is a 404
if (! $match instanceof RouteMatch) {
return;
}
// Route is whitelisted
$name = $match->getMatchedRouteName();
if (in_array($name, $list)) {
return;
}
// User is authenticated
if ($auth->hasIdentity()) {
return;
}
// Redirect to the user login page, as an example
$router = $e->getRouter();
$url = $router->assemble(array(), array(
'name' => 'login'
));
$response = $e->getResponse();
$response->getHeaders()
->addHeaderLine('Location', $url);
$response->setStatusCode(302);
return $response;
}, - 100);
where $list will contain the list of routes not to be processed:
$list = array('login', 'login/authenticate');
As checkout in ZFcAuth plugin in following urls, I found some code for check & redirect.
if (!$auth->hasIdentity() && $routeMatch->getMatchedRouteName() != 'user/login') {
$response = $e->getResponse();
$response->getHeaders()->addHeaderLine(
'Location',
$e->getRouter()->assemble(
array(),
array('name' => 'zfcuser/login')
)
);
$response->setStatusCode(302);
return $response;
}
This code chunk show the way to validate/redirect. However they are not in-build way as ZF2 only provide components. You can also use other plugins like ZfcUser, ZfcAcl, ZfcRABC which provide all functionality.
link : https://github.com/ZF-Commons/ZfcUser/issues/187#issuecomment-12088823 .