Setting Role Based Permission in code when saving new doc in Umbraco - umbraco

I am using Umbraco 7.2.8. When a new Document of a specific type is saved, I am hooking into the ContentService.Saved event and I want to be able to set the Public Access to only allow a specific member group access to it. Just like I would do using the Gui here.
I see in the documentation here https://our.umbraco.org/documentation/Reference/Management/Services/ContentService There are a couple methods like
.AssignContentPermission(IContent content, char permission, IEnumerable userIds)
and
ReplaceContentPermissions(EntityPermissionSet permissionSet)
which both allow me to pass in a list of userIds users that have access but I am interested in setting the membership groups that have access as well as the Login Page and Error Page. How can I do this?

Used to do it like this. I think it still applies:
Access.ProtectPage(false,nodeIdOfPageToProtect,loginPageNodeId,errorPageNodeId);
Access.AddMembershipRoleToDocument(nodeIdOfPageToProtect,"roleName");
Methods are in umbraco.cms.businesslogic.web so make sure you set this for your page
using umbraco.cms.businesslogic.web;
Does that help?

Related

MVC Session for storing user information vs DB call

I have a user details area that is split out on to about 6 different pages (details, contact, preferences, etc). I need to have access to all of the user details after login.
I was going to add the user details to a Session like this after login so that I could access them all from the different pages without having to call the database on each page;
Session["name"] = name;
Session["bla"] = bla;
However I've googled and some people talk about saving the session to a database, which sounds like i may as well not use it. The users may not access every page or require access to all of this information, so it could be seen as a bit needless to add them all to a Session.
Is there a recommended practice for storing user information like this? I also have an ID that needs to be shown on every page. Perhaps something like this is better for a session and the more detailed info pages to keep with their own database calls?
.
EDIT: I am using Umbraco 7.2.8 and am getting the member details from the MemberService. I am worried that it hits the database each time though. My code to get the Member details and also the custom member properties (currently in each controller) is;
// Get the details of the user currently logged in
var profileModel = Members.GetCurrentMemberProfileModel();
// Get the custom properties for the member
var member = memberService.GetByUsername(profileModel.UserName);
model.Firstname = profileModel.Name;
model.Email = profileModel.Email;
model.specialID = member.Properties["specialID"].Value.ToString();
Any pointers would be great!
If you use the built in Umbraco Member service (link 1, link 2) to manage your users, you'll have a relatively simple way to get current logged in member. It's also easy to manage the member profiles with custom data fields and so on. No need to think too much about sessions and such.
Edit: take a look in here - specifically the GetCurrentPersistedMember() method - Umbraco is using caching to save current member
There are three popular ways to store the data in memory
1) Caching
2) Session
3) Static Classes
Out of above three I will always prefer Caching, as numerous articles suggested and I too agree that Sessions are comparatively slow than Caching & Static classes. I would always prefer caching over sessions.
But whatever you use, make sure that you are initializing them at single place, so that all the sessions and caching used in whole application is known to every developer. This will help in code re-usability & reduces the duplication of initializing the same value again in system. It will also help in code-maintainability.

Is there anything out there to help handle "field level" authorization for ASP.NET MVC3?

I know you can use the Authorize attribute to control access to a Controller or ActionMethod... but what about more fine grained control? It seems common to have specific fields be allowed/disallowed based on a user's role, for instance. Maybe on an employee profile the employee can edit his profile information, but only a supervisor can change his job title...
Optimally I'd like to be able to develop views, models and controllers normally and have a configuration page on the website that site admins could then use to configure authorization at whatever granularity is required. In other words the programmers shouldn't worry about it (except for the guy writing/integrating that specific part of the system.)
I can envision DisplayFor and EditorFor checking attributes to render fields as ReadOnly, Hidden, etc... and maybe the attributes get added at run time from an Authorization Provider of some kind.
The question is: Is there a framework or something out there that already does this?
Write a custom ModelMetaDataProvider that will allow you to alter the metadata for each model and it's properties before they make it to the view. The built in helpers will not render a field if it's metadata value ShowForEdit = false or ShowForDisplay = false.
You can utilize a rules engine or some other ACL to manipulate the metadata on each model and property to get most of the behavior your looking for out of the box without touching the built in helpers. On edge cases where you need more control you can write your own helpers and pass more complex data in the metadata.AdditionalValues dictionary.
You can implement security at field level using HtmlHelper. In the following example they used textbox only implementation but it can easily be extended for all type of controls:
http://bartreyserhove.blogspot.ca/2008/12/field-level-security-using-aspnet-mvc.html

