reviewing the tags permission system
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Thu, 18 Nov 2010 19:16:19 +0000 (20:16 +0100)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Thu, 18 Nov 2010 19:16:19 +0000 (20:16 +0100)
tag_types don't have a min_role_id anymore but a set of roles
new methods AddRoleToTagType and DeleteRoleFromTagType to handle that
new file PLC/AuthorizeHelpers.py has helpers to implement authorizations
this is a checkpoint commit - remaining todo:
- slice tags methods are unchanged yet
- accessors and factory still use min_role_id

43 files changed:
PLC/Accessor.py
PLC/Faults.py
PLC/Ilinks.py
PLC/InterfaceTags.py
PLC/Interfaces.py
PLC/Methods/AddIlink.py
PLC/Methods/AddInterface.py
PLC/Methods/AddInterfaceTag.py
PLC/Methods/AddNodeTag.py
PLC/Methods/AddPerson.py
PLC/Methods/AddPersonTag.py
PLC/Methods/AddRoleToPerson.py
PLC/Methods/AddRoleToTagType.py [new file with mode: 0644]
PLC/Methods/AddSiteTag.py
PLC/Methods/AddSliceTag.py
PLC/Methods/AddTagType.py
PLC/Methods/DeleteIlink.py
PLC/Methods/DeleteInterface.py
PLC/Methods/DeleteInterfaceTag.py
PLC/Methods/DeleteNodeTag.py
PLC/Methods/DeletePersonTag.py
PLC/Methods/DeleteRoleFromPerson.py
PLC/Methods/DeleteRoleFromTagType.py [new file with mode: 0644]
PLC/Methods/DeleteSite.py
PLC/Methods/DeleteSiteTag.py
PLC/Methods/DeleteSliceTag.py
PLC/Methods/UpdateIlink.py
PLC/Methods/UpdateInterfaceTag.py
PLC/Methods/UpdateNodeTag.py
PLC/Methods/UpdatePersonTag.py
PLC/Methods/UpdateSiteTag.py
PLC/Methods/UpdateSliceTag.py
PLC/Methods/UpdateTagType.py
PLC/NodeTags.py
PLC/PersonTags.py
PLC/Roles.py
PLC/SiteTags.py
PLC/Sites.py
PLC/SliceTags.py
PLC/TagTypes.py
migrations/104-down-noderole.sql [new file with mode: 0644]
migrations/104-up-noderole.sql [new file with mode: 0644]
planetlab5.sql

index ea69ccb..0a499b5 100644 (file)
@@ -1,5 +1,3 @@
-# $Id$
-# $URL$
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
index 3309cb6..cebe5c5 100644 (file)
@@ -5,8 +5,6 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 #
 # Copyright (C) 2004-2006 The Trustees of Princeton University
 # Mark Huang <mlhuang@cs.princeton.edu>
 #
 # Copyright (C) 2004-2006 The Trustees of Princeton University
-# $Id$
-# $URL$
 #
 
 import xmlrpclib
 #
 
 import xmlrpclib
index 8cd97ae..d99f13c 100644 (file)
@@ -1,5 +1,3 @@
-# $Id$
-# $URL$
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
index 976a54e..4dcb531 100644 (file)
@@ -28,7 +28,6 @@ class InterfaceTag(Row):
         'tagname': TagType.fields['tagname'],
         'description': TagType.fields['description'],
         'category': TagType.fields['category'],
         'tagname': TagType.fields['tagname'],
         'description': TagType.fields['description'],
         'category': TagType.fields['category'],
-        'min_role_id': TagType.fields['min_role_id'],
         'value': Parameter(str, "Interface setting value"),
         ### relations
 
         'value': Parameter(str, "Interface setting value"),
         ### relations
 
index 2ea645f..c8ccd2e 100644 (file)
@@ -4,9 +4,6 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id$
-# $URL$
-#
 
 from types import StringTypes
 import socket
 
 from types import StringTypes
 import socket
@@ -227,6 +224,12 @@ class Interface(Row):
     def update_last_updated(self, commit = True):
         self.update_timestamp('last_updated', commit)
 
     def update_last_updated(self, commit = True):
         self.update_timestamp('last_updated', commit)
 
+    def delete(self,commit=True):
+        ### need to cleanup ilinks
+        self.api.db.do("DELETE FROM ilink WHERE src_interface_id=%d OR dst_interface_id=%d" % \
+                           (self['interface_id'],self['interface_id']))
+        
+        Row.delete(self)
 
 class Interfaces(Table):
     """
 
 class Interfaces(Table):
     """
index 6316805..c9d18b1 100644 (file)
@@ -1,10 +1,6 @@
-# $Id$
-# $URL$
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
-# $Revision: 9423 $
-#
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
@@ -13,9 +9,10 @@ from PLC.Auth import Auth
 from PLC.TagTypes import TagType, TagTypes
 from PLC.Ilinks import Ilink, Ilinks
 from PLC.Interfaces import Interface, Interfaces
 from PLC.TagTypes import TagType, TagTypes
 from PLC.Ilinks import Ilink, Ilinks
 from PLC.Interfaces import Interface, Interfaces
-
 from PLC.Sites import Sites
 
 from PLC.Sites import Sites
 
+from PLC.AuthorizeHelpers import AuthorizeHelpers
+
 class AddIlink(Method):
     """
     Create a link between two interfaces
 class AddIlink(Method):
     """
     Create a link between two interfaces
@@ -65,21 +62,18 @@ class AddIlink(Method):
             raise PLCInvalidArgument, "Ilink (%s,%d,%d) already exists and has value %r"\
                 %(tag_type['name'],src_if_id,dst_if_id,ilink['value'])
 
             raise PLCInvalidArgument, "Ilink (%s,%d,%d) already exists and has value %r"\
                 %(tag_type['name'],src_if_id,dst_if_id,ilink['value'])
 
-        if 'admin' not in self.caller['roles']:
-#       # check permission : it not admin, is the user affiliated with the right site(s) ????
-#           # locate node
-#           node = Nodes (self.api,[node['node_id']])[0]
-#           # locate site
-#           site = Sites (self.api, [node['site_id']])[0]
-#           # check caller is affiliated with this site
-#           if self.caller['person_id'] not in site['person_ids']:
-#               raise PLCPermissionDenied, "Not a member of the hosting site %s"%site['abbreviated_site']
-
-            required_min_role = tag_type ['min_role_id']
-            if required_min_role is not None and \
-                    min(self.caller['role_ids']) > required_min_role:
-                raise PLCPermissionDenied, "Not allowed to modify the specified ilink, requires role %d",required_min_role
-
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        elif not AuthorizeHelpers.person_access_tag_type (self.api, self.caller, tag_type):
+            raise PLCPermissionDenied, "%s, no permission to use this tag type"%self.name
+        elif AuthorizeHelpers.interface_belongs_to_person (self.api, src_if, self.caller):
+            pass
+        elif src_if_id != dst_if_id and AuthorizeHelpers.interface_belongs_to_person (self.api, dst_if, self.caller):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you must one either the src or dst interface"%self.name
+            
         ilink = Ilink(self.api)
         ilink['tag_type_id'] = tag_type['tag_type_id']
         ilink['src_interface_id'] = src_if_id
         ilink = Ilink(self.api)
         ilink['tag_type_id'] = tag_type['tag_type_id']
         ilink['src_interface_id'] = src_if_id
index e98d545..ec35fc7 100644 (file)
@@ -1,5 +1,6 @@
-# $Id$
-# $URL$
+#
+# Thierry Parmentelat - INRIA
+#
 from PLC.Faults import *
 from PLC.Auth import Auth
 from PLC.Method import Method
 from PLC.Faults import *
 from PLC.Auth import Auth
 from PLC.Method import Method
index 23aaeaf..912e147 100644 (file)
@@ -1,29 +1,25 @@
-# $Id$
-# $URL$
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
-# $Revision$
-#
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
+from PLC.Sites import Sites
+from PLC.Nodes import Nodes
+from PLC.Interfaces import Interface, Interfaces
 from PLC.TagTypes import TagType, TagTypes
 from PLC.InterfaceTags import InterfaceTag, InterfaceTags
 from PLC.TagTypes import TagType, TagTypes
 from PLC.InterfaceTags import InterfaceTag, InterfaceTags
-from PLC.Interfaces import Interface, Interfaces
-
-from PLC.Nodes import Nodes
-from PLC.Sites import Sites
 
 class AddInterfaceTag(Method):
     """
     Sets the specified setting for the specified interface
     to the specified value.
 
 
 class AddInterfaceTag(Method):
     """
     Sets the specified setting for the specified interface
     to the specified value.
 
-    In general only tech(s), PI(s) and of course admin(s) are allowed to
-    do the change, but this is defined in the tag type object.
+    Admins have full access.  Non-admins need to 
+    (1) have at least one of the roles attached to the tagtype, 
+    and (2) belong in the same site as the tagged subject.
 
     Returns the new interface_tag_id (> 0) if successful, faults
     otherwise.
 
     Returns the new interface_tag_id (> 0) if successful, faults
     otherwise.
@@ -42,9 +38,6 @@ class AddInterfaceTag(Method):
 
     returns = Parameter(int, 'New interface_tag_id (> 0) if successful')
 
 
     returns = Parameter(int, 'New interface_tag_id (> 0) if successful')
 
-    object_type = 'Interface'
-
-
     def call(self, auth, interface_id, tag_type_id_or_name, value):
         interfaces = Interfaces(self.api, [interface_id])
         if not interfaces:
     def call(self, auth, interface_id, tag_type_id_or_name, value):
         interfaces = Interfaces(self.api, [interface_id])
         if not interfaces:
@@ -65,20 +58,16 @@ class AddInterfaceTag(Method):
             raise PLCInvalidArgument, "Interface %d already has setting %d"%(interface['interface_id'],
                                                                                tag_type['tag_type_id'])
 
             raise PLCInvalidArgument, "Interface %d already has setting %d"%(interface['interface_id'],
                                                                                tag_type['tag_type_id'])
 
