Greeting, guys
I'm currently working on an authorization function on NestJS for my side project and use Casbin to apply my policies and permissions for users.
One step is that I want to provide an array of [handler name(ie. getAllUsers), api route(ie. api/v1/users), method(ie. get)] as an policy list while app bootstrap which will be wrote to database.
Getting api&method list is not a problem but question is I could't find a solution to get all of the handler name while app bootstrap
Do you have any experience or thoughts on it? would be much appreciate for your valuable sharing.
for the api&method way, I took this post as a reference and it worked well.
for handler name, I was thinking about the ExecutionContext from NestJs but it seems to be working in an interceptor while there is a request
** for those who might wonder why I need to put handler name in my polices, here is the way I implement the Casbin rule.
list a basic policies for all my apis.
create an role and add policies to it by handler name.
appoint the role to the user(whatever the user is) and the user can only access the allowed apis to perform.
Related
I am making a project using nestjs.
I want to prevent users with a specific role in all controllers except for one controller.
I know, add #UseGuard(RoleGuard) #Role(UserRole.Guest) to each controller.
But I have a lot of controllers, and more will be added over and over again.
Is there a way to do it all at once like middleware?
thank you!
Could you not have a base controller that you extend and add the decorator to the constructor or something?
Also, check out useGlobalPipes to see if that can help with shared request logic.
Summary
I am seeing a lot of contradictory architectural examples of a REST API in my work and keep getting different opinions on the subject.
I am familiar with the principles of REST and seeing as each endpoint points to a resource followed by a verb such as /project/create project/123/read.
Following the MVC pattern assuming I have a controller that is responsible for updating a project resource:
router.put("/project/:id/update", ProjectController.put)
First question:
Should this route be responsible for all updates to this resource, in example, assuming different features on my client like marking a project as finished or changing it's title are separated and might not have anything in common for the user. Ending up with the route described above, or should there be something like this:
router.put("/project/:id/mark-as-done", ProjectController.markAsDone)
router.put("/project/:id/update-info", ProjectController.updateInfo)
Second question:
Assuming I want to create a notification resource if a project is created/updated/deleted. Since the notification is a resource on it's own I am not sure how to go about this, but what I assumed and was taught is to use another callback:
router.put("/project/:id/update", ProjectController.put, NotificationController.create)
Third question:
Could I use the same controller to read all resources or just one, for example:
router.get("/project/read", ProjectController.get)
router.get("/project/:id/read", ProjectController.get)
Making the logic in the controller method determinate if it will return all projects or just one. Or should it be separated into different methods?
I would define APIs like this:-
CRUD for Project entity
create- router.post(/projects)
update:- router.put(/projects/:id)
delete:- router.delete(/projects/:id)
read:- router.get(/projects) and/or router.get(/projects/:id)
You can define all above routes in ProjectController.
Regarding Notification entity you can define as follows
read:- router.get(/projects/:id/notifications)
The same can be applied to PUT, DELETE, POST
Here is a good article defining rest guidelines https://stackoverflow.blog/2020/03/02/best-practices-for-rest-api-design/
I have a resource /cars and the endpoint in angular defined as
$resource('/cars/:carsId');
to GET all cars and a specific car.
At the server level, I have also added a middle-ware to check that carsId is always a valid MongoID.
Now I want to define another endpoint to GET all redcars.
My initial though was to add another resource like
$resource('/cars/redcars');
but this does not work since at the server level, my middle-ware will through an error because redcars is not valid MongoID.
My question is what is the best approach in this case ?
I can add a logic at server to check if the MongoID is invalid, but, if the value is redcars then return all redcars.
or there is a better way of doing this.
Thanks
pkpk
Typical patterns are:
use query parameters, as in, /cars/search?color=red
use /cars/types where the /cars/types/:color can be applied
An excellent resource for design patterns in API design is the Apigee API guide. NOTE: I am not endorsing Apigee by recommending their guide; I simply find that this ebook has many useful patterns collected in one place.
I am totally new to Action HeroJS and I was wondering how can I restricted users to access my action herojs rest API, url from the browser?
I have even put the route as POST, but it is still accessible by get method?
Just like in java when we specify a rest api as post, it will not be accessible by get or browser url?
How can I accomplish this?
Edit:
Contacted the Action Hero, on github, they were pretty helpful, the solution was:
in web.js, put simpleRouting : false, and it should resolve the Issue.
Before you could access a post routed action, from the URL but after doing this you cannot!!
accessing a POST using get will return you a 404.
Thanks #Evan
Regardless of your language/framework, all routes are able to be hit by anyone, unless you block them at load-balancer or similar level.
Rather than thinking about the problem as "how to block" access, you should be thinking about the problem like "how can I ensure that this user is authenticated to use this route". Using things like cookies or tokens is the way to go.
You can use actionhero's middleware to apply access rules to specific actions, and return errors to the use if they aren't allowed.
Here's an example project that does these types of things:
Actions for dealing with the session: https://github.com/evantahler/actionhero-angular-bootstrap-cors-csrf/blob/master/actions/session.js
Middleware which uses that session data for access: https://github.com/evantahler/actionhero-angular-bootstrap-cors-csrf/blob/master/initializers/session.js
and finally another action (route/url) which requires the logged-in-session middleware: https://github.com/evantahler/actionhero-angular-bootstrap-cors-csrf/blob/master/actions/showDocumentation.js
I'm actually building a RESTFul API node.js based and I m facing a problem.
The domain code is written, and I m now trying to manage access rights on this application and I dont know how to process.
In fact, I need to allow / restrict a ressource access on a user. Actually, I've thought about storing the rights in an array in the user like this :
{
userName:"foo",
userMail:"foo#bar.com",
userApiRightsAllowed:[
{
uri:"/site/1594656",
verb:"post",
},
{
uri:"/sites",
verb:"get",
}
]
}
In a custom middleware, I check if the user rights contains the req.url and the req.verb.
If it's okay, he can access the ressource. In the other case, he get a 403 FORBIDDEN.
The problem
The problem is when I need to get /sites . I authorized the user to get /sites, but he doesn't have the accesses to look at a site detail like /sites/65982 .
But in my list of sites, he will see all the sites and /sites/65982 in it.
Question
What is the best way of managing access rights on an API at the smallest granularity : the resource and the method ?
How can I do to make my code work, and that the user could see only the sites he's able to look at ?
EDIT : I'm working with a MongoDb database
Thanks in advance
Assuming you're using express (based on the tag), sails.js is a great option for extending the functionality of your app beyond the basic REST functionality that express gives you. Sails has some useful addons for helping with management of roles, users, and permissions:
sails-permissions
sails-auth