laravel how to except a certain global middleware on specific route [duplicate] - php

I'm new to Laravel and I am handed an existing application that is composed of two parts:
1 - An admin backend built on Laravel and uses Vueify
2 - The frontend website built on next.js and uses react components
The admin part communicates with Laravel using the "web routes" but also uses the "api routes" as well since the vue components make AJAX requests using those "api routes".
I am now tasked with "connecting" the frontend part to the laravel app. The frontend part will be using AJAX as well to communicate with laravel but I was told I should not use the same "api route" that is used by the admin backend because that has a lot more privileges that should not be accessible by the frontend. Basically it's a security risk and that I should somehow separate the two.
I'm not actually sure which term to use.. I initially thought it was called "channel" but I see that channel is one of the 4 "ways" of connecting to laravel (the other 3 being web, api and console). So I think routes is the term to use and forgive me for the double-quotes.
I have made a simple diagram to show the structure I mean. What I need to know is is there a way to create a second api route that would be used exclusively by the frontend and would include only a limited set of priviledges. I imagine something like /frontapi/ or /webapi/ as opposed to /api/ which is used now by the backend.
Thanks a lot for your help and please correct me if I am using wrong terminology.
EDIT
Thank you all for answering the part regarding separating the route prefix and the api route files.
One part of the question that I realized late that I hadn't made clear was the importance of separating the API Keys for both APIs since I think that is the main security issue and what would really make then two individual API "Channels or ways". I think that is one reason why I was confusing about the terminology because "way" sounded to me more separate that just a "route". I've also edited the question to reflect that. Thank you again for taking the time to help.

You can decompose routes in as many files as you want, you can also give each file its own prefix (like how api.php routes start with /api)
The modification need to be done in App\Providers\RouteServiceProvider
//in map() add $this->mapApiTwoRoutes()
public function map()
{
$this->mapApiRoutes();
$this->mapApiTwoRoutes();//<---this one
$this->mapWebRoutes();
}
//now add the method mapApiTwoRoutes
protected function mapApiTwoRoutes()
{
Route::prefix('api2')//<-- prefix in the url
->middleware('api')//<-- api middleware (throttle and such check App\Http\Kernal.php)
->namespace('App\Http\Controllers') //<-- you can modify the namespace of the controllers
->group(base_path('routes/apiTwo.php'));//<-- file containing the routes
}
And that's it.

You need to define a new route file, firstly add a new entry $this->mapApi2Routes(); in the map() function in app\Providers\RouteServiceProvider.
Then add a new function in that file, basically copying the mapApiRoutes() function, call it mapApi2Routes(). You can use different middleware etc. for the new file.
The last step would be adding a new file api2.php in the routes folder.

Related

Symfony2 - Load all routes in controller (without rebuilding cache)

I'm trying to create a Symfony form with a ChoiceType field that contains all the routes currently available. This form has the purpose of adding these routes to a module in our backend. I've already created a Module and Route entity. These are used to render the correct navigation structure for the users working on a specific module.
I've used Router#getRouteCollection() inside the form controller, using this the routing cache will be rebuild on every request to the page.
I was thinking about a command that uses this method and adds all the routes to the database. However this means that every time a route is added, this command needs to be executed as well. This seems like a step too much for such a simple task.
What would be the best practice to load these routes inside the controller? And would it be possible to do this without:
Rebuilding the cache every request when using getRouteCollection()
Executing an extra command every time a route has been added to the Collection
Creating a controller that uses getRouteCollection() and save the results in the session, cache etc.
Thanks for thinking with me.
Kind regards
I am not exactly sure for what use-case you need this routes but another problem will be that there are routes that you probably dont want to have in your routes list because they are for example routes from the profiler or AJAX routes. So a better approach could be to maintain your own list of routes in a database table where the user can make his choice from.

Use cases for generated URLs in Symfony2?