-        # check permission : it not admin, is the user affiliated with the right site
-        if 'admin' not in self.caller['roles']:
-            # locate node
-            node = Nodes (self.api,[interface['node_id']])[0]
-            # locate site
-            site = Sites (self.api, [node['site_id']])[0]
-            # check caller is affiliated with this site
-            if self.caller['person_id'] not in site['person_ids']:
-                raise PLCPermissionDenied, "Not a member of the hosting site %s"%site['abbreviated_site']
-
-            required_min_role = tag_type ['min_role_id']
-            if required_min_role is not None and \
-                    min(self.caller['role_ids']) > required_min_role:
-                raise PLCPermissionDenied, "Not allowed to modify the specified interface setting, requires role %d",required_min_role
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        elif not AuthorizeHelpers.person_access_tag_type (self.api, self.caller, tag_type):
+            raise PLCPermissionDenied, "%s, no permission to use this tag type"%self.name
+        elif AuthorizeHelpers.interface_belongs_to_person (self.api, interface, self.caller):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you must belong in the same site as subject interface"%self.name
+        
 
         interface_tag = InterfaceTag(self.api)
         interface_tag['interface_id'] = interface['interface_id']
 
         interface_tag = InterfaceTag(self.api)
         interface_tag['interface_id'] = interface['interface_id']
index f02181b..43e075f 100644 (file)
@@ -1,10 +1,6 @@
-# $Id$
-# $URL$
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
-# $Revision: 9423 $
-#
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
@@ -15,14 +11,16 @@ from PLC.Nodes import Node, Nodes
 from PLC.TagTypes import TagType, TagTypes
 from PLC.NodeTags import NodeTag, NodeTags
 
 from PLC.TagTypes import TagType, TagTypes
 from PLC.NodeTags import NodeTag, NodeTags
 
+from PLC.AuthorizeHelpers import AuthorizeHelpers
 
 class AddNodeTag(Method):
     """
     Sets the specified tag for the specified node
     to the specified value.
 
 
 class AddNodeTag(Method):
     """
     Sets the specified tag for the specified node
     to the specified value.
 
-    In general only tech(s), PI(s) and of course admin(s) are allowed to
-    do the change, but this is defined in the node tag type object.
+    Admins have full access.  Non-admins need to 
+    (1) have at least one of the roles attached to the tagtype, 
+    and (2) belong in the same site as the tagged subject.
 
     Returns the new node_tag_id (> 0) if successful, faults
     otherwise.
 
     Returns the new node_tag_id (> 0) if successful, faults
     otherwise.
@@ -42,9 +40,6 @@ class AddNodeTag(Method):
 
     returns = Parameter(int, 'New node_tag_id (> 0) if successful')
 
 
     returns = Parameter(int, 'New node_tag_id (> 0) if successful')
 
-    object_type = 'Node'
-
-
     def call(self, auth, node_id, tag_type_id_or_name, value):
         nodes = Nodes(self.api, [node_id])
         if not nodes:
     def call(self, auth, node_id, tag_type_id_or_name, value):
         nodes = Nodes(self.api, [node_id])
         if not nodes:
@@ -63,22 +58,19 @@ class AddNodeTag(Method):
 
         if len(conflicts) :
             raise PLCInvalidArgument, "Node %d already has tag %d"%(node['node_id'],
 
         if len(conflicts) :
             raise PLCInvalidArgument, "Node %d already has tag %d"%(node['node_id'],
-                                                                               tag_type['tag_type_id'])
-
-        # check permission : it not admin, is the user affiliated with the right site
-        if 'admin' not in self.caller['roles']:
-            # locate node
-            node = Nodes (self.api,[node['node_id']])[0]
-            # locate site
-            site = Sites (self.api, [node['site_id']])[0]
-            # check caller is affiliated with this site
-            if self.caller['person_id'] not in site['person_ids']:
-                raise PLCPermissionDenied, "Not a member of the hosting site %s"%site['abbreviated_site']
-
-            required_min_role = tag_type ['min_role_id']
-            if required_min_role is not None and \
-                    min(self.caller['role_ids']) > required_min_role:
-                raise PLCPermissionDenied, "Not allowed to modify the specified node tag, requires role %d"%required_min_role
+                                                                    tag_type['tag_type_id'])
+
+
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        elif not AuthorizeHelpers.person_access_tag_type (self.api, self.caller, tag_type):
+            raise PLCPermissionDenied, "%s, no permission to use this tag type"%self.name
+        elif AuthorizeHelpers.node_belongs_to_person (self.api, node, self.caller):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you must belong in the same site as subject node"%self.name
+
 
         node_tag = NodeTag(self.api)
         node_tag['node_id'] = node['node_id']
 
         node_tag = NodeTag(self.api)
         node_tag['node_id'] = node['node_id']
index 7c4d67d..8840975 100644 (file)
@@ -1,5 +1,3 @@
-# $Id$
-# $URL$
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
index 7f22bee..6bba377 100644 (file)
@@ -1,28 +1,23 @@
-# $Id: AddPersonTag.py 14587 2009-07-19 13:18:50Z thierry $
-# $URL: http://svn.planet-lab.org/svn/PLCAPI/tags/PLCAPI-4.3-27/PLC/Methods/AddPersonTag.py $
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
-# $Revision: 14587 $
-#
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
+from PLC.Persons import Person, Persons
 from PLC.TagTypes import TagType, TagTypes
 from PLC.PersonTags import PersonTag, PersonTags
 from PLC.TagTypes import TagType, TagTypes
 from PLC.PersonTags import PersonTag, PersonTags
-from PLC.Persons import Person, Persons
 
 
-from PLC.Nodes import Nodes
+from PLC.AuthorizeHelpers import AuthorizeHelpers
 
 class AddPersonTag(Method):
     """
     Sets the specified setting for the specified person
     to the specified value.
 
 
 class AddPersonTag(Method):
     """
     Sets the specified setting for the specified person
     to the specified value.
 
-    In general only tech(s), PI(s) and of course admin(s) are allowed to
-    do the change, but this is defined in the tag type object.
+    Admins have full access.  Non-admins can change their own tags.
 
     Returns the new person_tag_id (> 0) if successful, faults
     otherwise.
 
     Returns the new person_tag_id (> 0) if successful, faults
     otherwise.
@@ -41,9 +36,6 @@ class AddPersonTag(Method):
 
     returns = Parameter(int, 'New person_tag_id (> 0) if successful')
 
 
     returns = Parameter(int, 'New person_tag_id (> 0) if successful')
 
-    object_type = 'Person'
-
-
     def call(self, auth, person_id, tag_type_id_or_name, value):
         persons = Persons(self.api, [person_id])
         if not persons:
     def call(self, auth, person_id, tag_type_id_or_name, value):
         persons = Persons(self.api, [person_id])
         if not persons:
@@ -56,24 +48,22 @@ class AddPersonTag(Method):
         tag_type = tag_types[0]
 
         # checks for existence - does not allow several different settings
         tag_type = tag_types[0]
 
         # checks for existence - does not allow several different settings
-        conflicts = PersonTags(self.api,
-                                        {'person_id':person['person_id'],
-                                         'tag_type_id':tag_type['tag_type_id']})
+        conflicts = PersonTags(self.api, {'person_id':person['person_id'],
+                                          'tag_type_id':tag_type['tag_type_id']})
 
         if len(conflicts) :
 
         if len(conflicts) :
-            raise PLCInvalidArgument, "Person %d already has setting %d"%(person['person_id'],
-                                                                               tag_type['tag_type_id'])
-
-        # check permission : it not admin, is the user affiliated with the same site as this person
-        if 'admin' not in self.caller['roles']:
-            # check caller is affiliated with at least one of Person's sites
-            if len(set(person['site_ids']) & set(self.caller['site_ids'])) == 0:
-                raise PLCPermissionDenied, "Not a member of the person's sites: %s"%person['site_ids']
-
-            required_min_role = tag_type ['min_role_id']
-            if required_min_role is not None and \
-                    min(self.caller['role_ids']) > required_min_role:
-                raise PLCPermissionDenied, "Not allowed to modify the specified person setting, requires role %d",required_min_role
+            raise PLCInvalidArgument, "Person %d (%s) already has setting %d"% \
+                (person['person_id'],person['email'], tag_type['tag_type_id'])
+
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        # user can change tags on self
+        elif AuthorizeHelpers.person_access_person (self.api, self.caller, person):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you can only change your own tags"%self.name
+
 
         person_tag = PersonTag(self.api)
         person_tag['person_id'] = person['person_id']
 
         person_tag = PersonTag(self.api)
         person_tag['person_id'] = person['person_id']
