def get_slider_agents(scontext) : return [ ('anonymous_group', get_anonymous_group().get_ref()), ('all_members_group', get_all_members_group().get_ref()), ('context_agent', scontext.context_agent), ('context_admin', scontext.context_admin) ]
def has_access(agent, resource, interface): """Does the agent have access to this interface in this resource. All the special casing below will make it hard to refactor this method and for instance make it work for a whole lot of objects """ # make sure we've stripped resource from any SecureWrappers if resource.__class__.__name__ == "SecureWrapper": resource = resource.get_inner() # make sure we've stripped agent from any SecureWrappers if agent.__class__.__name__ == "SecureWrapper": agent = agent.get_inner() # we're always interested in the security_context of this resource context = resource.get_security_context() # which agents have access? if not SecurityTag.objects.filter(interface=interface, security_context=context): # lets create it if it is in defaults for the type -- this allows adding new interfaces to the type at runtime typ = resource.__class__ interface_name = interface.split(".")[1] if interface_name in get_interface_map(typ.__name__): agent_defaults = AgentDefaults[context.context_agent.obj.__class__][ context.context_agent.permission_prototype ] slider_agents = SliderAgents[context.context_agent.obj.__class__](context) sad = dict(slider_agents) context.setup_tag_from_defaults(interface, sad, agent_defaults) allowed_agents = SecurityTag.objects.get(interface=interface, security_context=context).agents # probably should memcache both allowed agents (per .View interface) and # agents held per user to allow many queries very quickly. allowed_agents = set([a.obj for a in allowed_agents.all()]) if get_anonymous_group() in allowed_agents: # in other words, if this resource is matched with anyone, we don't have to test # that user is in the "anyone" group return True if get_creator_agent().obj in allowed_agents: actual_creator = resource.get_ref().creator if agent == actual_creator: return True if agent.__class__ == AnonymousUser: # we clearly shouldn't be seeing this - sure but is this a security issue - t.s. return False agents_held = agent.get_enclosure_set() if allowed_agents.intersection(agents_held): return True print "has_access fails for %s, %s, %s, %s" % (interface, resource, context.context_agent.obj, agent) return False
def move_slider(self, new_agent, interface, user=None, skip_validation=False, no_user=False): """skip_validation is necessary on setup because some of the SecurityTags won't yet exist. Also when we move multiple sliders at the same time we should skip validation in the same way. """ if user: self.can_set_manage_permissions(interface, user) else: if not no_user: raise NotAnAgent type_name, iface_name = interface.split('.') try: new_agent.obj except: if is_agent(new_agent): new_agent = new_agent.get_ref() else: raise NotAnAgent slider_agents = SliderAgents[self.context_agent.obj.__class__](self) slider_agents.reverse() slider_agents = [t[1] for t in slider_agents] if new_agent in slider_agents: tag = SecurityTag.objects.get(interface=interface, security_context=self) split = slider_agents.index(new_agent) + 1 adds = slider_agents[:split] removes = slider_agents[split:] tag.remove_agents(removes) tag.add_agents(adds) if not skip_validation: self.validate_constraints(type_name) if interface == 'Profile.Viewer': try: User().public_field except Exception, e: # doesn't exist (this is not hub+) # we're finished here return target = self.get_target() if target.__class__.__name__ != 'User': return user = target if new_agent.obj == get_anonymous_group(): user.public_field = 1 else: user.public_field = 0 user.save()
def move_slider(self, new_agent, interface, user=None, skip_validation=False, no_user=False): """skip_validation is necessary on setup because some of the SecurityTags won't yet exist. Also when we move multiple sliders at the same time we should skip validation in the same way. """ if user: self.can_set_manage_permissions(interface, user) else: if not no_user: raise NotAnAgent type_name, iface_name = interface.split('.') try: new_agent.obj except: if is_agent(new_agent): new_agent = new_agent.get_ref() else: raise NotAnAgent slider_agents = SliderAgents[self.context_agent.obj.__class__](self) slider_agents.reverse() slider_agents = [t[1] for t in slider_agents] if new_agent in slider_agents: tag = SecurityTag.objects.get(interface=interface, security_context=self) split = slider_agents.index(new_agent) + 1 adds = slider_agents[:split] removes = slider_agents[split:] tag.remove_agents(removes) tag.add_agents(adds) if not skip_validation: self.validate_constraints(type_name) if interface == 'Profile.Viewer' : try : User().public_field except Exception, e : # doesn't exist (this is not hub+) # we're finished here return target = self.get_target() if target.__class__.__name__ != 'User' : return user = target if new_agent.obj == get_anonymous_group() : user.public_field = 1 else : user.public_field = 0 user.save()
def get_slider_agents(scontext): return [('anonymous_group', get_anonymous_group().get_ref()), ('all_members_group', get_all_members_group().get_ref()), ('context_agent', scontext.context_agent), ('context_admin', scontext.context_admin)]
def has_access(agent, resource, interface, sec_context=None, diagnose=None) : """Does the agent have access to this interface in this resource. All the special casing below will make it hard to refactor this method and for instance make it work for a whole lot of objects """ # if diagnose mode we want to try to find why we failed to get the interface we want if diagnose : diagnostics = {} # make sure we've stripped agent from any SecureWrappers if agent.__class__.__name__ == "SecureWrapper": agent = agent.get_inner() if not sec_context: # make sure we've stripped resource from any SecureWrappers if resource.__class__.__name__ == "SecureWrapper": resource = resource.get_inner() context = resource.get_security_context() else: context = sec_context if not SecurityTag.objects.filter(interface=interface, security_context=context): #lets create it if it is in defaults for the type -- this allows adding new interfaces to the type at runtime typ = resource.__class__ interface_name = interface.split('.')[1] if interface_name in get_interface_map(typ.__name__): agent_defaults = AgentDefaults[context.context_agent.obj.__class__][context.context_agent.permission_prototype] slider_agents = SliderAgents[context.context_agent.obj.__class__](context) sad = dict(slider_agents) context.setup_tag_from_defaults(interface, sad, agent_defaults) # which agents have access? allowed_agents = SecurityTag.objects.get(interface=interface, security_context=context).agents # probably should redis both allowed agents (per .View interface) and # agents held per user to allow many queries very quickly. allowed_agents = set([a.obj for a in allowed_agents.all()]) # diagnostic if diagnose : diagnostics['allowed_agents'] = allowed_agents if agent in allowed_agents : # agent must hold itself. agent.get_enclosures no longer includes agent return True if get_anonymous_group() in allowed_agents: # in other words, if this resource is matched with anyone, we don't have to test #that user is in the "anyone" group return True if resource: if get_creator_agent().obj in allowed_agents: actual_creator = resource.get_ref().creator if agent == actual_creator: return True agents_held = agent.get_enclosure_set() if diagnose : diagnostics['agents_held'] = agents_held if allowed_agents.intersection(agents_held): return True if diagnose : print print 'Interface ', interface print "Allowed Agents for ", resource for a in diagnostics['allowed_agents'] : print a print "Agents Held by ", agent for a in diagnostics['agents_held'] : print "%s,"%a, print for a in diagnostics['allowed_agents'] : if not a in diagnostics['agents_held'] : print a, " not in agents_held" return False
def has_access(agent, resource, interface, sec_context=None, diagnose=None): """Does the agent have access to this interface in this resource. All the special casing below will make it hard to refactor this method and for instance make it work for a whole lot of objects """ # if diagnose mode we want to try to find why we failed to get the interface we want if diagnose: diagnostics = {} # make sure we've stripped agent from any SecureWrappers if agent.__class__.__name__ == "SecureWrapper": agent = agent.get_inner() if not sec_context: # make sure we've stripped resource from any SecureWrappers if resource.__class__.__name__ == "SecureWrapper": resource = resource.get_inner() context = resource.get_security_context() else: context = sec_context if not SecurityTag.objects.filter(interface=interface, security_context=context): #lets create it if it is in defaults for the type -- this allows adding new interfaces to the type at runtime typ = resource.__class__ interface_name = interface.split('.')[1] if interface_name in get_interface_map(typ.__name__): agent_defaults = AgentDefaults[ context.context_agent.obj.__class__][ context.context_agent.permission_prototype] slider_agents = SliderAgents[context.context_agent.obj.__class__]( context) sad = dict(slider_agents) context.setup_tag_from_defaults(interface, sad, agent_defaults) # which agents have access? allowed_agents = SecurityTag.objects.get(interface=interface, security_context=context).agents # probably should redis both allowed agents (per .View interface) and # agents held per user to allow many queries very quickly. allowed_agents = set([a.obj for a in allowed_agents.all()]) # diagnostic if diagnose: diagnostics['allowed_agents'] = allowed_agents if agent in allowed_agents: # agent must hold itself. agent.get_enclosures no longer includes agent return True if get_anonymous_group() in allowed_agents: # in other words, if this resource is matched with anyone, we don't have to test #that user is in the "anyone" group return True if resource: if get_creator_agent().obj in allowed_agents: actual_creator = resource.get_ref().creator if agent == actual_creator: return True agents_held = agent.get_enclosure_set() if diagnose: diagnostics['agents_held'] = agents_held if allowed_agents.intersection(agents_held): return True if diagnose: print print 'Interface ', interface print "Allowed Agents for ", resource for a in diagnostics['allowed_agents']: print a print "Agents Held by ", agent for a in diagnostics['agents_held']: print "%s," % a, print for a in diagnostics['allowed_agents']: if not a in diagnostics['agents_held']: print a, " not in agents_held" return False
def test_access(self) : """ Starting with security_contexts""" nahia = User(username='******', email_address='*****@*****.**') nahia.save() adam = get_admin_user() kx, created = TgGroup.objects.get_or_create(group_name='kingsX', display_name='Hub Kings Cross', level='member', user=adam) kxsc = kx.to_security_context() blog = kx.create_OurPost(title='my blog', creator=adam) blog.save() # assert that the blog post acquires it's security context from Kings Cross self.assertEquals(blog.get_inner().get_security_context().id, kx.get_security_context().id) # confirm that there's an OurPost.Viewer interface for Kings Cross self.assertTrue( kx.get_tag_for_interface("OurPost.Viewer")) # but nahia has no access to the blog self.assertFalse(has_access(nahia, blog, "OurPost.Viewer")) # now lets add this user to the tag tag = kx.get_tag_for_interface("OurPost.Viewer") tag.add_agents([nahia.get_ref()]) # so now nahia has access self.assertTrue( has_access(nahia, blog, "OurPost.Viewer")) # but tuba doesn't tuba = User(username='******', email_address='*****@*****.**') tuba.save() self.assertFalse( has_access(tuba, blog, "OurPost.Viewer")) # however, we presumably want to give kings cross *members* access to it tag.add_agents([kx.get_ref()]) self.assertTrue( has_access(kx, blog, "OurPost.Viewer")) # so if we add tuba to kings cross kx.add_member(tuba) # she now has access self.assertTrue( has_access(tuba, blog, "OurPost.Viewer")) # Now we test that a second blog-post that's created starts with similar access blog2 = kx.create_OurPost(creator=adam, title='second post') blog2.save() self.assertTrue(has_access(tuba, blog2, "OurPost.Viewer")) # but we assume that not everyone got an editor interface self.assertFalse(has_access(tuba, blog2, "OurPost.Editor")) # add an arbitrary agent and remove her agaiin blog._inner.get_security_context().add_arbitrary_agent(tuba, 'OurPost.Editor', adam) self.assertTrue(has_access(tuba, blog, "OurPost.Editor")) blog._inner.get_security_context().remove_arbitrary_agent(tuba, 'OurPost.Editor', adam) self.assertFalse(has_access(tuba, blog, "OurPost.Editor")) #test moving the sliders around members_group = blog._inner.get_security_context().context_agent.obj admin_group = blog._inner.get_security_context().context_admin.obj #set the slider so that members of KX have the Editor interface blog._inner.get_security_context().move_slider(members_group, 'OurPost.Editor', adam) #check that the slider level actually changed level = blog._inner.get_security_context().get_slider_level('OurPost.Editor') self.assertTrue(level==members_group) #and check that tuba has access self.assertTrue(has_access(tuba, blog, "OurPost.Editor")) #now remove tuba from the members group members_group.remove_member(tuba) self.assertFalse(has_access(tuba, blog, "OurPost.Editor")) #and re-add her members_group.add_member(tuba) self.assertTrue(has_access(tuba, blog, "OurPost.Editor")) #raise the requirement to the admin group blog.get_inner().get_security_context().move_slider(admin_group, 'OurPost.Editor', adam) level = blog.get_inner().get_security_context().get_slider_level('OurPost.Editor') #check the slider changed and that adam can now access while tuba cannot self.assertTrue(level==admin_group) self.assertFalse(has_access(tuba, blog, "OurPost.Editor")) self.assertTrue(has_access(adam, blog, "OurPost.Editor")) #use the move_sliders interface which should be called by the UI and check that constraints are enforced correctly # this should fail validation because editor can't be higher than viewer def move_sliders(slider_dict, type_name, user): blog._inner.get_security_context().move_sliders(slider_dict, type_name, user=user) anonymous_group = get_anonymous_group() self.assertRaises(InvalidSliderConfiguration, move_sliders, {'OurPost.Editor':members_group, 'OurPost.Viewer':admin_group}, 'OurPost', adam) # so should this because Editor can't be anonymous self.assertRaises(InvalidSliderConfiguration, move_sliders, {'OurPost.Editor':anonymous_group, 'OurPost.Viewer':anonymous_group}, 'OurPost', adam) # check that nothing changed level = blog._inner.get_security_context().get_slider_level('OurPost.Editor') self.assertTrue(level==admin_group) # this should validate blog._inner.get_security_context().move_sliders({'OurPost.Editor':members_group, 'OurPost.Viewer':members_group}, 'OurPost', adam) # and levels should be changed level = blog._inner.get_security_context().get_slider_level('OurPost.Editor') self.assertTrue(level==members_group) level = blog._inner.get_security_context().get_slider_level('OurPost.Viewer') self.assertTrue(level==members_group) # so now we're going to give tuba special permissions on this blog post ONLY # so first make the blog post a custom context sc2 = blog2.create_custom_security_context() # assert now that blog2's security context is NOT the same as blog's self.assertNotEquals(blog2._inner.get_security_context(), blog._inner.get_security_context()) # but that the admin and agent are self.assertEquals(blog2._inner.get_security_context().context_agent, blog._inner.get_security_context().context_agent) self.assertEquals(blog2._inner.get_security_context().context_admin, blog._inner.get_security_context().context_admin) # another kings cross host elenor = User(username='******', email_address='*****@*****.**') elenor.save() # who doesn't have access self.assertFalse(has_access(elenor, blog2, 'OurPost.Editor')) # so we add her to the tag sc2.add_arbitrary_agent(elenor, 'OurPost.Editor', adam) # and she now has access self.assertTrue(has_access(elenor, blog2, "OurPost.Editor")) # let's take her away again and check she loses access blog2.remove_arbitrary_agent(elenor, 'OurPost.Editor', adam) self.assertFalse(has_access(elenor, blog2, "OurPost.Editor")) # and if we add elinor to kx kx.add_member(elenor) # so should have same access self.assertTrue(has_access(elenor, blog, "OurPost.Editor"))
def test_application(self): god = get_admin_user( ) # now a standard user, and member of the site_members_group's admin site = get_site(god) contact = site.create_Contact(god, first_name='kate', last_name='smith', email_address='*****@*****.**') contact.save() self.assertTrue(contact.get_inner().get_creator()) group = site.create_TgGroup(god, group_name='sexy_salad', display_name='Sexy Salad', level='member') self.assertTrue( group.get_inner().get_creator()) # group should have a creator self.assertEquals(group.get_inner().get_creator().id, god.id) application = site.create_Application(god, applicant=contact, request='I want to join in') # the following should be true because application was created by god # so god is its "creator" and default for Application.Editor is "creator" self.assertTrue(has_access(god, application, 'Application.Editor')) application.group = group.get_inner() application.save() self.assertTrue(has_access(group, application, 'Application.Viewer')) self.assertEquals(application.date.date(), datetime.datetime.today().date()) self.assertTrue(application.applicant.s_eq(contact)) self.assertEquals(application.request, 'I want to join in') self.assertTrue(application.group.s_eq(group)) self.assertEquals(application.status, PENDING) self.assertEquals(application.admin_comment, '') self.assertEquals(application.accepted_by, None) # adding a couple more ap2 = site.create_Application(god, applicant=contact, request='ap2', group=get_anonymous_group()) ap3 = site.create_Application(god, applicant=contact, request='ap3', group=get_all_members_group()) self.assertEquals(self.count(Application.objects.filter()), 3) self.assertEquals( self.count(Application.objects.filter(request='ap2')), 1) mable = User(username='******', email_address='*****@*****.**') mable.save() self.assertEquals(Application.objects.plus_count(mable), 0) # now there's a security tag which links "group" as context to the interface "ApplicationViewer" site.get_inner().get_security_context().add_arbitrary_agent( group, 'Application.Viewer', god) self.assertTrue(has_access(group, ap2, 'Application.Viewer')) self.assertFalse(has_access(mable, ap2, 'Application.Viewer')) self.assertEquals(Application.objects.plus_count(group), 3) s_application = Application.objects.plus_get(mable, id=application.id) def f(application, sponsor): application.accept(sponsor) self.assertRaises(PlusPermissionsNoAccessException, f, s_application, mable) self.assertEquals(s_application.get_inner().status, PENDING) application = Application.objects.get(id=application.id) application.accept(mable, 'site_root', admin_comment='great choice') self.assertEquals(application.status, WAITING_USER_SIGNUP) self.assertEquals(application.admin_comment, 'great choice') self.assertEquals(application.accepted_by, mable)
def test_application(self) : god = get_admin_user() # now a standard user, and member of the site_members_group's admin site = get_site(god) contact = site.create_Contact(god, first_name='kate', last_name='smith', email_address='*****@*****.**') contact.save() self.assertTrue(contact.get_inner().get_creator()) group = site.create_TgGroup(god, group_name='sexy_salad', display_name='Sexy Salad', level='member') self.assertTrue(group.get_inner().get_creator()) # group should have a creator self.assertEquals(group.get_inner().get_creator().id,god.id) application = site.create_Application(god, applicant=contact, request='I want to join in') # the following should be true because application was created by god # so god is its "creator" and default for Application.Editor is "creator" self.assertTrue(has_access(god, application, 'Application.Editor')) application.group = group.get_inner() application.save() self.assertTrue(has_access(group,application,'Application.Viewer')) self.assertEquals(application.date.date(),datetime.datetime.today().date()) self.assertTrue(application.applicant.s_eq(contact)) self.assertEquals(application.request, 'I want to join in') self.assertTrue(application.group.s_eq(group)) self.assertEquals(application.status, PENDING) self.assertEquals(application.admin_comment,'') self.assertEquals(application.accepted_by,None) # adding a couple more ap2 = site.create_Application(god, applicant=contact,request='ap2',group=get_anonymous_group()) ap3 = site.create_Application(god, applicant=contact,request='ap3',group=get_all_members_group()) self.assertEquals(self.count(Application.objects.filter()),3) self.assertEquals(self.count(Application.objects.filter(request='ap2')),1) mable = User(username='******',email_address='*****@*****.**') mable.save() self.assertEquals(Application.objects.plus_count(mable),0) # now there's a security tag which links "group" as context to the interface "ApplicationViewer" site.get_inner().get_security_context().add_arbitrary_agent(group, 'Application.Viewer', god) self.assertTrue(has_access(group, ap2, 'Application.Viewer')) self.assertFalse(has_access(mable, ap2, 'Application.Viewer')) self.assertEquals(Application.objects.plus_count(group),3) s_application = Application.objects.plus_get(mable, id=application.id) def f(application,sponsor) : application.accept(sponsor) self.assertRaises(PlusPermissionsNoAccessException,f,s_application,mable) self.assertEquals(s_application.get_inner().status,PENDING) application = Application.objects.get(id=application.id) application.accept(mable, 'site_root', admin_comment='great choice') self.assertEquals(application.status,WAITING_USER_SIGNUP) self.assertEquals(application.admin_comment,'great choice') self.assertEquals(application.accepted_by, mable)