X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=PLC%2FAccessors%2FFactory.py;h=3ad0bc1ad92cfa089608ab26d1c242cc229a6393;hb=fe32171e8722932e55d6c3e5b0df2acc34a1939f;hp=1c6d03e1199dbc01a3822805d925a17064c866c4;hpb=d605bcab2509fc2f9c6c5f1fae740d0e8c061a62;p=plcapi.git diff --git a/PLC/Accessors/Factory.py b/PLC/Accessors/Factory.py index 1c6d03e..3ad0bc1 100644 --- a/PLC/Accessors/Factory.py +++ b/PLC/Accessors/Factory.py @@ -1,7 +1,6 @@ +# # Thierry Parmentelat - INRIA -# $Id$ -# $URL$ - +# from types import NoneType from PLC.Faults import * @@ -22,8 +21,8 @@ from PLC.SiteTags import SiteTags, SiteTag from PLC.Persons import Persons, Person from PLC.PersonTags import PersonTags, PersonTag -# this is another story.. -#from PLC.Ilinks import Ilink +# need to import so the core classes get decorated with caller_may_write_tag +from PLC.AuthorizeHelpers import AuthorizeHelpers # known classes : { class -> details } taggable_classes = { Node : {'table_class' : Nodes, @@ -41,11 +40,11 @@ taggable_classes = { Node : {'table_class' : Nodes, Person: {'table_class' : Persons, 'joins_class': PersonTags, 'join_class': PersonTag, 'secondary_key':'email'}, -# Ilink : xxx } # xxx probably defined someplace else admin_roles = ['admin'] +person_roles = [ 'admin', 'pi', 'tech', 'user' ] all_roles = [ 'admin', 'pi', 'tech', 'user', 'node' ] tech_roles = [ 'admin', 'pi', 'tech' ] @@ -58,17 +57,25 @@ tech_roles = [ 'admin', 'pi', 'tech' ] # The expose_in_api flag tells whether this tag may be handled # through the Add/Get/Update methods as a native field # -# note: tag_min_role_id gets attached to the tagtype instance, +# note: roles get attached to the tagtype instance, # while get_roles and set_roles get attached to the created methods # this might need a cleanup # # in addition a convenience method like e.g. LocateNodeArch is defined # in the Accessor class; its purpose is to retrieve the tag, or to create it if needed - +# +# Legacy NOTE: +# prior to plcapi-5.0-19, this used to accept an additional argument +# named min_role_id; this was redundant and confusing, it has been +# removed, we now use set_roles to restrict access on the corresponding tag + +# the convention here is that methodsuffix should be mixed case, e.g. MyStuff +# while tagname is expected to be lowercase +# you then end up with e.g. GetPersonMyStuff def define_accessors (module, objclass, methodsuffix, tagname, category, description, - get_roles=['admin'], set_roles=['admin'], - tag_min_role_id=10, expose_in_api = False): + get_roles=all_roles, set_roles=admin_roles, + expose_in_api = False): if objclass not in taggable_classes: try: @@ -109,12 +116,14 @@ def define_accessors (module, objclass, methodsuffix, tagname, setattr(get_class,'roles',get_roles) setattr(get_class,'accepts',get_accepts) setattr(get_class,'returns', get_returns) - setattr(get_class,'skip_typecheck',True) +# that was useful for legacy method only, but we now need type_checking +# setattr(get_class,'skip_type_check',True) setattr(set_class,'roles',set_roles) setattr(set_class,'accepts',set_accepts) setattr(set_class,'returns', set_returns) - setattr(set_class,'skip_typecheck',True) +# that was useful for legacy method only, but we now need type_checking +# setattr(set_class,'skip_type_check',True) table_class = taggable_classes[objclass]['table_class'] joins_class = taggable_classes[objclass]['joins_class'] @@ -122,20 +131,21 @@ def define_accessors (module, objclass, methodsuffix, tagname, # locate the tag and create it if needed # this method is attached to the Accessor class - def locate_or_create_tag (self): + def tag_locator (self): return self.locate_or_create_tag (tagname=tagname, category=category, description=description, - min_role_id=tag_min_role_id) + roles=set_roles) # attach it to the Accessor class - setattr(Accessor,locator_name,locate_or_create_tag) + Accessor.register_tag_locator(locator_name,tag_locator) # body of the get method def get_call (self, auth, id_or_name): # locate the tag, see above - locator = getattr(Accessor,locator_name) - tag_type_id = locator(AccessorSingleton(self.api)) + tag_locator = Accessor.retrieve_tag_locator(locator_name) + tag_type = tag_locator(AccessorSingleton(self.api)) + tag_type_id=tag_type['tag_type_id'] filter = {'tag_type_id':tag_type_id} if isinstance (id_or_name,int): @@ -159,16 +169,26 @@ def define_accessors (module, objclass, methodsuffix, tagname, filter={primary_key:id_or_name} else: filter={secondary_key:id_or_name} - objs = table_class(self.api, filter,[primary_key,secondary_key]) +# we need the full monty b/c of the permission system +# objs = table_class(self.api, filter,[primary_key,secondary_key]) + objs = table_class(self.api, filter) if not objs: raise PLCInvalidArgument, "Cannot set tag on %s %r"%(objclass.__name__,id_or_name) - primary_id = objs[0][primary_key] + # the object being tagged + obj=objs[0] + primary_id = obj[primary_key] # locate the tag, see above - locator = getattr(Accessor,locator_name) - tag_type_id = locator(AccessorSingleton(self.api)) + tag_locator = Accessor.retrieve_tag_locator(locator_name) + tag_type = tag_locator(AccessorSingleton(self.api)) + tag_type_id = tag_type['tag_type_id'] + + # check authorization + if not hasattr(objclass,'caller_may_write_tag'): + raise PLCAuthenticationFailure, "class %s misses method caller_may_write_tag"%objclass.__name__ + obj.caller_may_write_tag (self.api,self.caller,tag_type) - # locate the join object (e.g. NodeTag, SliceTag or InterfaceTag) + # locate the join object (e.g. NodeTag or similar) filter = {'tag_type_id':tag_type_id} if isinstance (id_or_name,int): filter[primary_key]=id_or_name