Setting tag plcapi-5.4-1
[plcapi.git] / PLC / Accessors / Factory.py
index a207513..fec0d63 100644 (file)
@@ -21,6 +21,9 @@ from PLC.SiteTags import SiteTags, SiteTag
 from PLC.Persons import Persons, Person
 from PLC.PersonTags import PersonTags, PersonTag
 
+# 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,
                              'joins_class' : NodeTags, 'join_class' : NodeTag,
@@ -54,9 +57,8 @@ 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: roles get 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
@@ -64,15 +66,24 @@ tech_roles = [ 'admin', 'pi', 'tech' ]
 # 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
+# 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
-def define_accessors (module, objclass, methodsuffix, tagname,
-                      category, description,
-                      get_roles=all_roles, set_roles=admin_roles, 
-                      expose_in_api = False):
+
+# 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:
@@ -128,20 +139,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, enforce=False):
         return self.locate_or_create_tag (tagname=tagname,
                                           category=category,
                                           description=description,
-                                          roles=set_roles)
+                                          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 = 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}
@@ -176,13 +188,14 @@ def define_accessors (module, objclass, methodsuffix, tagname,
         primary_id = obj[primary_key]
 
         # locate the tag, see above
-        locator = getattr(Accessor,locator_name)
-        tag_type = 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 hasattr(objclass,'caller_may_write_tag'):
-            obj.caller_may_write_tag (self.api,self.caller,tag_type)
+        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 or similar)
         filter = {'tag_type_id':tag_type_id}