Coming from a straight PHP and Drupal background, I am recently learning the Symfony2 framework. Currently I am in the routing chapter of the book. This is probably a simple question.
What are some real world use cases for why one would want to generate URLs in a Symfony app? I understand the code but I'm having a bit of trouble determining its practical applications.
I'm referring to this section should you need a refresher.
As always, thank you!
P.S. Symfony is amazing. :)
Basically, you need to generate a URL whenever you need to link to anywhere in your application.
Let's say that you have an application that needs to manage some users. This means that you will probably have URLs like /user/create, /user/edit/(user id) and /user/remove/(user id).
Whenever you display a link to edit a user you need to know on what URL you can find the page that allows you to edit a user. So you need to link to /user/edit/(user id). One solution would be to have this as a fixed link so that in your code you could just write
edit this user
But what if you want to change this URL scheme? Let's say someone is unhappy with the term "user", after all the humans managed by this system are not only users, they are actually "person"s! So now you need to change all the URLs containing "user". Probably there are quite a few places in your app where you have had to hardcode these URLs and now you will need to find and change all of them. Eugh.
But fear not, for Symfony routing comes to the rescue!
Instead of hardcoding these URLs, we can simply let the Symfony router generate them for us. This means that we first need to tell Symfony which routes we have, e.g. by adding the following YAML code to our routes config file:
user_edit:
path: /user/edit/{userId}
defaults: { _controller: AppBundle:User:edit }
requirements:
userId: \d+
This tells our application "Okay, whenever somebody requests a page that looks like /user/edit/{userId}, then you need to call the editAction method in our UserController class in the AppBundle namespace and you need to pass the userId as a parameter. Oh, and also you should only call the controller if userId is a valid integer with at least one number."
So this is how Symfony knows how to map URLs to controllers. But the goodness that comes along with it is that we can use this information for the reverse way as well.
Usually, in our application we do not really care about what the URL looks like for a certain action we want to perform. All we know is that when clicking a certain link, then the browser should jump to a page that allows me to edit a user. And since we just defined a route that takes us right there, we can have Symfony generate the correct URL to achieve just that.
So in your view you can now discard the hardcoded URL from earlier and instead replace it with a route generated by the Symfony router:
edit this user
Now whenever you need to change what the URL actually looks like all you need to do is edit your routing config and not a lot of separate views.
Because, imagine you want to change a given page URL and you've hardcoded it in 10 Twig templates. You will have to modify all these files. On the opposite, when using the routing component:
You would only have to change the URL where the route is defined.
The routing component "takes" care of the current environment you are using (dev, prod...)
Also note that is a bad practice to "switch environment", a typical issue is to hardcode an URL in a Javascript. In this case you can expose your Symfony2 routes in the Javascript by using a bundle like FOSJsRoutingBundle.
I almost immediately realized their use and now I feel silly. :) For those who stop by this question in the future:
Notes about Generating URLs:
Similar to the Drupal l() function, sometimes you need to generate links inside your application based on a variety of parameters.
You don't always want to hardcode your links in case you decide to change paths sometime down the line.
In summary: Think of this as an alternative to using straight anchor tags with href elements all over the app and, instead, keeping things dynamic.
Use case
In the project I'm working I use generateUrl to redirect the user
after creating, editing an entity.
For example after creating a Service entity, I redirect the user to the view
of the just created Service.
Controller
return $this->redirect($this->generateUrl('myentity_view', array('id'=> $id)));
Additional note
In twig files, you can use the path function which call the routing component and generate url with given route name and parameters.

Codeigniter - find out if class was called directly