Symfony Admin Generator in multi user setup (restricting records in LIST view)

I am using SF 1.2.9 to build a website. I want to use the admin generator to provide admin functionality for the object models I have used (specifically LIST, edit and delete).
I have read the Symfony docs (Chapter 14), but unless, I am very much mistaken, all examples I have come accross so far, seems to be written for a single user environment only. Meaning that the list of records returned to the user is essentially, ALL the records in that table. In a multiuser environment, this is irresposible at best, and potentially, a security threat. It is a necessary requirement to restrict the list of records returned to a user to only those that they own (i.e. created).
Suppose I have a table with (YML) schema like this:
foobar_dongle:
id: ~
title: varchar(255)
info: longvarchar
owner_id: ~
created_at: ~
where owner id is a FK into a user table.
Assume I generate an admin module like this:
symfony propel:generate-admin backend FoobarDongle --module=dongle
Question:
How do I modify the list of records returned to a user in the LIST part of the code generated by the admin generator? As I mentioned above, currently, (i.e. out of the box), the admin generator presents the user (rather naively, I feel), with the ENTIRE set of records for the model being administered. I need to be able to restrict that list somehow, so that I can only return records owned by that user.
This is what I am trying to find out how to do.
I would be most grateful to anyone who can show me how I can restrict the list of records returned when using the admin generator for administration of an object model. Ideally, I would like to be able to specify a custom method that has all the custom 'filtering' logic - but so long as I can restrict the LIST of records a user can see (in admin), to only the records that he is the owner of, that is all I want to be able to do.
If you only want to restrict the returned objects in one or two modules, do this:
Go to the actions.class.php file of your module. There should be no methods by default and the class should inherit from autoModuleNameActions you. Insert the following method:
protected function buildQuery()
{
$query = parent::buildQuery();
// do what ever you like with the query like
$query->andWhere('user_id = ?', $this->getUser()->getId());
return $query;
}
But this becomes unhandy if you do it for more modules. In this case I would advice to create a new admin generator theme.
And if you want to make the query depending on some custom parameter in the admin generator config file, then you have to extend this file. But is not just done with adding a new parameter. You can read this article how to do this.
If you want to know more about the auto generated classes, have a look at this class: cache/[app]/[env]/modules/auto[ModuleName]/actions/actions.class.php.
Edit after comments:
I think you looked at the wrong class. Look here: cache/[app]/[env]/modules/auto[ModuleName]/actions/actions.class.php.
I set up a Propel project to check it and the method that is interesting for you is:
protected function buildCriteria()
{
if (is_null($this->filters))
{
$this->filters = $this->configuration->getFilterForm($this->getFilters());
}
$criteria = $this->filters->buildCriteria($this->getFilters());
$this->addSortCriteria($criteria);
$event = $this->dispatcher->filter(new sfEvent($this, 'admin.build_criteria'), $criteria);
$criteria = $event->getReturnValue();
return $criteria;
}
I also posted the whole content of this class to pastebin. It is a lot, the function is in line 245. Even if you don't find this class, you should be able to override this method like this:
protected function buildCriteria()
{
$criteria = parent::buildCriteria();
// do something with it
return $criteria;
}
I don't know about these criteria objects, so I can't help you with that but I hope the other things help you.
You should use sfGuardPlugin to provide your login/user functionality - it includes user groups and permissions that can be assigned to users and/or groups.
Using security.yml you can then configure which permissions/credentials are required to access individual actions. IE: you can allow everyone to access the list/update/delete actions, but only people with the create permission to access the create page.
The docs for sfGuardPlugin are worth reading:
http://www.symfony-project.org/plugins/sfGuardPlugin
Plus this section from the jobeet tutorial covers sfGuard and also use of security.yml and credentials:
http://www.symfony-project.org/jobeet/1_2/Propel/en/13
And to round off, this page from the book is relevant too:
http://www.symfony-project.org/reference/1_2/en/08-Security (although not sure it covers anything that isn't in the page i linked from jobeet)

