Is there a way to set all members of a group to be superuser in django? - django-admin

In Django, I would like to set all members of a group (administrators) to be superuser. Is there a way that I can do this so that new members of the group are automatically made a superuser?

You may be able to do this using signals. You can get the point after which a user has been added to a group and make that user a superuser if they are in the administrator group.
from django.contrib.auth.models import User, Group
from django.db.models.signals import m2m_changed
from django.dispatch import receiver
#receiver(signal=m2m_changed, sender=User.groups.through)
def manage_administratiors(instance, action, reverse, model, pk_set, using, *args, **kwargs):
if model == Group and action == 'post_add':
administrators_pk = Group.objects.get(name='administrators').pk
if administrators_pk in pk_set:
instance.is_superuser = True
instance.save()

Related

Defining a Dynamic Table Name Prefix in Rails

I'm using a Rails application to access a Dynamics NAV Database (today is called Dynamics 365 Business Central). In order to make it multi tenant, they partition the DB using table name prefixes ex: Company 1$Warehouse Entry or Company 2$Warehouse Entry.
I wanted to use a field defined in my User model in order to set the company name that it access.
In order to access the current user in the model I have used the following on application_controller.rb
before_action -> { User.current = current_user }
And then I set a base class where it declares the following instance method:
def self.set_company_name
company = User.current.nav_company ? User.current.nav_company + "$" : "Company 1$"
self.table_name = company + self.table_name
end
I also tried to use instance variables ##company but after reading I saw that table names in rails are cached.
What I have done works, but only if you restart the application. The table name doesn't change in runtime.
How can I make it dynamic? I saw this Question but the answer didn't show how to do this.
I don't know anything about Dynamics 365 and I don't understand why you want to associate two tables to one model, but I have worked with schemas/namespaces in postgresql for example: config.users where config is the schema and users the table name; so you can use it like select * from config.users.
Rails can easily adapt to this struct like you can see here.

Grails secure URL's using get form search

I have a Grails application using Spring Security.
This application is basically a content management system, so it is a CRUD.
My URL's access are basically formatted as follows:
/$controller/$action/$id
This is where encounters problems. That occurs in a controller, for example, to change a user I have the following URL:
/user/update/1
And into the controller I have the following code:
def update(Long id) {
def user = User.get(id);
[user: user]
}
That's the problem. If the user change the (id) directly without checking if the user id in request is correct, anyone can surf the users of my system. Now i have a big problem.
The solution that I thought would be to create a unique hash for each registration system, which would hinder the user to understand that, for example, the ID 1 has the hash 123aabbCCDD, for example.
But i have a lot of registers and many domains in the system, and i don't know if this is the best solution.
I need help to know, for example, using the spring security, I can do this kind of thing.
I tried to find solutions to the issue but I'm not sure by what words to search, so if there is already a question like mine, put the link in comments please.
Thanks.
As Joshua points out, if this is a general problem where you need to limit which users (or which roles) can perform particular actions, the spring-security-acl plugin will help. But that can be tedious to work with because you typically need to model things in a fine-grained way, and you end up with a lot of ACL data in the db.
But if you only want to restrict users to being able to edit themselves, just don't pass the user id. You already know who the user is if the action requires authentication. If that's the case, change the action to something like
def springSecurityService
def update() {
[user: springSecurityService.currentUser]
}
A related workflow that can often avoid using ACLs is allowing a user to edit something that they own, e.g. a CreditCard. Assuming you have static hasMany = [creditCards: CreditCard] in the User class and static belongsTo = [user: User] (or just User user), then you can allow the form to send the credit card id, but you just need to use a modified query, e.g.
def springSecurityService
def update(Long id) {
def user = springSecurityService.currentUser
def card = CreditCard.findByIdAndUser(id, user)
[creditCard: card]
}
The final SQL query will look something like select ... from credit_card where id=? and user_id=?, which has a big security advantage over the SQL for a get() call which would be select ... from credit_card where id=?. A malicious user can still try to send any id they want, but since the where clause checks both the id and the user foreign key, if they're not logged in as the card owner, the finder will return null and you can treat that as a mistake or a hack and not allow access.
Note that the hash approach you described isn't very secure - it's just "security by obscurity". If each user's hash is constant, it's not difficult to find out what a user's hash is and forge a request (e.g. a coworker can just look at another's monitor and see the url in their browser).

