I have the following filter:
Route::filter('security', function()
{
//do security checks
//send to my gateway controller and test() method
});
Route::when('/gateway', 'security');
The above does not seem to work, where am I going wrong?
What should I put inside the filter to load my test method in my gateway controller?
How can I test that the call is an ajax call using:
Request::ajax()
In order to make this code work you need to have a route /gateway created
Route::filter('security', function()
{
if(Request::ajax())
{
//do security checks
return Redirect::action('GatewayController#test');
}
});
Route::when('gateway', 'security');
Route::get('/gateway', 'GatewayController#test');
Note that the slash / has been removed in Route::when('/gateway', 'security');.
This is because the Router adds a slash when checking registered patterns against the path info for the current request
Related
Is it possible to globally set a listener on API calls made with Axios in Vue? The Laravel back-end has middleware set up on each endpoint that will either give the requested data or return a message saying that they need to check their messages. My goal is to capture that message and redirect the user to the page to view their message. I can't think of a way to do this other than setting something on each function that checks for the message and responds accordingly. There are hundreds of functions and that it wouldn't be a clean solution.
Any and all recommendations are welcome!
Using Axios Interceptors you can do something along these lines:
this.$http.interceptors.response.use(response => () {
// Redirect to a new page when you send
// custom header from the server
if (response.headers.hasOwnProperty('my-custom-header')) {
window.location.href = '/another-page';
}
// Or when you get a specific response status code
if (response.status === 402) {
window.location.href = '/another-page';
}
// Or when the response contains some specific data
if (response.data.someKey === 'redirect') {
window.location.href = '/another-page';
}
// ...or whatever you want
});
Currently I'm writing a Laravel 5.6 REST api. Now I want to secure my endpoints:
Each user in my application has a role. Based on that the user should be able to access some endpoints and otherwise should get a 403 error. For this I would like to use Policies because, when used as middleware, they can authorize actions before the incoming request even reaches my route or controller.
I declare my endpoints like this:
Route::apiResource('me', 'UserController');
My problem now is that if I want to use Policies as middleware I have to specify the (HTTP) method like this middleware('can:update,post'). How should I do this when I use apiResource in my route declaration?
BTW: Currently I have written a FormRequest for each method (which is a pain) and do the authorization there. Can I simply return true in the authorize method after switching to Policies middleware?
Since you are using FormRequest::class to validate the request data, it is best practice to first check is the user is authorized to make the request. For Laravel 5.6 the cleanest solution would be to specify each policy manually in the __construct() method of your resource controller.
public function __construct()
{
$this->middleware('can:viewAny,App\Post')->only('index');
$this->middleware('can:create,App\Post')->only('store');
$this->middleware('can:view,post')->only('show');
$this->middleware('can:update,post')->only('update');
$this->middleware('can:delete,post')->only('delete');
}
If your were validating form data inside your controller instead of using FormRequest::class, a cleaner solution would be to also authorize the user inside the controller.
public function store(Request $request)
{
$this->authorize('create', Post::class);
// The user is authorized to make this request...
$request->validate([
//Validation Rules
});
// The form data has been successfully validated...
// Controller logic...
}
Since Laravel 5.7 you can do all of this using one line of code on your controller's __construct() method.
public function __construct()
{
$this->authorizeResource(Post::class, 'post');
}
You can define route groups, routes that have a common behaviour (middleware, prefix etc. ).
The following should work:
Route::middleware('can:update,post')->group(function () {
Route::apiResource('me', 'UserController');
//more routes
});
You can prefix routes as well:
Route::middleware('can:update,post')->group(function () {
Route::prefix('users')->group(function () {
Route::apiResource('me', 'UserController'); //Translated to ex: /users/me
Route::prefix('books')->group(function () {
Route::apiResource('{book}', 'UserController'); //Translated to ex: /users/me/book_1
});
});
});
P.S: I haven't used resources before but it should do the job
I am looking for best practices with AngularJS:
I need to share a json ajax response between nested controllers.
Controller1->Controller2->Controller3
Right now I have a working version that simply sets a $scope.variable with the response in controller1, and the other controllers access it by calling the same variable.
I have tried creating a global service, but the problem is I make the ajax call in a controller, and before the ajax call is finished, the global variable defaults to null for all the other controllers.
I am just trying to understand what best approach is in this situation.
Thanks
Create publisher/subscriber service or factory and subscribe methods from your controller2 and 3 to data change. Just like this:
angular
.module('')
.factory('GlobalAjaxVariable', function() {
var subscribers = [];
function publish(data) {
callbacks.forEach(function(clb) {
clb(data);
});
}
return {
setData: function(ajaxData) {
publish(ajaxData);
},
addSubscriber: function(clb) {
subscribers.push(clb);
}
};
});
You can put the value in $rootScope.variable and after access it from any other controller (as $scope.variable)
I’m creating a SaaS app (who isn’t?) and like most SaaS apps, I’ve taking the account subdomain approach. My routes file looks like this:
$router->group(['domain' => '{account}.example.com'], function($router)
{
$router->get('/', function()
{
return response('Hello, world.');
});
});
I then decided to add some route parameter validation and binding in my RouteServiceProvider file:
public function boot(Router $router)
{
parent::boot($router);
$router->pattern('account', '[a-z0-9]+');
$router->bind('account', function($subdomain)
{
return Account::whereSubdomain($subdomain)->firstOrFail();
});
}
However, these don’t actually seem to be triggered. I know this as I can put something like dd('here?') in the bind call, and it’s never triggered. I can also reduce my account pattern filter to something like [0-9]+ and it’ll still be matched if I include letters in the subdomain.
What am I doing wrong? How can I get route patterns and bindings to work on variables in the domain key of my route group?
Turns out moving any bindings to the map method (instead of the boot) method works, and pattern filters need to go inside the route group definition, like so:
$router->group(['domain' => '{account}.example.com'], function($router)
{
$router->pattern('account', '[a-z0-9]+');
$router->get('/', function()
{
return response('Hello, world.');
});
});
Not ideal, so any one knows how to have filter patterns be kept in my RouteServiceProvider class so they’re not littered in my routes file, then would love to hear from you.
I have a standard CI web app, but I've decided to get the chaotic javascript in order using backbone. I had a whole pile of serialized forms/jQuery AJAX requests to various controller methods: authenticate, change_password, register_member, request_new_password, etc.., and don't quite understand how REST works instead. I'm using Phil Sturgeon's REST library for CI https://github.com/philsturgeon/codeigniter-restserver
Should every backbone model have a different api url? And what am I supposed to actually call the controller methods?
<?php
require(APPPATH.'/libraries/REST_Controller.php');
class RestApi extends REST_Controller
{
function get()
{
But it just 404s.
I just don't get how to replace the routing to fifty of my old methods based on a handful of HTTP methods. Does the name of the backbone model need to match something on the server side?
You have to name your functions index_HTTPMETHOD. In your example it would be:
class RestApi extends REST_Controller {
// this will handle GET http://.../RestApi
function index_get() {
}
// additionally this will handle POST http://.../RestApi
function index_post() {
}
// and so forth
// if you want to POST to http://.../RestApi/somefunc
function somefunc_post() {
}
}
the url-attribute of the model should match the server-side 'url' which returns the JSON that will make up the model's attributes. Backbone.js has default functionality to this, which is to match the model's collection url with it's id attribute. The collection url requirement can be foregone by overriding the urlRoot -function, in order to operate model's outside of collections.
If you want to be independent of the id -attribute as well, you sould override the url -attribute/function to provide your own url that matches to the model on the server, like this:
url: 'path/to/my/model'
or
url: function() { // Define the url as a function of some model properties
var path = this.model_root + '/' + 'some_other_url_fragment/' + this.chosen_model_identifier;
return path;
}