+#
# Thierry Parmentelat - INRIA
-# $Id$
-# $URL$
-
+#
from types import NoneType
from PLC.Faults import *
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,
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' ]
# 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,
-# while get_roles and set_roles get attached to the created methods
-# this might need a cleanup
+# note: set_roles get attached as 'roles' to the tagtype instance,
+# also get_roles and set_roles get attached to the created methods
#
# 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
-
-def define_accessors (module, objclass, methodsuffix, tagname,
- category, description,
- get_roles=['admin'], set_roles=['admin'],
- tag_min_role_id=10, expose_in_api = False):
+#
+# 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 write 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
+
+# the entry point accepts a single class or a list of classes
+def define_accessors (module, objclasses, *args, **kwds):
+ if not isinstance(objclasses,list):
+ objclasses=[objclasses]
+ for objclass in objclasses:
+ define_accessors_ (module, objclass, *args, **kwds)
+
+# this is for one class
+def define_accessors_ (module, objclass, methodsuffix, tagname,
+ category, description,
+ get_roles=all_roles, set_roles=admin_roles,
+ expose_in_api = False):
if objclass not in taggable_classes:
try:
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']
# 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, enforce=False):
return self.locate_or_create_tag (tagname=tagname,
category=category,
description=description,
- min_role_id=tag_min_role_id)
+ roles=set_roles,
+ enforce=enforce)
# 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):
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