index 458b40b..1e47033 100644 (file)
@@ -1,5 +1,3 @@
-# $Id$
-# $URL$
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
diff --git a/PLC/Methods/AddRoleToTagType.py b/PLC/Methods/AddRoleToTagType.py
new file mode 100644 (file)
index 0000000..947adcd
--- /dev/null
@@ -0,0 +1,58 @@
+from PLC.Faults import *
+from PLC.Method import Method
+from PLC.Auth import Auth
+from PLC.Parameter import Parameter, Mixed
+from PLC.TagTypes import TagType, TagTypes
+from PLC.Roles import Role, Roles
+
+class AddRoleToTagType(Method):
+    """
+    Add the specified role to the tagtype so that 
+    users with that role can tweak the tag.
+
+    Only admins can call this method
+
+    Returns 1 if successful, faults otherwise.
+    """
+
+    roles = ['admin']
+
+    accepts = [
+        Auth(),
+        Mixed(Role.fields['role_id'],
+              Role.fields['name']),
+        Mixed(TagType.fields['tag_type_id'],
+              TagType.fields['tagname']),
+        ]
+
+    returns = Parameter(int, '1 if successful')
+
+    def call(self, auth, role_id_or_name, tag_type_id_or_tagname):
+        # Get role
+        roles = Roles(self.api, [role_id_or_name])
+        if not roles:
+            raise PLCInvalidArgument, "Invalid role '%s'" % unicode(role_id_or_name)
+        role = roles[0]
+
+        # Get subject tag type
+        tag_types = TagTypes(self.api, [tag_type_id_or_tagname])
+        if not tag_types:
+            raise PLCInvalidArgument, "No such tag type"
+        tag_type = tag_types[0]
+
+        # Authenticated function
+        assert self.caller is not None
+
+        # Only admins 
+        if 'admin' not in self.caller['roles']: 
+            raise PLCInvalidArgument, "Not allowed to grant that role"
+
+        if role['role_id'] not in tag_type['role_ids']:
+            tag_type.add_role(role)
+
+        self.event_objects = {'TagType': [tag_type['tag_type_id']],
+                              'Role': [role['role_id']]}
+        self.message = "Role %d added to tag_type %d" % \
+            (role['role_id'], tag_type['tag_type_id'])
+
+        return 1
index 9bc5ef7..cde238f 100644 (file)
@@ -1,29 +1,26 @@
-# $Id: AddSiteTag.py 14587 2009-07-19 13:18:50Z thierry $
-# $URL: http://svn.planet-lab.org/svn/PLCAPI/tags/PLCAPI-4.3-27/PLC/Methods/AddSiteTag.py $
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
-# $Revision: 14587 $
-#
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
+from PLC.Sites import Site, Sites
+from PLC.Nodes import Nodes
 from PLC.TagTypes import TagType, TagTypes
 from PLC.SiteTags import SiteTag, SiteTags
 from PLC.TagTypes import TagType, TagTypes
 from PLC.SiteTags import SiteTag, SiteTags
-from PLC.Sites import Site, Sites
 
 
-from PLC.Nodes import Nodes
-from PLC.Sites import Sites
+from PLC.AuthorizeHelpers import AuthorizeHelpers
 
 class AddSiteTag(Method):
     """
     Sets the specified setting for the specified site
     to the specified value.
 
 
 class AddSiteTag(Method):
     """
     Sets the specified setting for the specified site
     to the specified value.
 
-    In general only tech(s), PI(s) and of course admin(s) are allowed to
-    do the change, but this is defined in the tag type object.
+    Admins have full access.  Non-admins need to 
+    (1) have at least one of the roles attached to the tagtype, 
+    and (2) belong in the same site as the tagged subject.
 
     Returns the new site_tag_id (> 0) if successful, faults
     otherwise.
 
     Returns the new site_tag_id (> 0) if successful, faults
     otherwise.
@@ -42,9 +39,6 @@ class AddSiteTag(Method):
 
     returns = Parameter(int, 'New site_tag_id (> 0) if successful')
 
 
     returns = Parameter(int, 'New site_tag_id (> 0) if successful')
 
-    object_type = 'Site'
-
-
     def call(self, auth, site_id, tag_type_id_or_name, value):
         sites = Sites(self.api, [site_id])
         if not sites:
     def call(self, auth, site_id, tag_type_id_or_name, value):
         sites = Sites(self.api, [site_id])
         if not sites:
@@ -58,26 +52,23 @@ class AddSiteTag(Method):
 
         # checks for existence - does not allow several different settings
         conflicts = SiteTags(self.api,
 
         # checks for existence - does not allow several different settings
         conflicts = SiteTags(self.api,
-                                        {'site_id':site['site_id'],
-                                         'tag_type_id':tag_type['tag_type_id']})
+                             {'site_id':site['site_id'],
+                              'tag_type_id':tag_type['tag_type_id']})
 
         if len(conflicts) :
             raise PLCInvalidArgument, "Site %d already has setting %d"%(site['site_id'],
 
         if len(conflicts) :
             raise PLCInvalidArgument, "Site %d already has setting %d"%(site['site_id'],
-                                                                               tag_type['tag_type_id'])
-
-        # check permission : it not admin, is the user affiliated with the right site
-        if 'admin' not in self.caller['roles']:
-            # locate site
-            site = Sites (self.api, site_id)[0]
-            # check caller is affiliated with this site
-            if self.caller['person_id'] not in site['person_ids']:
-                raise PLCPermissionDenied, "Not a member of the hosting site %s"%site['abbreviated_site']
-
-            required_min_role = tag_type ['min_role_id']
-            if required_min_role is not None and \
-                    min(self.caller['role_ids']) > required_min_role:
-                raise PLCPermissionDenied, "Not allowed to modify the specified site setting, requires role %d",required_min_role
-
+                                                                        tag_type['tag_type_id'])
+
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        elif not AuthorizeHelpers.person_access_tag_type (self.api, self.caller, tag_type):
+            raise PLCPermissionDenied, "%s, no permission to use this tag type"%self.name
+        elif AuthorizeHelpers.person_belongs_to_site (self.api, self.caller, site):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you must be part of the subject site"%self.name
+            
         site_tag = SiteTag(self.api)
         site_tag['site_id'] = site['site_id']
         site_tag['tag_type_id'] = tag_type['tag_type_id']
         site_tag = SiteTag(self.api)
         site_tag['site_id'] = site['site_id']
         site_tag['tag_type_id'] = tag_type['tag_type_id']
index e55aa7c..a01bb12 100644 (file)
@@ -1,15 +1,19 @@
-# $Id$
-# $URL$
+#
+# Thierry Parmentelat - INRIA
+#
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
+from PLC.Auth import Auth
+
 from PLC.TagTypes import TagType, TagTypes
 from PLC.Slices import Slice, Slices
 from PLC.Nodes import Node, Nodes
 from PLC.SliceTags import SliceTag, SliceTags
 from PLC.NodeGroups import NodeGroup, NodeGroups
 from PLC.InitScripts import InitScript, InitScripts
 from PLC.TagTypes import TagType, TagTypes
 from PLC.Slices import Slice, Slices
 from PLC.Nodes import Node, Nodes
 from PLC.SliceTags import SliceTag, SliceTags
 from PLC.NodeGroups import NodeGroup, NodeGroups
 from PLC.InitScripts import InitScript, InitScripts
-from PLC.Auth import Auth
+
+from PLC.AuthorizeHelpers import AuthorizeHelpers
 
 class AddSliceTag(Method):
     """
 
 class AddSliceTag(Method):
     """
@@ -122,8 +126,8 @@ class AddSliceTag(Method):
 
         # Check if slice attribute alreay exists
         slice_tags_check = SliceTags(self.api, {'slice_id': slice['slice_id'],
 
         # Check if slice attribute alreay exists
         slice_tags_check = SliceTags(self.api, {'slice_id': slice['slice_id'],
-                                                            'tagname': tag_type['tagname'],
-                                                            'value': value})
+                                                'tagname': tag_type['tagname'],
+                                                'value': value})
         for slice_tag_check in slice_tags_check:
             # do not compare between slice tag and sliver tag
             if 'node_id' not in slice_tag and slice_tag_check['node_id'] is not None:
         for slice_tag_check in slice_tags_check:
             # do not compare between slice tag and sliver tag
             if 'node_id' not in slice_tag and slice_tag_check['node_id'] is not None:
index 336edb3..4319c12 100644 (file)
@@ -14,7 +14,7 @@ from PLC.TagTypes import TagType, TagTypes
 from PLC.Auth import Auth
 
 can_update = lambda (field, value): field in \
 from PLC.Auth import Auth
 
 can_update = lambda (field, value): field in \
-             ['tagname', 'description', 'category', 'min_role_id']
+             ['tagname', 'description', 'category']
 
 class AddTagType(Method):
     """
 
 class AddTagType(Method):
     """
index 40780ad..6452b0d 100644 (file)
@@ -1,10 +1,6 @@
-# $Id$
-# $URL$
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
-# $Revision: 9423 $
-#
 
 from PLC.Faults import *
 from PLC.Method import Method
 
 from PLC.Faults import *
 from PLC.Method import Method
@@ -17,6 +13,8 @@ from PLC.Nodes import Node, Nodes
 from PLC.Sites import Site, Sites
 from PLC.TagTypes import TagType, TagTypes
 
 from PLC.Sites import Site, Sites
 from PLC.TagTypes import TagType, TagTypes
 
+from PLC.AuthorizeHelpers import AuthorizeHelpers
+
 class DeleteIlink(Method):
     """
     Deletes the specified ilink
 class DeleteIlink(Method):
     """
     Deletes the specified ilink
@@ -46,29 +44,24 @@ class DeleteIlink(Method):
             raise PLCInvalidArgument, "No such ilink %r"%ilink_id
         ilink = ilinks[0]
 
             raise PLCInvalidArgument, "No such ilink %r"%ilink_id
         ilink = ilinks[0]
 
+        src_if=Interfaces(self.api,ilink['src_interface_id'])[0]
+        dst_if=Interfaces(self.api,ilink['dst_interface_id'])[0]
+        
         tag_type_id = ilink['tag_type_id']
         tag_type = TagTypes (self.api,[tag_type_id])[0]
         tag_type_id = ilink['tag_type_id']
         tag_type = TagTypes (self.api,[tag_type_id])[0]
-        required_min_role = tag_type ['min_role_id']
-
-        # check permission : it not admin, is the user affiliated with the right site<S>
-        if 'admin' not in self.caller['roles']:
-            for key in ['src_interface_id','dst_interface_id']:
-                # locate interface
-                interface_id=ilink[key]
-                interface = Interfaces (self.api,interface_id)[0]
-                node_id=interface['node_id']
-                node = Nodes (self.api,node_id) [0]
-                # locate site
-                site_id = node['site_id']
-                site = Sites (self.api, [site_id]) [0]
-                # check caller is affiliated with this site
-                if self.caller['person_id'] not in site['person_ids']:
-                    raise PLCPermissionDenied, "Not a member of the hosting site %s"%site['abbreviated_site']
-
-                if required_min_role is not None and \
-                        min(self.caller['role_ids']) > required_min_role:
-                    raise PLCPermissionDenied, "Not allowed to modify the specified ilink, requires role %d",required_min_role
 
 
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        elif not AuthorizeHelpers.person_access_tag_type (self.api, self.caller, tag_type):
+            raise PLCPermissionDenied, "%s, no permission to use this tag type"%self.name
+        elif AuthorizeHelpers.interface_belongs_to_person (self.api, src_if, self.caller):
+            pass
+        elif src_if_id != dst_if_id and AuthorizeHelpers.interface_belongs_to_person (self.api, dst_if, self.caller):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you must own either the src or dst interface"%self.name
+            
         ilink.delete()
         self.object_ids = [ilink['src_interface_id'],ilink['dst_interface_id']]
 
         ilink.delete()
         self.object_ids = [ilink['src_interface_id'],ilink['dst_interface_id']]
 