ACL on field level in Grails

in our new software project, we have the following requirement: A webpage shall show a set of data. This data shall be editable by some users (assigned to roles, i.e. manager), and only viewable by others. The tricky part is described by an example:
A User-page consists of address data and account information. The addess data shall be editable by the user and the manager and viewable by all users, while account information shall only be viewable by the actual user and the manager.
I have read a lot of information about SpringSecurity. It provides a very good framework to gran permissions on urls and methods and even domain classes. But what I need is field level ACLs. At least, that's what I think at the moment.
So, the question is: How to solve this problem using Grails?
Thanks a lot in advance,
Regards Daniel
Spring Security (Acegi Plugin) is definitely the way to go with Grails.
There is a taglib you can use that will allow a page to be different for different roles such as the following:
<g:ifUserHasRole roles="ROLE_ADMIN">
html code for extra fields
</g:ifUserHasRole>
Me, I'd encode it on the domain class, emulating the way GORM has you annotate the domain classes (static access = [field1: "ROLE_USER", field2: "ROLE_ADMIN,ROLE_USER"] as an example). Then build a method your controller could use to redact them for a given user. That method could use the domain class's annotations to decide how to redact it. Then, metaprogram it onto each of the domain classes the way plugins do.
Similarly, write the opposite method to restrict data bindings of params into the domain class, write your own data binding utility method, then metaprogram it onto each domain class as well.
Then you can just use instance.redact(user) or instance.bindData(params, user) to do what you want, and it's practically declarative syntax.
We have a similar situation and use both the ifUserHasRole tag in the gsp to drive the appropriate presentation and the we have a filter that enforces the rules based on the action being called. For example, on user controller we would only allow the management roles to call save action, or if the user.id is the same as the session.user.id. This seemed to be the best option for our situation.
What about creating an ACL class like this:
class ACL(val entry: Entry*) {
def isAccessAllowed(subject: String, permission: String): Boolean = ...
}
class Entry(val subject: String, val permission: String*)
usage:
new ACL(
new Entry("dave", "read", "write"),
new Entry("linda", "read")
)
(This example is in Scala, because I found it more expressive in this case, but it should be easy to transfer it to Groovy.)
You would then connect an ACL object with the object to be protected.

Passing data from view to action ?? Solution?

I'm trying to send the user id (integer) from a view to the action. If I pass it using routevalues object, the user id will be visible in the browser address bar.
How can I pass user id from view to the action without using aforementioned method??
You can use a hidden input element inside a form. You should generally use POST, not GET (i.e. use a form, not an a href) for anything that is changing data in your system.
The user id is commonly inferred from your authentication mechanism (cookie etc), so for the current user you shouldn't need to pass it around.
The main time you would include this in the request is when the page being displayed relates to users - and in particular where you (or an admin) want to browse other users records - then you might use "/users/current/orders" (use the cookie) or "/users/12345/orders" (and you should verify permission to browse 12345).
Note that if you use /current/ or similar, you should ensure it isn't cached between different users - so in many ways it is simpler to just show the user-id and to heck with the url; just go for the simple "/users/12345/orders" case.
What is the scenario here?

Resources