I am attempting to create a controller that can detect if it is called from another controller in the application.
If it called directly via the URL, however, I need to know so I can perform some other actions.
i.e.
cheese/modulename calling potato/modulename is different to someone accessing site/cheese/modulename via URL - and I need to be able to pick up on this and act accordingly.
I am aware of:
$this->router->class
but it will not work as I may have the same named class in another module (HMVC pattern as an FYI) that may want to call this controller (cheese/modulename calling potato/modulename as an example would return 'modulename' - so I can't use that as a check to see if it was called by itself.)
I basically need a check for:
controller was called via another controller = true / false
can anyone tell me how (or if I am being thick!)
I am doing this in the __construct() just in case your solution will have a problem with that (can't see why but you never know!)
EDIT
Thank you to Mohammad Walid for his answer.
For clarity the structure is
CLIENTS
MODELS
CONTROLLERS
- Client
- Api
VIEWS
JOBS
MODELS
CONTROLLERS
- Jobs
- Api
VIEWS
I will be calling the API from Client - but may also call it from another API (possibly) That may be
In another Module
For Example the CLIENTS Api might get called from the JOBS Api Controller (I have no intention of doing this at present but it may be a possibility under different scenarios I haven't forseen and want to make it future-proof so I don't have a massive refactoring job in the future.)
You can try this:
function is_called_via_url($controller_object){
return $this->uri->segment(1) === get_class($controller_object);
}
and in your controller:
if(is_called_via_url($this)){
//do something
}
I'm not quite sure if passing $this as an argument in the constructor will work, but it worth try.
Reference and a hint from MonkeyZeus's comment.
From the comments there seems to be no way to do this without using debug_backtrace($options, $limit)
However the work-around I have ended up doing is to add a 'flag' within the authorisation module (which is called before all controllers)
The flag defaults to false.
If a controller from within my application calls the API page I turn this flag to true (is_application = true - I am currently just manually pasting this into the __construct of any controllers in my application that need to talk to my API)
I can then just do a simple
if(!is_application){
//this was called directly from the URL not from within the application
}
from within the API controller.
Hopefully this will be helpful for others who are attempting this sort of thing and once again thank you to the people who took the time to comment / answer.

Kohana 3.3 - dynamic menu creation with rights management possible?

I would like to use Kohana 3.3 as a replacement for my self written "framework" which I am currently using for my webapp. Could you please tell me if it is possible to fulfill the following requirements and how to achieve this?
My app consists of several controllers, which I want to access via menu. This menu should be dynamically created, so that a newly created controller will show up immediately. Additionally the menu should exclude controllers which are not accessible for the currently logged in user.
Each controller must be able to check the user's role before executing an action (e.g. global admin, controller-specific admin, regular user). Depending on this role each controller must be able to permit or prohibit access. (Thought about a group membership based method).
I want to use a separate template (as far as I know aka partial) for the menu and for each controller output. They all should be merged with a "frame" template (with header, footer,login info, etc.). I saw there is a special controller for templates (template_controller iirc) - is this the right one to use as my base controller? And should I create a base controller which manages my "template" and nest the other controllers in it somehow?!
Additionally it would be nice if each controller had the ability to recognize the current request as ajax or non-ajax and adjust the rendering accordingly (in most cases "rendering" the whole site again is not desired with ajax).
I would be grateful for every answer!
Thanks in advance.
Yes, but you'd have to search for the controller files yourself AFAIK.
Yes, see before(),
2.1 If you want to keep it in one place you would only have to write a little extra something to specifiy which action requires what privileges. Check out Kohana's Request class for some nice stuff you could use for this (I'd say take a look at the url, uri and request methods, I don't know by hard what exactly they do)
2.2 You could also do it on a per-controller basis; e.g. Controller_Admin could do the following ugly one-liner (check snippet for 2.2 below). I suggest splitting it up a little bit though, e.g. giving your base controller a protected $_user variable which it fills in it's before() method and then use $this->_user instead of Auth stuff.
It's Controller_Template but yes, you got that right ;)
Like this? Request::$current->is_ajax() (http://kohanaframework.org/3.3/guide-api/Request#is_ajax)
Snippet for 2.2:
if ( ! Auth::instance()->get_user()->has('role', ORM::factory('Role', array('name' => 'admin')))
throw new HTTP_Exception_403('Permission denied!');

Cakephp different classes for requests

I have an application in Cakephp. In my front-end, it only responses for one request and I have used usual CakeRequest() class, and in my back-end, as far as using extjs, I have defined another Request and Response Class for multi-requests and multi-responses. but I have problem in distinguishing between them. I mean where and when one of them is executed. the default cakephp index.php file for front-end is
$Dispatcher->dispatch(new CakeRequest(), new CakeResponse(array('charset' => Configure::read('App.encoding'))));
and for back-end is
$Dispatcher->dispatch(new TestRequestCollection(...
but I don't know the if clause between them.
To what if clause are you referring to?
CakePHP is not designed to use different request classes in the index.php. Not sure what you are doing here. You might want to go the same route I went with Bancha and create a second frontend controller which does different a dispatching.

Categories