Background: Completely new to MVC2. Has C# experience, but limited web experience.
I need more fine grained access than simply assigning a Role to a user. The user may have the role at 0+ points in a tree.
/
/Europe
/England
/France
/USA
For example, a user might be moderator of all forums under "Europe" and have access to posting news in France.
The two example controllers have actions as these:
ForumController:
public ActionResult DeletePost(int id) { ... }
NewsController:
[HttpPost]
public ActionResult Post(int treeID, ...) { ... }
How should I approach this? From what I gather Membership+RoleProvider cannot do this level of fine-grained control.
Previously I have written custom user/role/auth system which supported all this, but it was incompatible with "the standard" controls such as LoginView.
The goal would be to have roles allowing access like so:
NewsAdmin
Add news
Edit news
Delete news
NewsPoster
Add news
Therefore, the Post action of News controler should check: Does user have "Add news"-access where he is trying to post?
I would really like to somehow specify this using attributes, so the actual action code could be cleaner and just assume that the caller has appropirate access.
Hope the question makes sense, and I can get some pointers on where to read.
(Oh, and I'm sure this question has been answered in some variant before. I just can't seem to find it. I won't mind single-link replies, if you feel they might be helpful to read)
I think you're being too quick to dismiss the role provider. If a user had a role called NewsAdmin_Europe_AddNews that would pretty much answer the question, wouldn't it?
Once you've made your authentication scheme work with the role provider, you need to tie that into MVC. Subtype AuthorizeAttribute and override AuthorizeCore. Warning: Your code here must be thread-safe and re-entrant. Call base.AuthorizeCore and then test for the specific role based on the URI/query (you won't get route values since this can be served from cache, bypassing MVC altogether).
This is some work, but will be more secure in the end than trying to reinvent membership.
Related
I'm creating an API, I have a user that I can request by calling:
/api/request/user/{id}
This works fine.
Say each user had a set of skills, could be one skill or 100.
I want to get all the skills for a specific user.
Would I be super specific and make it so that you'll have to call:
/api/request/user/{id}/skills
Or does this:
/api/request/skills/{id} (where {id} is the user's id)
suffice?
Is there a REST API standard I should be following or is it flexible ?
Any advice is highly appreciated, Thank you.
As skills is user's property, let's consider it as sub-resource. Getting sub-resources is based on nesting URL (hierarchical way), so /api/request/user/{id}/skills would be great!
In /api/request/skills/{id} case id should be an identifier of skill to make your API intuitive.
Also remember about naming convention. Be consistent, your skills resource is plural so let's rename user to users.
So, to sum up
/api/request/users/{user_id}
/api/request/users/{user_id}/skills
/api/request/skills/{skill_id}
would be nice.
I am working with GWT / RequestFactory and a set of customer requirements regarding permissions. Let me explain a basic example:
Every user is assigned to a company. Every user should be able to edit company's core data - but only e.g contact information, website etc. Security-relevant ones like BIC/SWIFT, IBAN, Company name and so on can only be changed if the user has a certain permission XY.
So far so good, on the client side I can check the permissions and disable those fields the user is not allowed to edit. But what would be the most elegant way to ensure on the server side that those fields have not been set without permission?
My problem is that I cannot track changes on the server side. Having #PreAuthorize on every setter is not an option too, because it would end in an authorization-massacre in each and every entity.
At the moment I am following a workaround: every field that is secured / depends on a given permission is passed as an argument to the entity-method and is excluded from the proxy. That way, values cannot be set using the proxy and I can check in my server code if the user has permissions. If not, nothing happens. If user has permissions, I set the values manually. But that produces a lot of boilerplate-code and ugly method signatures because the number of values passed to the method could get large.
I hope you understand my issue. I'm looking forward for your opinions and tips. Thank you in advance.
Well, you can receive many answers (different each other), and all of them could be right, so, at the end is your call. Wait for others answers. I am going to give you the approach that I followed (and it worked pretty well). :D.
Under my opinion, the server should do less as possible, so keep the logic for allowing modify each param on the server I think it is not a scalable solution (if your system has 1M users modifying everything at the same time, will your server work fluent?). I prefer let the client do the job (like Roomba :D).
For solving that problem, in our system we implemented an Access Control List solution. You can store in your db, on each user entity, a list with granted permissions. So, when that information arrives to the client (after user's log in, for example), you can get them, and show the fields that he/she is allow to modify.
Something like:
if (canModifyPersonalDetails(user.getAcls(), ...) ) {
//show labels ...
}
if (canModifyBankDetails(user.getAcls(), ...) ) {
//show labels
}
You can not avoid server call for log in, so it is not a big deal send the extra information (think about the ACLs could be simple list of integers 0 means personal details, 1 bank details....).
If you are dealing with very compromised information and you prefer do some stuff on the server, in that case probably I'd set up a security level, when you are persisting/updating your proxy, I'd do something like:
if (isAllowForPersonalDetails(user.getSecurityCode()) {
//update the modified personal details
}
if (isAllowForBankDetails(user.getSecurityCode()) {
//update the modified bank details
}
user.update();
I am a big fan of clear User GUI's, and a very big fan of let the server free as much as possible, so I prefer the first option. But if you have constraints for modifying user entity in db, or you prefer do not modify your views, or any constraint with security, maybe the second option is the best one for you.
Hope that helps!
I want a teacher capability to check the whether the login user is a teacher?
If teacher, I want a different Home Page i.e, my custom page
If student, a different page
Could anyone help ?
What you want to do is use the has_capabilty() function. That is the way you should pose the question. Does the user i am looking at have the capability to see this page. Moodle is all about context and in one context the user may have a different capability than another. Hence, to ask "if a user is a teacher" is the wrong question.
Example of implementation (using moodle 1.9)
if(has_capability('block/my_history:userview', get_context_instance(CONTEXT_USER)) ){
$this->content->footer = 'Manager View';
}else{
$this->content->footer = 'Non Manager View';
}
See this forum discussion for more understanding http://moodle.org/mod/forum/discuss.php?d=70739
Notice the comments by Tim Hunt in this post http://moodle.org/mod/forum/discuss.php?d=126223
It takes a bit of learning, but it works well once you get your head around it.
Good luck
I'm new to ZF and need to create multiple login views for each of my 3 user types, employees, employers and admins. Should I use the indexcontroller to serve up the login for the employees and create separate controller classes to handle the employer and admin login pages? How might I utilize JQuery to direct my employer and admin users to the correct login page from the index view?
Thanks much:)
I can give you 2 options.
Modules
Split your Application into logical segments called modules, for those 3 groups each group will receive its own Module.
Each module mimics the well known standard "Application" structure:
module
Controllers
Models
etc
ACL
http://framework.zend.com/manual/en/zend.acl.html
You check which type of user is currently logged and decid via "if()" statements which view should be rendered.
Custom view rendering is done as described by "Lobo":
via
$this->_helper->viewRenderer->setRender('view-name');
If you don't have any user session data, I mean, if you absolutely do not know of which kind the user visiting your page is you simply have to serve 3 links to either a different module or different controller or to one and the same controller but passing the user type as param.
Examples:
Link to module: /modulename/controllername/actionname/
Link to certain controller: /emplyeecontroller/login
Link to general controller handling different params: /logincontroller/login/type/emplyee
There are many possible solutions to achieve your desired aim.
You have to decide which one fits the most into your project.
I would say that this is a bit to open ended to answer in a good way, but I'll try to fill in the blanks with my imagination and give you an answer. I don't use JQuery so I can't give you an answer there unfortunately.
If this is just to handle login I would guess that the logic is more or less the same (and even if it isn't the logic should be in models anyway), and you just want to change the visual appearance, so then you could use the code
$this->_helper->viewRenderer->setRender('view-name');
This code will render the view called /application/views/scripts/controller/*view-name*.phtml by default. Thus you can get whatever variable you use to distinguish the different users and give them the right view.
If there's more differences than just the visual I would probably use different actions within a loginController or something like that.
Then I would use standard indexAction (and thus the view index.phtml as default) for the normal employees, and on that page show some kind of text like "Not an employee? Go to the employers login instead". Employers are then directed to login/employer or something like that which by default will call the employerAction and use the employer view. And then you do something similar with the admin login. the controller will then look something like this
<?php
class LoginController
{
public function indexAction()
{
/*Do login stuff here*/
}
public function employerAction()
{
/*Do login stuff here*/
}
public function adminAction()
{
/*Do login stuff here*/
}
}
Lastly, if there are major differences between how the different users interact with your page, you might consider looking into modules.
You can find all this information at http://framework.zend.com/manual/en/manual.html
I have delete links in my Asp.Net Mvc2 application.
/{controller}/Delete/{id}
It seems using link to delete has a security risk. Don’t use Delete Links because they create Security Holes
I found this Implementing RESTful Routes & Controllers in ASP.NET MVC 2.0 but I am not sure how to implement a simple delete functionality using the new HttpDeleteAttribute class.
Are there any examples on deleting, the RESTful approach?
The RESTful approach to a Delete is to send enough information to identify the resource and use the HTTP command DELETE (or some alternative for web pages). But all of that is detailed in the article, so I don't think that's what you're really asking.
If you mean "What do I do instead of a Delete link?", the answer is usually to go to a "Are you sure you want to delete Product 8496?" form where the button's action POSTs the delete request. That form can either be on a new page or a modal popup, or both if you want to combine usability and accessibility.
It's a (more of) a security risk if you dont use the [HttpPost] attribute on the controller.
Besides that, your approach isn't a restful one.
The idea is that you have just one Url that can be passed different Http Verbs which are implicit
Return all: /Product/ [HttpGet]
Return One: /Product/43 [HttpGet]
Add : /Product/ (Product info in form post) [HttpPut] or [HttpPost]
Delete: /Product/43 [HttpDelete]
You can do this using MVC in the standard form or JQuery
And to answer the question:
Add a delete link like this Delete Product but hook into it using the JQuery live events so that it hijacks the click using .preventDefault, then call the url as an ajax request with a DELETE verb.
Need more help let me know