index 4475f5d..229a0d7 100644 (file)
@@ -1,5 +1,3 @@
-# $Id$
-# $URL$
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
index 67b2bbb..187d25e 100644 (file)
@@ -1,34 +1,29 @@
-# $Id$
-# $URL$
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
-# $Revision$
-#
-
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
-from PLC.InterfaceTags import InterfaceTag, InterfaceTags
+from PLC.Sites import Sites
+from PLC.Nodes import Nodes
 from PLC.Interfaces import Interface, Interfaces
 from PLC.Interfaces import Interface, Interfaces
-
-from PLC.Nodes import Node, Nodes
-from PLC.Sites import Site, Sites
+from PLC.TagTypes import TagType, TagTypes
+from PLC.InterfaceTags import InterfaceTag, InterfaceTags
 
 class DeleteInterfaceTag(Method):
     """
     Deletes the specified interface setting
 
 
 class DeleteInterfaceTag(Method):
     """
     Deletes the specified interface setting
 
-    Attributes may require the caller to have a particular role in order
-    to be deleted, depending on the related tag type.
-    Admins may delete attributes of any slice or sliver.
+    Admins have full access.  Non-admins need to 
+    (1) have at least one of the roles attached to the tagtype, 
+    and (2) belong in the same site as the tagged subject.
 
     Returns 1 if successful, faults otherwise.
     """
 
 
     Returns 1 if successful, faults otherwise.
     """
 
