====
[plcapi.git] / PLC / AuthorizeHelpers.py
index fe04d12..ec8daaf 100644 (file)
@@ -5,6 +5,8 @@ from PLC.Faults import *
 from PLC.Persons import Persons,Person
 from PLC.Sites import Sites,Site
 from PLC.Nodes import Nodes,Node
+from PLC.Interfaces import Interfaces,Interface
+from PLC.Slices import Slices,Slice
 
 class AuthorizeHelpers:
 
@@ -47,6 +49,10 @@ class AuthorizeHelpers:
             try:   return Nodes(api,node_id_or_hostname)[0]['node_id'] in slice['node_ids']
             except:return False
 
+    @staticmethod
+    def node_in_slice (api, caller_node, slice):
+        return caller_node['node_id'] in slice['node_ids']
+
     @staticmethod
     def node_id_in_site (api, node_id_or_hostname, site):
         if isinstance (node_id_or_hostname,int):
@@ -85,18 +91,24 @@ class AuthorizeHelpers:
     def slice_belongs_to_pi (api, slice, pi):
         return slice['site_id'] in pi['site_ids']
 
+    @staticmethod
+    def caller_is_node (api, caller, node):
+        return 'node_id' in caller and caller['node_id']==node['node_id']
+
 
 # authorization methods - check if a given caller can set tag on this object
 # called in {Add,Update,Delete}<Class>Tags methods, and in the accessors created in factory
 # attach these as <Class>.caller_may_write_tag so accessors can find it
 
 def caller_may_write_node_tag (node, api, caller, tag_type):
-    if 'admin' in caller['roles']:
+    if 'roles' in caller and 'admin' in caller['roles']:
         pass
     elif not AuthorizeHelpers.caller_may_access_tag_type (api, caller, tag_type):
         raise PLCPermissionDenied, "Role mismatch for writing tag %s"%(tag_type['tagname'])
     elif AuthorizeHelpers.node_belongs_to_person (api, node, caller):
         pass
+    elif AuthorizeHelpers.caller_is_node (api, caller, node):
+        pass
     else:
         raise PLCPermissionDenied, "Writing node tag: must belong in the same site as %s"%\
             (node['hostname'])
@@ -105,7 +117,7 @@ setattr(Node,'caller_may_write_tag',caller_may_write_node_tag)
         
 
 def caller_may_write_interface_tag (interface, api, caller, tag_type):
-    if 'admin' in caller['roles']:
+    if 'roles' in caller and 'admin' in caller['roles']:
         pass
     elif not AuthorizeHelpers.caller_may_access_tag_type (api, caller, tag_type):
         raise PLCPermissionDenied, "Role mismatch for writing tag %s"%(tag_type['tagname'])
@@ -119,7 +131,7 @@ setattr(Interface,'caller_may_write_tag',caller_may_write_interface_tag)
         
 
 def caller_may_write_site_tag (site, api, caller, tag_type):
-    if 'admin' in caller['roles']:
+    if 'roles' in caller and 'admin' in caller['roles']:
         pass
     elif not AuthorizeHelpers.caller_may_access_tag_type (api, caller, tag_type):
         raise PLCPermissionDenied, "Role mismatch for writing tag %s"%(tag_type['tagname'])
@@ -132,7 +144,7 @@ setattr(Site,'caller_may_write_tag',caller_may_write_site_tag)
 
 
 def caller_may_write_person_tag (person, api, caller, tag_type):
-    if 'admin' in caller['roles']:
+    if 'roles' in caller and 'admin' in caller['roles']:
         pass
     # user can change tags on self
     elif AuthorizeHelpers.person_may_access_person (api, caller, person):
@@ -145,20 +157,27 @@ setattr(Person,'caller_may_write_tag',caller_may_write_person_tag)
 
 def caller_may_write_slice_tag (slice, api, caller, tag_type, node_id_or_hostname=None, nodegroup_id_or_name=None):
     granted=False
-    if 'admin' in caller['roles']:
+    reason=""
+    if 'roles' in caller and 'admin' in caller['roles']:
         granted=True
     # does caller have right role(s) ? this knows how to deal with caller being a node
     elif not AuthorizeHelpers.caller_may_access_tag_type (api, caller, tag_type):
+        reason="caller may not access this tag type"
         granted=False
     # node callers: check the node is in the slice
     elif isinstance(caller, Node): 
         # nodes can only set their own sliver tags
         if node_id_or_hostname is None: 
+            reason="wrong node caller"
             granted=False
         elif not AuthorizeHelpers.node_match_id (api, caller, node_id_or_hostname):
+            reason="node mismatch"
             granted=False
         elif not AuthorizeHelpers.node_in_slice (api, caller, slice):
+            reason="slice not in node"
             granted=False
+        else:
+            granted=True
     # caller is a non-admin person
     else:
         # only admins can handle slice tags on a nodegroup
@@ -171,6 +190,7 @@ def caller_may_write_slice_tag (slice, api, caller, tag_type, node_id_or_hostnam
                 raise PLCPermissionDenied, "%s, node must be in slice when setting sliver tag"
         # try all roles to find a match - tech are ignored b/c not in AddSliceTag.roles anyways
         for role in AuthorizeHelpers.person_tag_type_common_roles(api,caller,tag_type):
+            reason="user not in slice; or slice does not belong to pi's site"
             # regular users need to be in the slice
             if role=='user':
                 if AuthorizeHelpers.person_in_slice(api, caller, slice):
@@ -180,7 +200,9 @@ def caller_may_write_slice_tag (slice, api, caller, tag_type, node_id_or_hostnam
                 if AuthorizeHelpers.slice_belongs_to_pi (api, slice, caller):
                     granted=True ; break
     if not granted:
-        raise PLCPermissionDenied, "Cannot write slice tag %s"%(tag_type['tagname'])
+#        try: print "DEBUG: caller=%s"%caller
+#        except: pass
+        raise PLCPermissionDenied, "Cannot write slice tag %s - %s"%(tag_type['tagname'],reason)
 
 setattr(Slice,'caller_may_write_tag',caller_may_write_slice_tag)