Spring Security in Grails providing authorization

A suggestion here would be deeply appreciated.
We use Spring Security domain object security to lock down access to specific objects in our Grails application. We have extended permissions as well. We use normal #PreAuthorize annotation to control access to the domain objects depending up the privileges assigned to a specific user.
In this architecture, I want for one user to be able to invite a second user to join a group. To do this, the second user receives an invitation from the first user to join a group with specific privileges. The second user can choose to accept or reject the invitation.
Given that the domain object belongs to the first user, not the second user, how could I grant access to the second user to the domain object with the privileges offered?
I have tried to hack a solution using #PreAuthorize("permitAll") on a service method just to see if that would work. While not ask secure as granting an object the privilege to set privileges to a domain object, it at least would get me going. But no joy, I continue to get "accessDenied for class" errors, presumably because the current user is the second user, not the domain object owner.
Do I need to work through the SpEL suggestion here? I barely understand how the bean resolver works unfortunately.
Edit: Even when I verify the invitation is valid at invocation Spring ACL throws an exception when the first ACE for the new user is attempted to be inserted. The exception occurs in void setPermissions(ObjectIdentity oid, recipient, Collection permissions) at the insertAce call:
void setPermissions(ObjectIdentity oid, recipient, Collection permissions) {
Sid sid = createSid(recipient)
MutableAcl acl
try {
acl = aclService.readAclById(oid)
}
catch (NotFoundException e) {
acl = aclService.createAcl(oid)
}
int deleted = 0
acl.entries.eachWithIndex { AccessControlEntry ace, int i ->
if (ace.sid == sid) {
acl.deleteAce(i-deleted)
deleted++
}
}
permissions.each {
acl.insertAce(acl.entries.size(), it, sid, true)
}
aclService.updateAcl acl
}
I assume that the access is denied because the current user (who did not exist when the invitation was issued) does not have the rights to set permissions on an object owned by another user.
You can use your Role class not only for generic roles (Admin,User, etc.), but for application specific ones as well. Simply allow the user to create a Role for a resource and then allow their invitees to be granted that role. Spring Security comes with a handy ifAnyGranted() method, which accepts a comma-delimited String of role names. At a resource entry-point simply ensure that a particular role is granted:
class Conversation{
Role role
}
class ConversationController{
def enterConversation(){
// obtain conversation instance
if(!SpringSecurityUtils.ifAnyGranted(conversationInstance.role.authority){response.sendError(401)}
}
}
The answer turned out to be using RunAs. For Grails, I did this as follows:
Create a Role specific for allowing invited users to act as an administrator in order to access a protected object. In Bootstrap, ensure this role is loaded into the SecRole domain:
def invitedRole = SecRole.findByAuthority('ROLE_RUN_AS_INVITED_USER')
if (!invitedRole) {
invitedRole = new SecRole()
invitedRole.authority = "ROLE_RUN_AS_INVITED_USER"
invitedRole.save(failOnError:true, flush:true)
}
Ensure in config.groovy that the role can change the target object:grails.plugins.springsecurity.acl.authority.changeAclDetails = 'ROLE_RUN_AS_INVITED_USER'
Enable RunAs in config.groovy
grails.plugins.springsecurity.useRunAs = true
grails.plugins.springsecurity.runAs.key = [key]
annotate the service method
#PreAuthorize([check that this is indeed an invited user])
#Secured(['ROLE_USER', 'RUN_AS_INVITED_USER'])
and it all works. The trick was to make the ROLE_RUN_AS_INVITED_USER able to change acl's.
Reference:
http://static.springsource.org/spring-security/site/docs/3.0.x/reference/runas.html
http://grails-plugins.github.io/grails-spring-security-acl/docs/manual/guide/2.%20Usage.html#2.5%20Run-As%20Authentication%20Replacement

Grails with Shiro - How to assign specifice permission to perticular user even he has role based permission

i installed shiro plugin in my application.i assigned one complete controller for role:'role_developer'..so if any user comes under role_developer he can access all actions of that controller..but here i want remove two actions of that controller..so please suggest me ..
here my code is:
def shiroRole = new ShiroRole()
shiroRole.name='ROLE_DEVELOPER'// create role as role developer
shiroROle.addToPermission('Person') //assigned permissions Person controller with all actionss
shiro.save()
now iam going create one user of ROLE_DEVELOPER and assigning permission some actions like person controller:create,list only
def shiroUser = new ShiroUser()
shiroUser.username='username'
shiroUser.passwordHash= new Sha256Hash("password").toHex()
shiroUser.addToRoles(ShiroRole.findByName('ROLE_DEVELOPER')
newUser.addToPermissions('person:list,create')
newUser.save()
...so here shiroUser shoud not be access all actions assigned to role_dveloper
Don't know how to do this using pure shiro API, but it can be done using grails filters
Something like this
import org.apache.shiro.SecurityUtils
import org.apache.shiro.subject.Subject
class ProjectFilters {
def filters = {
all(controller: 'Person', action: '*') {
before = {
Subject subject = SecurityUtils.getSubject()
//boolean hasRole = subject.hasRole('ROLE_DEVELOPER')
//boolean hasPermission = subject.isPermitted('Person')
if (/*your logic here*/) {
redirect(uri: '/access-denied')
return false
}
}
}
}
}
you don't need filters. :-)
I never used
shiroRole.addToPermission('Person')
but from your question I guess that's equal to
shiroRole.addToPermission('Person:*')
giving the owner of the role access to all actions of the Person controller.
It seems that you now would like to remove some of the permissions for one of the users by assigning permissions to this special user. But that's not the way it works. AFAIK, there is no way to remove permissions, and that's ok because it is more secure...
Shiro works in the following way:
Permissions like a:b give a user access to controller a and action b. A role is a collection of permissions. Permissions are additive.
So if you create a role
def shiroRole = new ShiroRole()
shiroRole.name='ROLE_USER'// create role as role developer
shiroRole.addToPermission('Person:list,show') //assigned permissions Person controller with all actionss
shiroRole.save()
and a user
def shiroUser = new ShiroUser()
shiroUser.username='username'
shiroUser.passwordHash= new Sha256Hash("password").toHex()
shiroUser.addToRoles(ShiroRole.findByName('ROLE_USER')
shiroUser.addToPermissions('person:create,save')
shiroUser.save()
this user will have access to Person:list and Person:show from the assigned role and Person:create and Person:save from his direct permissions.
As you can see, most of the time it is enough to work with roles and avoid using direct permissions.
I hope this helps...

Django List Admin allow sort on Reverse Foreign Key

When Creating your own Admin Class for django.contrib.comments, I want to allow sorting of flagged comments. I can a custom method to the admin class that return comment.flags.count(), but not sure I get the admin to sort by this.
The problem I see is that its CommentFlag model that contains the foreign key to Comment model.
Anybody know a solution with out changing django.contrib.comments?
def queryset(self, request):
qs = super(CommentsAdmin, self).queryset(request)
return qs.extra(select={
'flag_count': 'SELECT COUNT(*) FROM django_comment_flags WHERE django_comment_flags.comment_id = django_comments.id'
},)
def flags(self):
return self.flags.count()
flags.admin_order_field = 'flag_count'
Its a bit messy, but Django complains that flag_count is not an accessor for the Model Comment when you register the admin.

Resources