-    roles = ['admin', 'pi', 'user']
+    roles = ['admin', 'pi', 'user', 'tech']
 
     accepts = [
         Auth(),
 
     accepts = [
         Auth(),
@@ -37,37 +32,25 @@ class DeleteInterfaceTag(Method):
 
     returns = Parameter(int, '1 if successful')
 
 
     returns = Parameter(int, '1 if successful')
 
-    object_type = 'Interface'
-
-
     def call(self, auth, interface_tag_id):
         interface_tags = InterfaceTags(self.api, [interface_tag_id])
         if not interface_tags:
             raise PLCInvalidArgument, "No such interface tag %r"%interface_tag_id
         interface_tag = interface_tags[0]
 
     def call(self, auth, interface_tag_id):
         interface_tags = InterfaceTags(self.api, [interface_tag_id])
         if not interface_tags:
             raise PLCInvalidArgument, "No such interface tag %r"%interface_tag_id
         interface_tag = interface_tags[0]
 
-        ### reproducing a check from UpdateSliceTag, looks dumb though
-        interfaces = Interfaces(self.api, [interface_tag['interface_id']])
-        if not interfaces:
-            raise PLCInvalidArgument, "No such interface %r"%interface_tag['interface_id']
-        interface = interfaces[0]
-
-        assert interface_tag['interface_tag_id'] in interface['interface_tag_ids']
-
-        # check permission : it not admin, is the user affiliated with the right site
-        if 'admin' not in self.caller['roles']:
-            # locate node
-            node = Nodes (self.api,[interface['node_id']])[0]
-            # locate site
-            site = Sites (self.api, [node['site_id']])[0]
-            # check caller is affiliated with this site
-            if self.caller['person_id'] not in site['person_ids']:
-                raise PLCPermissionDenied, "Not a member of the hosting site %s"%site['abbreviated_site']
-
-            required_min_role = tag_type ['min_role_id']
-            if required_min_role is not None and \
-                    min(self.caller['role_ids']) > required_min_role:
-                raise PLCPermissionDenied, "Not allowed to modify the specified interface setting, requires role %d",required_min_role
+        tag_type_id = interface_tag['tag_type_id']
+        tag_type = TagTypes (self.api,[tag_type_id])[0]
+        interface = Interfaces (self.api, interface_tag['interface_id'])
+
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        elif not AuthorizeHelpers.person_access_tag_type (self.api, self.caller, tag_type):
+            raise PLCPermissionDenied, "%s, no permission to use this tag type"%self.name
+        elif AuthorizeHelpers.interface_belongs_to_person (self.api, interface, self.caller):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you must belong in the same site as subject interface"%self.name
 
         interface_tag.delete()
         self.object_ids = [interface_tag['interface_tag_id']]
 
         interface_tag.delete()
         self.object_ids = [interface_tag['interface_tag_id']]
index 9b3fdb8..bd99f0e 100644 (file)
@@ -1,34 +1,31 @@
-# $Id$
-# $URL$
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
-# $Revision: 9423 $
-#
 
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
 
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
-from PLC.NodeTags import NodeTag, NodeTags
+from PLC.Sites import Site, Sites
 from PLC.Nodes import Node, Nodes
 from PLC.Nodes import Node, Nodes
+from PLC.TagTypes import TagType, TagTypes
+from PLC.NodeTags import NodeTag, NodeTags
 
 
-from PLC.Nodes import Node, Nodes
-from PLC.Sites import Site, Sites
+from PLC.AuthorizeHelpers import AuthorizeHelpers
 
 class DeleteNodeTag(Method):
     """
     Deletes the specified node tag
 
 
 class DeleteNodeTag(Method):
     """
     Deletes the specified node tag
 
-    Attributes may require the caller to have a particular role in order
-    to be deleted, depending on the related node tag type.
-    Admins may delete attributes of any slice or sliver.
+    Admins have full access.  Non-admins need to 
+    (1) have at least one of the roles attached to the tagtype, 
+    and (2) belong in the same site as the tagged subject.
 
     Returns 1 if successful, faults otherwise.
     """
 
 
     Returns 1 if successful, faults otherwise.
     """
 
-    roles = ['admin', 'pi', 'user']
+    roles = ['admin', 'pi', 'user', 'tech']
 
     accepts = [
         Auth(),
 
     accepts = [
         Auth(),
@@ -37,37 +34,25 @@ class DeleteNodeTag(Method):
 
     returns = Parameter(int, '1 if successful')
 
 
     returns = Parameter(int, '1 if successful')
 
-    object_type = 'Node'
-
-
     def call(self, auth, node_tag_id):
         node_tags = NodeTags(self.api, [node_tag_id])
         if not node_tags:
             raise PLCInvalidArgument, "No such node tag %r"%node_tag_id
         node_tag = node_tags[0]
 
     def call(self, auth, node_tag_id):
         node_tags = NodeTags(self.api, [node_tag_id])
         if not node_tags:
             raise PLCInvalidArgument, "No such node tag %r"%node_tag_id
         node_tag = node_tags[0]
 
-        ### reproducing a check from UpdateSliceTag, looks dumb though
-        nodes = Nodes(self.api, [node_tag['node_id']])
-        if not nodes:
-            raise PLCInvalidArgument, "No such node %r"%node_tag['node_id']
-        node = nodes[0]
-
-        assert node_tag['node_tag_id'] in node['node_tag_ids']
-
-        # check permission : it not admin, is the user affiliated with the right site
-        if 'admin' not in self.caller['roles']:
-            # locate node
-            node = Nodes (self.api,[node['node_id']])[0]
-            # locate site
-            site = Sites (self.api, [node['site_id']])[0]
-            # check caller is affiliated with this site
-            if self.caller['person_id'] not in site['person_ids']:
-                raise PLCPermissionDenied, "Not a member of the hosting site %s"%site['abbreviated_site']
-
-            required_min_role = tag_type ['min_role_id']
-            if required_min_role is not None and \
-                    min(self.caller['role_ids']) > required_min_role:
-                raise PLCPermissionDenied, "Not allowed to modify the specified node tag, requires role %d",required_min_role
+        tag_type_id = node_tag['tag_type_id']
+        tag_type = TagTypes (self.api,[tag_type_id])[0]
+        node = Nodes (self.api, node_tag['node_id'])
+
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        elif not AuthorizeHelpers.person_access_tag_type (self.api, self.caller, tag_type):
+            raise PLCPermissionDenied, "%s, no permission to use this tag type"%self.name
+        elif AuthorizeHelpers.node_belongs_to_person (self.api, node, self.caller):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you must belong in the same site as subject node"%self.name
 
         node_tag.delete()
         self.object_ids = [node_tag['node_tag_id']]
 
         node_tag.delete()
         self.object_ids = [node_tag['node_tag_id']]
index e4abcdd..19ab5fe 100644 (file)
@@ -1,11 +1,6 @@
-# $Id: DeletePersonTag.py 14587 2009-07-19 13:18:50Z thierry $
-# $URL: http://svn.planet-lab.org/svn/PLCAPI/tags/PLCAPI-4.3-27/PLC/Methods/DeletePersonTag.py $
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
-# $Revision: 14587 $
-#
-
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
@@ -14,16 +9,13 @@ from PLC.Auth import Auth
 from PLC.PersonTags import PersonTag, PersonTags
 from PLC.Persons import Person, Persons
 
 from PLC.PersonTags import PersonTag, PersonTags
 from PLC.Persons import Person, Persons
 
-from PLC.Nodes import Node, Nodes
-from PLC.Persons import Person, Persons
+from PLC.AuthorizeHelpers import AuthorizeHelpers
 
 class DeletePersonTag(Method):
     """
     Deletes the specified person setting
 
 
 class DeletePersonTag(Method):
     """
     Deletes the specified person setting
 
-    Attributes may require the caller to have a particular role in order
-    to be deleted, depending on the related tag type.
-    Admins may delete attributes of any slice or sliver.
+    Admins have full access.  Non-admins can change their own tags.
 
     Returns 1 if successful, faults otherwise.
     """
 
     Returns 1 if successful, faults otherwise.
     """
@@ -37,33 +29,22 @@ class DeletePersonTag(Method):
 
     returns = Parameter(int, '1 if successful')
 
 
     returns = Parameter(int, '1 if successful')
 
-    object_type = 'Person'
-
-
     def call(self, auth, person_tag_id):
         person_tags = PersonTags(self.api, [person_tag_id])
         if not person_tags:
             raise PLCInvalidArgument, "No such person tag %r"%person_tag_id
         person_tag = person_tags[0]
 
     def call(self, auth, person_tag_id):
         person_tags = PersonTags(self.api, [person_tag_id])
         if not person_tags:
             raise PLCInvalidArgument, "No such person tag %r"%person_tag_id
         person_tag = person_tags[0]
 
-        ### reproducing a check from UpdateSliceTag, looks dumb though
-        persons = Persons(self.api, [person_tag['person_id']])
-        if not persons:
-            raise PLCInvalidArgument, "No such person %r"%person_tag['person_id']
-        person = persons[0]
-
-        assert person_tag['person_tag_id'] in person['person_tag_ids']
-
-        # check permission : it not admin, is the user affiliated with the right person
-        if 'admin' not in self.caller['roles']:
-            # check caller is affiliated with this person's site
-            if len(set(person['site_ids']) & set(self.caller['site_ids'])) == 0:
-                raise PLCPermissionDenied, "Not a member of the person's sites: %s"%person['site_ids']
+        person = Persons (self.api, person_tag['person_id'])[0]
 
 
-            required_min_role = tag_type ['min_role_id']
-            if required_min_role is not None and \
-                    min(self.caller['role_ids']) > required_min_role:
-                raise PLCPermissionDenied, "Not allowed to modify the specified person setting, requires role %d",required_min_role
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        # user can change tags on self
+        elif AuthorizeHelpers.person_access_person (self.api, self.caller, person):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you can only change your own tags"%self.name
 
         person_tag.delete()
         self.object_ids = [person_tag['person_tag_id']]
 
         person_tag.delete()
         self.object_ids = [person_tag['person_tag_id']]
index 28dedfb..4deacf6 100644 (file)
@@ -1,5 +1,3 @@
-# $Id$
-# $URL$
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
diff --git a/PLC/Methods/DeleteRoleFromTagType.py b/PLC/Methods/DeleteRoleFromTagType.py
new file mode 100644 (file)
index 0000000..cdce6fa
--- /dev/null
@@ -0,0 +1,59 @@
+from PLC.Faults import *
+from PLC.Method import Method
+from PLC.Parameter import Parameter, Mixed
+from PLC.TagTypes import TagType, TagTypes
+from PLC.Auth import Auth
+from PLC.Roles import Role, Roles
+
+class DeleteRoleFromTagType(Method):
+    """
+    Delete the specified role from the tagtype so that 
+    users with that role can no longer tweak the tag.
+
+    Only admins can call this method
+
+    Returns 1 if successful, faults otherwise.
+    """
+
+    roles = ['admin']
+
+    accepts = [
+        Auth(),
+        Mixed(Role.fields['role_id'],
+              Role.fields['name']),
+        Mixed(TagType.fields['tag_type_id'],
+              TagType.fields['tagname']),
+        ]
+
+    returns = Parameter(int, '1 if successful')
+
+    def call(self, auth, role_id_or_name, tag_type_id_or_tagname):
+        # Get role
+        roles = Roles(self.api, [role_id_or_name])
+        if not roles:
+            raise PLCInvalidArgument, "Invalid role '%s'" % unicode(role_id_or_name)
+        role = roles[0]
+
+        # Get subject tag type
+        tag_types = TagTypes(self.api, [tag_type_id_or_tagname])
+        if not tag_types:
+            raise PLCInvalidArgument, "No such tag type"
+        tag_type = tag_types[0]
+
+        # Authenticated function
+        assert self.caller is not None
+
+        # Only admins 
+        if 'admin' not in self.caller['roles']: 
+            raise PLCInvalidArgument, "Not allowed to revoke that role"
+
+        if role['role_id'] in tag_type['role_ids']:
+            tag_type.remove_role(role)
+
+        # Logging variables
+        self.event_objects = {'TagType': [tag_type['tag_type_id']],
+                              'Role': [role['role_id']]}
+        self.message = "Role %d revoked from tag_type %d" % \
+                       (role['role_id'], tag_type['tag_type_id'])
+
+        return 1
index 9776275..db2b294 100644 (file)
@@ -1,5 +1,3 @@
-# $Id$
-# $URL$
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
index ab22400..f0e87c3 100644 (file)
@@ -1,29 +1,25 @@
-# $Id: DeleteSiteTag.py 14587 2009-07-19 13:18:50Z thierry $
-# $URL: http://svn.planet-lab.org/svn/PLCAPI/tags/PLCAPI-4.3-27/PLC/Methods/DeleteSiteTag.py $
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
-# $Revision: 14587 $
-#
-
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
-from PLC.SiteTags import SiteTag, SiteTags
 from PLC.Sites import Site, Sites
 from PLC.Sites import Site, Sites
+from PLC.Nodes import Nodes
+from PLC.TagTypes import TagType, TagTypes
+from PLC.SiteTags import SiteTag, SiteTags
 
 
-from PLC.Nodes import Node, Nodes
-from PLC.Sites import Site, Sites
+from PLC.AuthorizeHelpers import AuthorizeHelpers
 
 class DeleteSiteTag(Method):
     """
     Deletes the specified site setting
 
 
 class DeleteSiteTag(Method):
     """
     Deletes the specified site setting
 
-    Attributes may require the caller to have a particular role in order
-    to be deleted, depending on the related tag type.
-    Admins may delete attributes of any slice or sliver.
+    Admins have full access.  Non-admins need to 
+    (1) have at least one of the roles attached to the tagtype, 
+    and (2) belong in the same site as the tagged subject.
 
     Returns 1 if successful, faults otherwise.
     """
 
     Returns 1 if successful, faults otherwise.
     """
@@ -37,34 +33,26 @@ class DeleteSiteTag(Method):
 
     returns = Parameter(int, '1 if successful')
 
 
     returns = Parameter(int, '1 if successful')
 
-    object_type = 'Site'
-
-
     def call(self, auth, site_tag_id):
         site_tags = SiteTags(self.api, [site_tag_id])
         if not site_tags:
             raise PLCInvalidArgument, "No such site tag %r"%site_tag_id
         site_tag = site_tags[0]
 
     def call(self, auth, site_tag_id):
         site_tags = SiteTags(self.api, [site_tag_id])
         if not site_tags:
             raise PLCInvalidArgument, "No such site tag %r"%site_tag_id
         site_tag = site_tags[0]
 
-        ### reproducing a check from UpdateSliceTag, looks dumb though
-        sites = Sites(self.api, [site_tag['site_id']])
-        if not sites:
-            raise PLCInvalidArgument, "No such site %r"%site_tag['site_id']
-        site = sites[0]
-
-        assert site_tag['site_tag_id'] in site['site_tag_ids']
-
-        # check permission : it not admin, is the user affiliated with the right site
-        if 'admin' not in self.caller['roles']:
-            # check caller is affiliated with this site
-            if self.caller['person_id'] not in site['person_ids']:
-                raise PLCPermissionDenied, "Not a member of the hosting site %s"%site['abbreviated_site']
-
-            required_min_role = tag_type ['min_role_id']
-            if required_min_role is not None and \
-                    min(self.caller['role_ids']) > required_min_role:
-                raise PLCPermissionDenied, "Not allowed to modify the specified site setting, requires role %d",required_min_role
-
+        tag_type_id = site_tag['tag_type_id']
+        tag_type = TagTypes (self.api,[tag_type_id])[0]
+        site = Sites (self.api, site_tag['site_id'])
+        
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        elif not AuthorizeHelpers.person_access_tag_type (self.api, self.caller, tag_type):
+            raise PLCPermissionDenied, "%s, no permission to use this tag type"%self.name
+        elif AuthorizeHelpers.person_belongs_to_site (self.api, self.caller, site):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you must be part of the subject site"%self.name
+            
         site_tag.delete()
         self.object_ids = [site_tag['site_tag_id']]
 
         site_tag.delete()
         self.object_ids = [site_tag['site_tag_id']]
 
index 9e2ad06..e63393e 100644 (file)
@@ -1,12 +1,16 @@
-# $Id$
-# $URL$
+#
+# Thierry Parmentelat - INRIA
+#
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
+from PLC.Auth import Auth
+
 from PLC.SliceTags import SliceTag, SliceTags
 from PLC.Slices import Slice, Slices
 from PLC.Nodes import Node, Nodes
 from PLC.SliceTags import SliceTag, SliceTags
 from PLC.Slices import Slice, Slices
 from PLC.Nodes import Node, Nodes
-from PLC.Auth import Auth
+
+from PLC.AuthorizeHelpers import AuthorizeHelpers
 
 class DeleteSliceTag(Method):
     """
 
 class DeleteSliceTag(Method):
     """
@@ -21,7 +25,7 @@ class DeleteSliceTag(Method):
     Returns 1 if successful, faults otherwise.
     """
 
     Returns 1 if successful, faults otherwise.
     """
 
-    roles = ['admin', 'pi', 'user']
+    roles = ['admin', 'pi', 'user', 'tech']
 
     accepts = [
         Auth(),
 
     accepts = [
         Auth(),
index dae4633..05daf17 100644 (file)
@@ -1,10 +1,6 @@
-# $Id$
-# $URL$
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
-# $Revision: 9423 $
-#
 
 from PLC.Faults import *
 from PLC.Method import Method
 
 from PLC.Faults import *
 from PLC.Method import Method
@@ -13,9 +9,11 @@ from PLC.Auth import Auth
 
 from PLC.Ilinks import Ilink, Ilinks
 from PLC.Interfaces import Interface, Interfaces
 
 from PLC.Ilinks import Ilink, Ilinks
 from PLC.Interfaces import Interface, Interfaces
-
+from PLC.TagTypes import TagType, TagTypes
 from PLC.Sites import Sites
 
 from PLC.Sites import Sites
 
+from PLC.AuthorizeHelpers import AuthorizeHelpers
+
 class UpdateIlink(Method):
     """
     Updates the value of an existing ilink
 class UpdateIlink(Method):
     """
     Updates the value of an existing ilink
@@ -43,9 +41,23 @@ class UpdateIlink(Method):
             raise PLCInvalidArgument, "No such ilink %r"%ilink_id
         ilink = ilinks[0]
 
             raise PLCInvalidArgument, "No such ilink %r"%ilink_id
         ilink = ilinks[0]
 
-        # xxx see AddIlink for this - should be written once in the Ilink class I guess
-        # checks rights and stuff
+        src_if=Interfaces(self.api,ilink['src_interface_id'])[0]
+        dst_if=Interfaces(self.api,ilink['dst_interface_id'])[0]
+        tag_type_id = ilink['tag_type_id']
+        tag_type = TagTypes (self.api,[tag_type_id])[0]
 
 
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        elif not AuthorizeHelpers.person_access_tag_type (self.api, self.caller, tag_type):
+            raise PLCPermissionDenied, "%s, no permission to use this tag type"%self.name
+        elif AuthorizeHelpers.interface_belongs_to_person (self.api, src_if, self.caller):
+            pass
+        elif src_if_id != dst_if_id and AuthorizeHelpers.interface_belongs_to_person (self.api, dst_if, self.caller):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you must own either the src or dst interface"%self.name
+            
         ilink['value'] = value
         ilink.sync()
 
         ilink['value'] = value
         ilink.sync()
 
index 4a3f02f..e29041f 100644 (file)
@@ -1,27 +1,24 @@
-# $Id$
-# $URL$
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
-# $Revision$
-#
-
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
-from PLC.InterfaceTags import InterfaceTag, InterfaceTags
-from PLC.Interfaces import Interface, Interfaces
-
-from PLC.Nodes import Nodes
 from PLC.Sites import Sites
 from PLC.Sites import Sites
+from PLC.Nodes import Nodes
+from PLC.Interfaces import Interface, Interfaces
+from PLC.TagTypes import TagType, TagTypes
+from PLC.InterfaceTags import InterfaceTag, InterfaceTags
 
 class UpdateInterfaceTag(Method):
     """
     Updates the value of an existing interface setting
 
 
 class UpdateInterfaceTag(Method):
     """
     Updates the value of an existing interface setting
 
-    Access rights depend on the tag type.
+    Admins have full access.  Non-admins need to 
+    (1) have at least one of the roles attached to the tagtype, 
+    and (2) belong in the same site as the tagged subject.
 
     Returns 1 if successful, faults otherwise.
     """
 
     Returns 1 if successful, faults otherwise.
     """
@@ -36,36 +33,26 @@ class UpdateInterfaceTag(Method):
 
     returns = Parameter(int, '1 if successful')
 
 
     returns = Parameter(int, '1 if successful')
 
-    object_type = 'Interface'
-
     def call(self, auth, interface_tag_id, value):
         interface_tags = InterfaceTags(self.api, [interface_tag_id])
         if not interface_tags:
             raise PLCInvalidArgument, "No such interface setting %r"%interface_tag_id
         interface_tag = interface_tags[0]
 
     def call(self, auth, interface_tag_id, value):
         interface_tags = InterfaceTags(self.api, [interface_tag_id])
         if not interface_tags:
             raise PLCInvalidArgument, "No such interface setting %r"%interface_tag_id
         interface_tag = interface_tags[0]
 
-        ### reproducing a check from UpdateSliceTag, looks dumb though
-        interfaces = Interfaces(self.api, [interface_tag['interface_id']])
-        if not interfaces:
-            raise PLCInvalidArgument, "No such interface %r"%interface_tag['interface_id']
-        interface = interfaces[0]
-
-        assert interface_tag['interface_tag_id'] in interface['interface_tag_ids']
+        tag_type_id = interface_tag['tag_type_id']
+        tag_type = TagTypes (self.api,[tag_type_id])[0]
+        interface = Interfaces (self.api, interface_tag['interface_id'])
 
 
-        # check permission : it not admin, is the user affiliated with the right site
-        if 'admin' not in self.caller['roles']:
-            # locate node
-            node = Nodes (self.api,[interface['node_id']])[0]
-            # locate site
-            site = Sites (self.api, [node['site_id']])[0]
-            # check caller is affiliated with this site
-            if self.caller['person_id'] not in site['person_ids']:
-                raise PLCPermissionDenied, "Not a member of the hosting site %s"%site['abbreviated_site']
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        elif not AuthorizeHelpers.person_access_tag_type (self.api, self.caller, tag_type):
+            raise PLCPermissionDenied, "%s, no permission to use this tag type"%self.name
+        elif AuthorizeHelpers.interface_belongs_to_person (self.api, interface, self.caller):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you must belong in the same site as subject interface"%self.name
 
 
-            required_min_role = tag_type ['min_role_id']
-            if required_min_role is not None and \
-                    min(self.caller['role_ids']) > required_min_role:
-                raise PLCPermissionDenied, "Not allowed to modify the specified interface setting, requires role %d",required_min_role
 
         interface_tag['value'] = value
         interface_tag.sync()
 
         interface_tag['value'] = value
         interface_tag.sync()
index a783f16..3cc7891 100644 (file)
@@ -1,10 +1,6 @@
-# $Id$
-# $URL$
 #
 # Thierry Parmentelat - INRIA
 #
 #
 # Thierry Parmentelat - INRIA
 #
-# $Revision: 9423 $
-#
 
 from PLC.Faults import *
 from PLC.Method import Method
 
 from PLC.Faults import *
 from PLC.Method import Method
@@ -13,13 +9,18 @@ from PLC.Auth import Auth
 
 from PLC.Sites import Sites
 from PLC.Nodes import Node, Nodes
 
 from PLC.Sites import Sites
 from PLC.Nodes import Node, Nodes
+from PLC.TagTypes import TagType, TagTypes
 from PLC.NodeTags import NodeTag, NodeTags
 
 from PLC.NodeTags import NodeTag, NodeTags
 
+from PLC.AuthorizeHelpers import AuthorizeHelpers
+
 class UpdateNodeTag(Method):
     """
     Updates the value of an existing node tag
 
 class UpdateNodeTag(Method):
     """
     Updates the value of an existing node tag
 
-    Access rights depend on the node tag type.
+    Admins have full access.  Non-admins need to 
+    (1) have at least one of the roles attached to the tagtype, 
+    and (2) belong in the same site as the tagged subject.
 
     Returns 1 if successful, faults otherwise.
     """
 
     Returns 1 if successful, faults otherwise.
     """
@@ -34,36 +35,26 @@ class UpdateNodeTag(Method):
 
     returns = Parameter(int, '1 if successful')
 
 
     returns = Parameter(int, '1 if successful')
 
-    object_type = 'Node'
-
     def call(self, auth, node_tag_id, value):
         node_tags = NodeTags(self.api, [node_tag_id])
         if not node_tags:
             raise PLCInvalidArgument, "No such node tag %r"%node_tag_id
         node_tag = node_tags[0]
 
     def call(self, auth, node_tag_id, value):
         node_tags = NodeTags(self.api, [node_tag_id])
         if not node_tags:
             raise PLCInvalidArgument, "No such node tag %r"%node_tag_id
         node_tag = node_tags[0]
 
-        ### reproducing a check from UpdateSliceTag, looks dumb though
-        nodes = Nodes(self.api, [node_tag['node_id']])
-        if not nodes:
-            raise PLCInvalidArgument, "No such node %r"%node_tag['node_id']
-        node = nodes[0]
-
-        assert node_tag['node_tag_id'] in node['node_tag_ids']
+        tag_type_id = node_tag['tag_type_id']
+        tag_type = TagTypes (self.api,[tag_type_id])[0]
+        node = Nodes (self.api, node_tag['node_id'])
 
 
-        # check permission : it not admin, is the user affiliated with the right site
-        if 'admin' not in self.caller['roles']:
-            # locate node
-            node = Nodes (self.api,[node['node_id']])[0]
-            # locate site
-            site = Sites (self.api, [node['site_id']])[0]
-            # check caller is affiliated with this site
-            if self.caller['person_id'] not in site['person_ids']:
-                raise PLCPermissionDenied, "Not a member of the hosting site %s"%site['abbreviated_site']
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        elif not AuthorizeHelpers.person_access_tag_type (self.api, self.caller, tag_type):
+            raise PLCPermissionDenied, "%s, no permission to use this tag type"%self.name
+        elif AuthorizeHelpers.node_belongs_to_person (self.api, node, self.caller):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you must belong in the same site as subject node"%self.name
 
 
-            required_min_role = node_tag['min_role_id']
-            if required_min_role is not None and \
-                    min(self.caller['role_ids']) > required_min_role:
-                raise PLCPermissionDenied, "Not allowed to modify the specified node tag, requires role %d",required_min_role
 
         node_tag['value'] = value
         node_tag.sync()
 
         node_tag['value'] = value
         node_tag.sync()
index 4162684..97862ef 100644 (file)
@@ -1,9 +1,6 @@
-# $Id: UpdatePersonTag.py 14587 2009-07-19 13:18:50Z thierry $
-# $URL: http://svn.planet-lab.org/svn/PLCAPI/tags/PLCAPI-4.3-27/PLC/Methods/UpdatePersonTag.py $
 #
 #
-# $Revision: 14587 $
+# Thierry Parmentelat - INRIA
 #
 #
-
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
@@ -12,14 +9,13 @@ from PLC.Auth import Auth
 from PLC.PersonTags import PersonTag, PersonTags
 from PLC.Persons import Person, Persons
 
 from PLC.PersonTags import PersonTag, PersonTags
 from PLC.Persons import Person, Persons
 
-from PLC.Nodes import Nodes
-from PLC.Persons import Persons
+from PLC.AuthorizeHelpers import AuthorizeHelpers
 
 class UpdatePersonTag(Method):
     """
     Updates the value of an existing person setting
 
 
 class UpdatePersonTag(Method):
     """
     Updates the value of an existing person setting
 
-    Access rights depend on the tag type.
+    Admins have full access.  Non-admins can change their own tags.
 
     Returns 1 if successful, faults otherwise.
     """
 
     Returns 1 if successful, faults otherwise.
     """
@@ -34,34 +30,22 @@ class UpdatePersonTag(Method):
 
     returns = Parameter(int, '1 if successful')
 
 
     returns = Parameter(int, '1 if successful')
 
-    object_type = 'Person'
-
     def call(self, auth, person_tag_id, value):
         person_tags = PersonTags(self.api, [person_tag_id])
         if not person_tags:
             raise PLCInvalidArgument, "No such person setting %r"%person_tag_id
         person_tag = person_tags[0]
 
     def call(self, auth, person_tag_id, value):
         person_tags = PersonTags(self.api, [person_tag_id])
         if not person_tags:
             raise PLCInvalidArgument, "No such person setting %r"%person_tag_id
         person_tag = person_tags[0]
 
-        ### reproducing a check from UpdateSliceTag, looks dumb though
-        persons = Persons(self.api, [person_tag['person_id']])
-        if not persons:
-            raise PLCInvalidArgument, "No such person %r"%person_tag['person_id']
-        person = persons[0]
-
-        assert person_tag['person_tag_id'] in person['person_tag_ids']
-
-        # check permission : it not admin, is the user affiliated with the right person
-        if 'admin' not in self.caller['roles']:
-            # check caller is affiliated with this person's person
-            if not self.caller.can_update(person):
-                raise PLCPermissionDenied, "person_id %s doesn't have access to person_tag_id %s" % (
-                    person['person_id'],
-                    person_tag['person_tag_id'])
+        person = Persons (self.api, person_tag['person_id'])[0]
 
 
-            required_min_role = person_tag['min_role_id']
-            if required_min_role is not None and \
-                    min(self.caller['role_ids']) > required_min_role:
-                raise PLCPermissionDenied, "Not allowed to modify the specified person setting, requires role %d" % required_min_role
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        # user can change tags on self
+        elif AuthorizeHelpers.person_access_person (self.api, self.caller, person):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you can only change your own tags"%self.name
 
         person_tag['value'] = value
         person_tag.sync()
 
         person_tag['value'] = value
         person_tag.sync()
index 06919bf..901a875 100644 (file)
@@ -1,25 +1,25 @@
-# $Id: UpdateSiteTag.py 14587 2009-07-19 13:18:50Z thierry $
-# $URL: http://svn.planet-lab.org/svn/PLCAPI/tags/PLCAPI-4.3-27/PLC/Methods/UpdateSiteTag.py $
 #
 #
-# $Revision: 14587 $
+# Thierry Parmentelat - INRIA
 #
 #
-
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Auth import Auth
 
-from PLC.SiteTags import SiteTag, SiteTags
 from PLC.Sites import Site, Sites
 from PLC.Sites import Site, Sites
-
 from PLC.Nodes import Nodes
 from PLC.Nodes import Nodes
-from PLC.Sites import Sites
+from PLC.TagTypes import TagType, TagTypes
+from PLC.SiteTags import SiteTag, SiteTags
+
+from PLC.AuthorizeHelpers import AuthorizeHelpers
 
 class UpdateSiteTag(Method):
     """
     Updates the value of an existing site setting
 
 
 class UpdateSiteTag(Method):
     """
     Updates the value of an existing site setting
 
-    Access rights depend on the tag type.
+    Admins have full access.  Non-admins need to 
+    (1) have at least one of the roles attached to the tagtype, 
+    and (2) belong in the same site as the tagged subject.
 
     Returns 1 if successful, faults otherwise.
     """
 
     Returns 1 if successful, faults otherwise.
     """
@@ -34,33 +34,26 @@ class UpdateSiteTag(Method):
 
     returns = Parameter(int, '1 if successful')
 
 
     returns = Parameter(int, '1 if successful')
 
-    object_type = 'Site'
-
     def call(self, auth, site_tag_id, value):
         site_tags = SiteTags(self.api, [site_tag_id])
         if not site_tags:
             raise PLCInvalidArgument, "No such site setting %r"%site_tag_id
         site_tag = site_tags[0]
 
     def call(self, auth, site_tag_id, value):
         site_tags = SiteTags(self.api, [site_tag_id])
         if not site_tags:
             raise PLCInvalidArgument, "No such site setting %r"%site_tag_id
         site_tag = site_tags[0]
 
-        ### reproducing a check from UpdateSliceTag, looks dumb though
-        sites = Sites(self.api, [site_tag['site_id']])
-        if not sites:
-            raise PLCInvalidArgument, "No such site %r"%site_tag['site_id']
-        site = sites[0]
-
-        assert site_tag['site_tag_id'] in site['site_tag_ids']
-
-        # check permission : it not admin, is the user affiliated with the right site
-        if 'admin' not in self.caller['roles']:
-            # check caller is affiliated with this site
-            if self.caller['person_id'] not in site['person_ids']:
-                raise PLCPermissionDenied, "Not a member of the hosting site %s"%site['abbreviated_site']
-
-            required_min_role = tag_type ['min_role_id']
-            if required_min_role is not None and \
-                    min(self.caller['role_ids']) > required_min_role:
-                raise PLCPermissionDenied, "Not allowed to modify the specified site setting, requires role %d",required_min_role
-
+        tag_type_id = site_tag['tag_type_id']
+        tag_type = TagTypes (self.api,[tag_type_id])[0]
+        site = Sites (self.api, site_tag['site_id'])
+        
+        # check authorizations
+        if 'admin' in self.caller['roles']:
+            pass
+        elif not AuthorizeHelpers.person_access_tag_type (self.api, self.caller, tag_type):
+            raise PLCPermissionDenied, "%s, no permission to use this tag type"%self.name
+        elif AuthorizeHelpers.person_belongs_to_site (self.api, self.caller, site):
+            pass
+        else:
+            raise PLCPermissionDenied, "%s: you must be part of the subject site"%self.name
+            
         site_tag['value'] = value
         site_tag.sync()
 
         site_tag['value'] = value
         site_tag.sync()
 
index 76a6354..e8b8b33 100644 (file)
@@ -1,13 +1,17 @@
-# $Id$
-# $URL$
+#
+# Thierry Parmentelat - INRIA
+#
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
+from PLC.Auth import Auth
+
 from PLC.SliceTags import SliceTag, SliceTags
 from PLC.Nodes import Node
 from PLC.Slices import Slice, Slices
 from PLC.InitScripts import InitScript, InitScripts
 from PLC.SliceTags import SliceTag, SliceTags
 from PLC.Nodes import Node
 from PLC.Slices import Slice, Slices
 from PLC.InitScripts import InitScript, InitScripts
-from PLC.Auth import Auth
+
+from PLC.AuthorizeHelpers import AuthorizeHelpers
 
 class UpdateSliceTag(Method):
     """
 
 class UpdateSliceTag(Method):
     """
index bad4ba2..56bd61f 100644 (file)
@@ -8,7 +8,7 @@ from PLC.TagTypes import TagType, TagTypes
 from PLC.Auth import Auth
 
 can_update = lambda (field, value): field in \
 from PLC.Auth import Auth
 
 can_update = lambda (field, value): field in \
-             ['tagname', 'description', 'category', 'min_role_id']
+             ['tagname', 'description', 'category']
 
 class UpdateTagType(Method):
     """
 
 class UpdateTagType(Method):
     """
index c289dee..7f69e32 100644 (file)
@@ -25,7 +25,6 @@ class NodeTag(Row):
         'tagname': TagType.fields['tagname'],
         'description': TagType.fields['description'],
         'category': TagType.fields['category'],
         'tagname': TagType.fields['tagname'],
         'description': TagType.fields['description'],
         'category': TagType.fields['category'],
-        'min_role_id': TagType.fields['min_role_id'],
         }
 
 class NodeTags(Table):
         }
 
 class NodeTags(Table):
index be1e86e..30869af 100644 (file)
@@ -26,7 +26,6 @@ class PersonTag(Row):
         'tagname': TagType.fields['tagname'],
         'description': TagType.fields['description'],
         'category': TagType.fields['category'],
         'tagname': TagType.fields['tagname'],
         'description': TagType.fields['description'],
         'category': TagType.fields['category'],
-        'min_role_id': TagType.fields['min_role_id'],
         'value': Parameter(str, "Person setting value"),
         ### relations
 
         'value': Parameter(str, "Person setting value"),
         ### relations
 
index 03d9884..4aa4d6b 100644 (file)
@@ -22,7 +22,7 @@ class Role(Row):
 
     table_name = 'roles'
     primary_key = 'role_id'
 
     table_name = 'roles'
     primary_key = 'role_id'
-    join_tables = ['person_role', ('tag_types', 'min_role_id')]
+    join_tables = ['person_role', 'tag_type_role' ]
     fields = {
         'role_id': Parameter(int, "Role identifier"),
         'name': Parameter(str, "Role", max = 100),
     fields = {
         'role_id': Parameter(int, "Role identifier"),
         'name': Parameter(str, "Role", max = 100),
index c70a46c..45cbfd9 100644 (file)
@@ -26,7 +26,6 @@ class SiteTag(Row):
         'tagname': TagType.fields['tagname'],
         'description': TagType.fields['description'],
         'category': TagType.fields['category'],
         'tagname': TagType.fields['tagname'],
         'description': TagType.fields['description'],
         'category': TagType.fields['category'],
-        'min_role_id': TagType.fields['min_role_id'],
         'value': Parameter(str, "Site setting value"),
         ### relations
 
         'value': Parameter(str, "Site setting value"),
         ### relations
 
index fca3b14..cfb26ad 100644 (file)
@@ -1,5 +1,3 @@
-# $Id$
-# $URL$
 from types import StringTypes
 import string
 
 from types import StringTypes
 import string
 
index a320e62..78273ca 100644 (file)
@@ -28,7 +28,6 @@ class SliceTag(Row):
         'tagname': TagType.fields['tagname'],
         'description': TagType.fields['description'],
         'category': TagType.fields['category'],
         'tagname': TagType.fields['tagname'],
         'description': TagType.fields['description'],
         'category': TagType.fields['category'],
-        'min_role_id': TagType.fields['min_role_id'],
         'value': Parameter(str, "Slice attribute value"),
         }
 
         'value': Parameter(str, "Slice attribute value"),
         }
 
index d4d4cd7..c045a63 100644 (file)
@@ -22,13 +22,14 @@ class TagType (Row):
 
     table_name = 'tag_types'
     primary_key = 'tag_type_id'
 
     table_name = 'tag_types'
     primary_key = 'tag_type_id'
-    join_tables = ['node_tag', 'interface_tag', 'slice_tag', 'site_tag', 'person_tag' ]
+    join_tables = ['tag_type_role', 'node_tag', 'interface_tag', 'slice_tag', 'site_tag', 'person_tag' ]
     fields = {
         'tag_type_id': Parameter(int, "Node tag type identifier"),
         'tagname': Parameter(str, "Node tag type name", max = 100),
         'description': Parameter(str, "Node tag type description", max = 254),
         'category' : Parameter (str, "Node tag category", max=64, optional=True),
     fields = {
         'tag_type_id': Parameter(int, "Node tag type identifier"),
         'tagname': Parameter(str, "Node tag type name", max = 100),
         'description': Parameter(str, "Node tag type description", max = 254),
         'category' : Parameter (str, "Node tag category", max=64, optional=True),
-        'min_role_id': Parameter(int, "Minimum (least powerful) role that can set or change this attribute"),
+        'role_ids': Parameter([int], "List of role identifiers"),
+        'roles': Parameter([str], "List of roles"),
         }
 
     def validate_name(self, name):
         }
 
     def validate_name(self, name):
@@ -43,12 +44,9 @@ class TagType (Row):
 
         return name
 
 
         return name
 
-    def validate_min_role_id(self, role_id):
-        roles = [row['role_id'] for row in Roles(self.api)]
-        if role_id not in roles:
-            raise PLCInvalidArgument, "Invalid role"
+    add_role = Row.add_object(Role, 'tag_type_role')
+    remove_role = Row.remove_object(Role, 'tag_type_role')
 
 
-        return role_id
 
 class TagTypes(Table):
     """
 
 class TagTypes(Table):
     """
@@ -59,7 +57,7 @@ class TagTypes(Table):
     def __init__(self, api, tag_type_filter = None, columns = None):
         Table.__init__(self, api, TagType, columns)
 
     def __init__(self, api, tag_type_filter = None, columns = None):
         Table.__init__(self, api, TagType, columns)
 
-        sql = "SELECT %s FROM tag_types WHERE True" % \
+        sql = "SELECT %s FROM view_tag_types WHERE True" % \
               ", ".join(self.columns)
 
         if tag_type_filter is not None:
               ", ".join(self.columns)
 
         if tag_type_filter is not None:
diff --git a/migrations/104-down-noderole.sql b/migrations/104-down-noderole.sql
new file mode 100644 (file)
index 0000000..f7d7220
--- /dev/null
@@ -0,0 +1,20 @@
+-- reverting....
+-- DELETE from roles WHERE name='node';
+
+-- recreate the min_role_id column
+ALTER TABLE tag_types ADD COLUMN min_role_id integer REFERENCES roles;
+
+-- compute the highest role available for each tag_type and store it as min_role_id
+-- xxx todo
+
+--- tmp - set to something so we can run down&up again
+UPDATE tag_types SET min_role_id=10;
+UPDATE tag_types SET min_role_id=20 WHERE tag_type_id%2=0;
+
+DROP TABLE tag_type_role CASCADE;
+-- done by cascade
+--DROP VIEW view_tag_types;
+--DROP VIEW tag_type_roles;
+
+--------------------
+UPDATE plc_db_version SET subversion = 103;
diff --git a/migrations/104-up-noderole.sql b/migrations/104-up-noderole.sql
new file mode 100644 (file)
index 0000000..c31af7a
--- /dev/null
@@ -0,0 +1,122 @@
+-- changing the permission model on tags
+-- we replace the single 'min_role_id' field attached to tag_types
+-- with a set of roles
+
+
+-- create a separate table to keep the tag-type x role relationship
+CREATE TABLE tag_type_role (
+    tag_type_id integer REFERENCES tag_types NOT NULL, -- tag_type ID
+    role_id integer REFERENCES roles NOT NULL,         -- role ID
+    PRIMARY KEY (tag_type_id, role_id)
+);
+CREATE INDEX tag_type_role_tag_type_id_idx ON tag_type_role (tag_type_id);
+CREATE INDEX tag_type_role_role_id_idx ON tag_type_role (role_id);
+
+-- fill this from the former min_role_id field in the tag_types table
+-- add all roles lower or equal to the min_role_id
+INSERT INTO tag_type_role ("tag_type_id","role_id") SELECT tag_type_id,role_id FROM tag_types,roles where role_id<=min_role_id;
+
+-- we can now drop the min_role_id column
+ALTER TABLE tag_types DROP COLUMN min_role_id CASCADE;
+
+-- create views to expose roles
+CREATE OR REPLACE VIEW tag_type_roles AS
+SELECT tag_type_id,
+array_accum(role_id) AS role_ids,
+array_accum(roles.name) AS roles
+FROM tag_type_role 
+LEFT JOIN roles USING (role_id)
+GROUP BY tag_type_id;
+
+CREATE OR REPLACE VIEW view_tag_types AS
+SELECT 
+tag_types.tag_type_id,
+tag_types.tagname,
+tag_types.description,
+tag_types.category,
+COALESCE((SELECT role_ids FROM tag_type_roles WHERE tag_type_roles.tag_type_id = tag_types.tag_type_id), '{}') AS role_ids,
+COALESCE((SELECT roles FROM tag_type_roles WHERE tag_type_roles.tag_type_id = tag_types.tag_type_id), '{}') AS roles
+FROM tag_types; 
+
+
+-- remove min_role_id from the object views
+CREATE OR REPLACE VIEW view_person_tags AS
+SELECT
+person_tag.person_tag_id,
+person_tag.person_id,
+persons.email,
+tag_types.tag_type_id,
+tag_types.tagname,
+tag_types.description,
+tag_types.category,
+person_tag.value
+FROM person_tag 
+INNER JOIN tag_types USING (tag_type_id)
+INNER JOIN persons USING (person_id);
+
+CREATE OR REPLACE VIEW view_site_tags AS
+SELECT
+site_tag.site_tag_id,
+site_tag.site_id,
+sites.login_base,
+tag_types.tag_type_id,
+tag_types.tagname,
+tag_types.description,
+tag_types.category,
+site_tag.value
+FROM site_tag 
+INNER JOIN tag_types USING (tag_type_id)
+INNER JOIN sites USING (site_id);
+
+CREATE OR REPLACE VIEW view_interface_tags AS
+SELECT
+interface_tag.interface_tag_id,
+interface_tag.interface_id,
+interfaces.ip,
+tag_types.tag_type_id,
+tag_types.tagname,
+tag_types.description,
+tag_types.category,
+interface_tag.value
+FROM interface_tag
+INNER JOIN tag_types USING (tag_type_id)
+INNER JOIN interfaces USING (interface_id);
+
+CREATE OR REPLACE VIEW view_node_tags AS
+SELECT
+node_tag.node_tag_id,
+node_tag.node_id,
+nodes.hostname,
+tag_types.tag_type_id,
+tag_types.tagname,
+tag_types.description,
+tag_types.category,
+node_tag.value
+FROM node_tag 
+INNER JOIN tag_types USING (tag_type_id)
+INNER JOIN nodes USING (node_id);
+
+CREATE OR REPLACE VIEW view_slice_tags AS
+SELECT
+slice_tag.slice_tag_id,
+slice_tag.slice_id,
+slice_tag.node_id,
+slice_tag.nodegroup_id,
+tag_types.tag_type_id,
+tag_types.tagname,
+tag_types.description,
+tag_types.category,
+slice_tag.value,
+slices.name
+FROM slice_tag
+INNER JOIN tag_types USING (tag_type_id)
+INNER JOIN slices USING (slice_id);
+
+-- same for ilinks
+CREATE OR REPLACE VIEW view_ilinks AS
+SELECT * FROM tag_types 
+INNER JOIN ilink USING (tag_type_id);
+
+-- INSERT INTO roles (role_id, name) VALUES (50, 'node');
+
+UPDATE plc_db_version SET subversion = 104;
index 6ac84c5..4083039 100644 (file)
@@ -69,6 +69,8 @@ CREATE TABLE tag_types (
     tag_type_id serial PRIMARY KEY,                    -- ID
     tagname text UNIQUE NOT NULL,                      -- Tag Name
     description text,                                  -- Optional Description
     tag_type_id serial PRIMARY KEY,                    -- ID
     tagname text UNIQUE NOT NULL,                      -- Tag Name
     description text,                                  -- Optional Description
+-- this is deprecated -- see migrations/104*
+-- starting with subversion 104, a tag type has a SET OF roles attached to it
     min_role_id integer REFERENCES roles DEFAULT 10,   -- set minimal role required
     category text NOT NULL DEFAULT 'general'           -- Free text for grouping tags together
 ) WITH OIDS;
     min_role_id integer REFERENCES roles DEFAULT 10,   -- set minimal role required
     category text NOT NULL DEFAULT 'general'           -- Free text for grouping tags together
 ) WITH OIDS;