Ejemplo n.º 1
0
 def setUp(self):
     super(SuperuserPermissionCheckerTest, self).setUp()
     self.system = createSystemData()
     UserAPI().create([(u'username', u'password', u'User',
                        u'*****@*****.**')])
     self.user = getUser(u'username')
     self.permissions = PermissionAPI(self.user)
Ejemplo n.º 2
0
class CachingPermissionAPI(object):
    """The public API to cached permission-related logic in the model."""
    def __init__(self, user):
        self._api = PermissionAPI(user, factory=CachingAPIFactory())

    def set(self, values):
        """See L{PermissionAPI.set}.

        Modified permissions are removed from the cache.
        """
        namespacePaths = [
            path for (path, operation, _, _) in values
            if operation in Operation.NAMESPACE_OPERATIONS
        ]
        tagPaths = [
            path for (path, operation, _, _) in values
            if operation in Operation.TAG_OPERATIONS
        ]
        cache = PermissionCache()
        cache.clearNamespacePermissions(namespacePaths)
        cache.clearTagPermissions(tagPaths)
        self._api.set(values)

    def get(self, values):
        """See L{PermissionAPI.get}."""
        return self._api.get(values)
Ejemplo n.º 3
0
 def setUp(self):
     super(FacadeNamespaceTest, self).setUp()
     createSystemData()
     self.transact = Transact(self.threadPool)
     factory = FluidinfoSessionFactory('API-9000')
     self.facade = Facade(self.transact, factory)
     UserAPI().create([(u'username', u'password', u'User',
                        u'*****@*****.**')])
     self.user = getUser(u'username')
     self.permissions = PermissionAPI(self.user)
Ejemplo n.º 4
0
    def testCreateChildTagWithDelegatedCreator(self):
        """
        L{TagAPI.create} always ensures that a new L{Tag} is usable by the
        L{User} that created it.  In the case of default permissions, the user
        creating the new L{Tag} is granted L{Operation.UPDATE_TAG},
        L{Operation.DELETE_TAG}, L{Operation.WRITE_TAG_VALUE} and
        L{Operation.DELETE_TAG_VALUE}.
        """
        UserAPI().create([(u'friend', u'secret', u'name', u'*****@*****.**')
                          ])
        PermissionAPI(self.user).set([(u'username', Operation.CREATE_NAMESPACE,
                                       Policy.CLOSED, [u'username',
                                                       u'friend'])])

        friend = getUser(u'friend')
        TagAPI(friend).create([(u'username/tag', u'A shared tag')])
        result = getTagPermissions([u'username/tag'])
        tag, permission = result.one()
        self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]),
                         permission.get(Operation.UPDATE_TAG))
        self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]),
                         permission.get(Operation.DELETE_TAG))
        self.assertEqual((Policy.CLOSED, [self.user.id]),
                         permission.get(Operation.CONTROL_TAG))
        self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]),
                         permission.get(Operation.WRITE_TAG_VALUE))
        self.assertEqual((Policy.OPEN, []),
                         permission.get(Operation.READ_TAG_VALUE))
        self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]),
                         permission.get(Operation.DELETE_TAG_VALUE))
        self.assertEqual((Policy.CLOSED, [self.user.id]),
                         permission.get(Operation.CONTROL_TAG_VALUE))
Ejemplo n.º 5
0
    def testCreatePrivateChildTagWithDelegatedCreator(self):
        """
        L{TagAPI.create} always ensures that a new L{Tag} is usable by the
        L{User} that created it.  If the L{Operation.READ_TAG_VALUE}
        permission is L{Policy.CLOSED} the creator is added to the exceptions
        list.
        """
        UserAPI().create([(u'friend', u'secret', u'name', u'*****@*****.**')
                          ])
        PermissionAPI(self.user).set([(u'username', Operation.CREATE_NAMESPACE,
                                       Policy.CLOSED, [u'username',
                                                       u'friend']),
                                      (u'username', Operation.LIST_NAMESPACE,
                                       Policy.CLOSED, [u'username',
                                                       u'friend'])])

        friend = getUser(u'friend')
        TagAPI(friend).create([(u'username/tag', u'A shared tag')])
        result = getTagPermissions([u'username/tag'])
        tag, permission = result.one()
        self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]),
                         permission.get(Operation.UPDATE_TAG))
        self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]),
                         permission.get(Operation.DELETE_TAG))
        self.assertEqual((Policy.CLOSED, [self.user.id]),
                         permission.get(Operation.CONTROL_TAG))
        self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]),
                         permission.get(Operation.WRITE_TAG_VALUE))
        self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]),
                         permission.get(Operation.READ_TAG_VALUE))
        self.assertEqual((Policy.CLOSED, [self.user.id, friend.id]),
                         permission.get(Operation.DELETE_TAG_VALUE))
        self.assertEqual((Policy.CLOSED, [self.user.id]),
                         permission.get(Operation.CONTROL_TAG_VALUE))
Ejemplo n.º 6
0
    def testCreateChildTagInheritsParentNamespacePermissions(self):
        """
        L{TagAPI.create} creates new L{Tag}s with permissions inherited from
        the parent L{Namespace}'s permissions.
        """
        PermissionAPI(self.user).set([
            (u'username', Operation.CREATE_NAMESPACE, Policy.CLOSED,
             [u'username']),
            (u'username', Operation.UPDATE_NAMESPACE, Policy.OPEN, []),
            (u'username', Operation.DELETE_NAMESPACE, Policy.OPEN, []),
            (u'username', Operation.LIST_NAMESPACE, Policy.CLOSED,
             [u'username']),
            (u'username', Operation.CONTROL_NAMESPACE, Policy.OPEN, [])
        ])

        self.tags.create([(u'username/tag', u'A child tag')])
        result = getTagPermissions([u'username/tag'])
        tag, permission = result.one()
        self.assertEqual((Policy.CLOSED, [self.user.id]),
                         permission.get(Operation.UPDATE_TAG))
        self.assertEqual((Policy.CLOSED, [self.user.id]),
                         permission.get(Operation.DELETE_TAG))
        self.assertEqual((Policy.OPEN, []),
                         permission.get(Operation.CONTROL_TAG))
        self.assertEqual((Policy.CLOSED, [self.user.id]),
                         permission.get(Operation.WRITE_TAG_VALUE))
        self.assertEqual((Policy.CLOSED, [self.user.id]),
                         permission.get(Operation.READ_TAG_VALUE))
        self.assertEqual((Policy.CLOSED, [self.user.id]),
                         permission.get(Operation.DELETE_TAG_VALUE))
        self.assertEqual((Policy.OPEN, []),
                         permission.get(Operation.CONTROL_TAG_VALUE))
Ejemplo n.º 7
0
 def setUp(self):
     super(SuperuserPermissionCheckerTest, self).setUp()
     self.system = createSystemData()
     UserAPI().create([(u'username', u'password', u'User',
                        u'*****@*****.**')])
     self.user = getUser(u'username')
     self.permissions = PermissionAPI(self.user)
Ejemplo n.º 8
0
def setVersionTag(version):
    """Updates the fluiddb/version tag.

    @param version: The new version string.
    """
    user = getUser(u'fluiddb')
    objectID = ObjectAPI(user).create(u'fluidinfo')
    releaseDate = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
    values = {
        objectID: {
            u'fluiddb/api-version': {
                'mime-type': 'text/plain',
                'contents': version
            },
            u'fluiddb/release-date': {
                'mime-type': 'text/plain',
                'contents': releaseDate + '\n'
            }
        }
    }
    TagValueAPI(user).set(values)
    PermissionAPI(user).set([
        (u'fluiddb/api-version', Operation.READ_TAG_VALUE, Policy.OPEN, []),
        (u'fluiddb/release-date', Operation.READ_TAG_VALUE, Policy.OPEN, [])
    ])

    try:
        transaction.commit()
    except:
        transaction.abort()
        raise
Ejemplo n.º 9
0
    def testCreateChildNamespaceInheritsParentNamespacePermissions(self):
        """
        L{NamespaceAPI.create} creates new L{Namespace}s with
        L{Operation.CREATE_NAMESPACE} permissions inherited from the parent
        L{Namespace}'s permissions.
        """
        UserAPI().create([(u'user', u'secret', u'name', u'*****@*****.**')])
        user = getUser(u'user')
        PermissionAPI(self.user).set([
            (u'user', Operation.CREATE_NAMESPACE, Policy.OPEN, []),
            (u'user', Operation.UPDATE_NAMESPACE, Policy.OPEN, []),
            (u'user', Operation.DELETE_NAMESPACE, Policy.OPEN, []),
            (u'user', Operation.LIST_NAMESPACE, Policy.CLOSED, [u'user']),
            (u'user', Operation.CONTROL_NAMESPACE, Policy.OPEN, [])
        ])

        self.namespaces.create([(u'user/child', u'A child namespace')])
        result = getNamespacePermissions([u'user/child'])
        namespace, permission = result.one()
        self.assertEqual((Policy.OPEN, []),
                         permission.get(Operation.CREATE_NAMESPACE))
        self.assertEqual((Policy.OPEN, []),
                         permission.get(Operation.UPDATE_NAMESPACE))
        self.assertEqual((Policy.OPEN, []),
                         permission.get(Operation.DELETE_NAMESPACE))
        self.assertEqual((Policy.CLOSED, [user.id]),
                         permission.get(Operation.LIST_NAMESPACE))
        self.assertEqual((Policy.OPEN, []),
                         permission.get(Operation.CONTROL_NAMESPACE))
Ejemplo n.º 10
0
 def setUp(self):
     super(TagValueAPITest, self).setUp()
     self.system = createSystemData()
     UserAPI().create([(u'username', u'password', u'User',
                        u'*****@*****.**')])
     self.user = getUser(u'username')
     self.permissions = PermissionAPI(self.user)
     self.tagValues = TagValueAPI(self.user)
Ejemplo n.º 11
0
 def testSetWithSuperuserInExceptions(self):
     """
     L{PermissionAPI.set} raises L{UserNotAllowedInExceptionError} if a
     superuser is given in one of the exceptions lists.
     """
     superuser = self.system.users['fluiddb']
     values = [(u'username', Operation.CREATE_NAMESPACE,
                Policy.OPEN, [u'fluiddb'])]
     self.assertRaises(UserNotAllowedInExceptionError,
                       PermissionAPI(superuser).set, values)
Ejemplo n.º 12
0
 def setUp(self):
     super(FacadeNamespaceTest, self).setUp()
     createSystemData()
     self.transact = Transact(self.threadPool)
     factory = FluidinfoSessionFactory('API-9000')
     self.facade = Facade(self.transact, factory)
     UserAPI().create([(u'username', u'password', u'User',
                        u'*****@*****.**')])
     self.user = getUser(u'username')
     self.permissions = PermissionAPI(self.user)
Ejemplo n.º 13
0
 def testSetWithAnonymousUserAndForbiddenOperation(self):
     """
     L{PermissionAPI.set} raises L{UserNotAllowedInExceptionError} if an
     anonymous user is given in one of the exceptions list and the operation
     is forbidden for anonymous users.
     """
     anon = self.system.users[u'anon']
     values = [(u'username', Operation.CREATE_NAMESPACE,
                Policy.OPEN, [u'anon'])]
     self.assertRaises(UserNotAllowedInExceptionError,
                       PermissionAPI(anon).set, values)
Ejemplo n.º 14
0
 def testSetWithAnonymousUserAndPermittedOperation(self):
     """
     L{PermissionAPI.set} updates existing permissions for the anonymous
     user if the operation is allowed for anonymous users.
     """
     anon = self.system.users[u'anon']
     values = [(u'username', Operation.LIST_NAMESPACE,
                Policy.OPEN, [u'anon'])]
     PermissionAPI(anon).set(values)
     namespace, permission = getNamespacePermissions([u'username']).one()
     self.assertEqual(Policy.OPEN, permission.listPolicy)
     self.assertEqual([anon.id], permission.listExceptions)
Ejemplo n.º 15
0
 def testActivationTokenTagPermission(self):
     """
     L{bootstrapWebAdminData} creates a C{fluiddb/users/activation-token}
     tag with write permissions for the C{fluidinfo.com} user.
     """
     createSystemData()
     bootstrapWebAdminData()
     superuser = getUser(u'fluiddb')
     pathAndOperation = (u'fluiddb/users/activation-token',
                         Operation.WRITE_TAG_VALUE)
     result = PermissionAPI(superuser).get([pathAndOperation])
     policy, exceptions = result[pathAndOperation]
     self.assertEqual(Policy.CLOSED, policy)
     self.assertEqual([u'fluidinfo.com'], exceptions)
Ejemplo n.º 16
0
def bootstrapWebAdminData():
    """Create system data in a database."""
    try:
        superuser = getUser(u'fluiddb')
        UserAPI().create([((u'fluidinfo.com', u'secret', u'Fluidinfo website',
                            u'*****@*****.**'))])
        webuser = getUser(u'fluidinfo.com')
        webuser.role = Role.USER_MANAGER
        TagAPI(superuser).create([(u'fluiddb/users/activation-token',
                                   u'Activation token for the user')])
        PermissionAPI(superuser).set([
            (u'fluiddb/users/activation-token', Operation.WRITE_TAG_VALUE,
             Policy.CLOSED, [u'fluidinfo.com'])
        ])
        anonuser = getUser(u'anon')
        OAuthConsumerAPI.register(anonuser)
    except:
        transaction.abort()
        raise
    else:
        transaction.commit()
Ejemplo n.º 17
0
class FacadeNamespaceTest(FluidinfoTestCase):

    resources = [('cache', CacheResource()),
                 ('config', ConfigResource()),
                 ('log', LoggingResource()),
                 ('store', DatabaseResource()),
                 ('threadPool', ThreadPoolResource())]

    def setUp(self):
        super(FacadeNamespaceTest, self).setUp()
        createSystemData()
        self.transact = Transact(self.threadPool)
        factory = FluidinfoSessionFactory('API-9000')
        self.facade = Facade(self.transact, factory)
        UserAPI().create([(u'username', u'password', u'User',
                           u'*****@*****.**')])
        self.user = getUser(u'username')
        self.permissions = PermissionAPI(self.user)

    @inlineCallbacks
    def testGetNamespaceWithoutData(self):
        """
        L{Facade.getNamespace} raises a L{TNonexistentNamespace} exception if
        the requested L{Namespace.path} doesn't exist.
        """
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.getNamespace(session, u'username/unknown',
                                                False, False, False)
            yield self.assertFailure(deferred, TNonexistentNamespace)

    @inlineCallbacks
    def testGetNamespace(self):
        """
        L{Facade.getNamespace} returns a L{TNamespace} instance with
        information about the requested L{Namespace}.
        """
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            result = yield self.facade.getNamespace(session, u'username',
                                                    False, False, False)

        self.assertEqual(str(self.user.namespace.objectID), result.objectId)
        self.assertEqual(u'username', result.path)

    @inlineCallbacks
    def testGetNamespaceWithDescription(self):
        """
        L{Facade.getNamespace} includes the L{Namespace.description}, if it
        was requested.
        """
        namespaces = NamespaceAPI(self.user)
        namespaces.create([(u'username/name', u'A namespace.')])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            result = yield self.facade.getNamespace(session, u'username/name',
                                                    True, False, False)
        self.assertEqual(u'A namespace.', result.description)

    @inlineCallbacks
    def testGetNamespaceWithNamespaces(self):
        """
        L{Facade.getNamespace} includes child L{Namespace.name}s, if they were
        requested.
        """
        namespaces = NamespaceAPI(self.user)
        namespaces.create([(u'username/name', u'A namespace.')])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            result = yield self.facade.getNamespace(session, u'username',
                                                    False, True, False)
        self.assertEqual([u'name', u'private'], sorted(result.namespaces))

    @inlineCallbacks
    def testGetNamespaceWithTags(self):
        """
        L{Facade.getNamespace} includes child L{Tag.name}s, if they were
        requested.
        """
        createTag(self.user, self.user.namespace, u'tag')
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            result = yield self.facade.getNamespace(session, u'username',
                                                    False, False, True)
        self.assertEqual([u'tag'], result.tags)

    @inlineCallbacks
    def testGetNamespaceWithUnknownPath(self):
        """
        L{Facade.getNamespace} raises a L{TNonexistentNamespace} exception
        if the specified L{Namespace} doesn't exist.
        """
        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.getNamespace(session, u'unknown',
                                                returnDescription=False,
                                                returnNamespaces=False,
                                                returnTags=False)
            yield self.assertFailure(deferred, TNonexistentNamespace)

    @inlineCallbacks
    def testGetNamespaceWithPermissionDenied(self):
        """
        L{Facade.getNamespace} raises a L{TPathPermissionDenied} exception
        if the user doesn't have C{LIST} permissions on the specified
        L{Namespace}.
        """
        self.permissions.set([(u'username', Operation.LIST_NAMESPACE,
                               Policy.CLOSED, [])])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.getNamespace(session, u'username',
                                                returnDescription=True,
                                                returnNamespaces=True,
                                                returnTags=True)
            yield self.assertFailure(deferred, TPathPermissionDenied)

    @inlineCallbacks
    def testCreateNamespace(self):
        """L{Facade.createNamespace} creates a new L{Namespace}."""
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            objectID = yield self.facade.createNamespace(
                session, u'username', u'name', u'A namespace.')

        self.store.rollback()
        self.assertNotIdentical(None, objectID)
        objectID = UUID(objectID)
        namespace = getNamespaces(objectIDs=[objectID]).one()
        self.assertIdentical(self.user, namespace.creator)
        self.assertEqual(u'username/name', namespace.path)
        self.assertEqual(u'name', namespace.name)
        self.assertEqual(objectID, namespace.objectID)

    @inlineCallbacks
    def testCreateNamespaceWithExistingPath(self):
        """
        L{Facade.createNamespace} raises a L{TNamespaceAlreadyExists}
        exception if the new L{Namespace} already exists.
        """
        createNamespace(self.user, u'username/name', self.user.namespace.id)
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.createNamespace(session, u'username',
                                                   u'name', u'A namespace.')
            yield self.assertFailure(deferred, TNamespaceAlreadyExists)

    @inlineCallbacks
    def testCreateNamespaceWithUnknownParent(self):
        """
        L{Facade.createNamespace} raises a L{TNonexistentNamespace} exception
        if a non-existent parent L{Namespace} is specified.
        """
        createNamespace(self.user, u'username/name', self.user.namespace.id)
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.createNamespace(session, u'unknown/parent',
                                                   u'name', u'A  namespace.')
            yield self.assertFailure(deferred, TNonexistentNamespace)

    @inlineCallbacks
    def testCreateNamespaceWithInvalidPath(self):
        """
        L{Facade.createNamespace} raises a L{TInvalidPath} exception
        if the path of the L{Namespace} is not well formed.
        """
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.createNamespace(session, u'username',
                                                   u'bad name', u'description')
            yield self.assertFailure(deferred, TInvalidPath)

    @inlineCallbacks
    def testCreateNamespaceImplicitlyCreatesParent(self):
        """
        L{Facade.createNamespace} implicitly creates parent L{Namespace}s if
        they don't exist.
        """
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            objectID = yield self.facade.createNamespace(
                session, u'username/parent', u'name', u'A namespace.')
            namespace = yield self.facade.getNamespace(
                session, u'username/parent/name', returnDescription=False,
                returnNamespaces=False, returnTags=False)
            self.assertEqual(objectID, namespace.objectId)

    @inlineCallbacks
    def testCreateIsDenied(self):
        """
        L{Facade.createNamespace} raises a L{TPathPermissionDenied} exception
        if the user doesn't have C{CREATE} permissions on the parent
        L{Namespace}.
        """
        self.permissions.set([(u'username', Operation.CREATE_NAMESPACE,
                               Policy.CLOSED, [])])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.createNamespace(session, u'username',
                                                   u'test', u'description')
            yield self.assertFailure(deferred, TPathPermissionDenied)

    @inlineCallbacks
    def testUpdateNamespace(self):
        """
        L{Facade.updateNamespace} updates the description for an existing
        L{Namespace}.
        """
        namespaces = NamespaceAPI(self.user)
        namespaces.create([(u'username/name', u'A namespace.')])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            yield self.facade.updateNamespace(session, u'username/name',
                                              u'A new description.')

        self.store.rollback()
        result = namespaces.get([u'username/name'], withDescriptions=True)
        self.assertEqual(u'A new description.',
                         result[u'username/name']['description'])

    @inlineCallbacks
    def testUpdateNamespaceWithUnknownPath(self):
        """
        L{Facade.updateNamespace} raises a L{TNonexistentNamespace} exception
        if the requested L{Namespace.path} doesn't exist.
        """
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.updateNamespace(
                session, u'username/unknown', u'A new description.')
            yield self.assertFailure(deferred, TNonexistentNamespace)

    @inlineCallbacks
    def testUpdateIsDenied(self):
        """
        L{Facade.updateNamespace} raises a L{TPathPermissionDenied} exception
        if the user doesn't have C{UPDATE} permissions on the specified
        L{Namespace}.
        """
        self.permissions.set([(u'username', Operation.UPDATE_NAMESPACE,
                               Policy.CLOSED, [])])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.updateNamespace(session, u'username',
                                                   u'description')
            yield self.assertFailure(deferred, TPathPermissionDenied)

    @inlineCallbacks
    def testDeleteNamespace(self):
        """L{Facade.deleteNamespace} deletes a L{Namespace}."""
        namespaces = NamespaceAPI(self.user)
        namespaces.create([(u'username/name', u'A namespace.')])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            yield self.facade.deleteNamespace(session, u'username/name')

        self.store.rollback()
        self.assertEqual({}, namespaces.get([u'username/name']))

    @inlineCallbacks
    def testDeleteNamespaceWithUnknownPath(self):
        """
        L{Facade.deleteNamespace} raises a L{TNonexistentNamespace} exception
        if the requested L{Namespace.path} doesn't exist.
        """
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.deleteNamespace(session,
                                                   u'username/unknown')
            yield self.assertFailure(deferred, TNonexistentNamespace)

    @inlineCallbacks
    def testDeleteNamespaceWithData(self):
        """
        L{Facade.deleteNamespace} raises a L{TNamespaceNotEmpty} exception if
        the requested L{Namespace} has child data such as other L{Namespace}s
        or L{Tag}s.
        """
        namespaces = NamespaceAPI(self.user)
        namespaces.create([(u'username/parent', u'A parent namespace.')])
        namespaces.create([(u'username/parent/child', u'A child namespace.')])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.deleteNamespace(session, u'username/parent')
            yield self.assertFailure(deferred, TNamespaceNotEmpty)

    @inlineCallbacks
    def testDeleteIsDenied(self):
        """
        L{Facade.deleteNamespace} raises a L{TPathPermissionDenied} exception
        if the user doesn't have C{DELETE} permissions on the specified
        L{Namespace}.
        """
        namespaces = NamespaceAPI(self.user)
        namespaces.create([(u'username/test', u'description')])
        self.permissions.set([(u'username/test', Operation.DELETE_NAMESPACE,
                               Policy.OPEN, [u'username'])])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.deleteNamespace(session, u'username/test')
            yield self.assertFailure(deferred, TPathPermissionDenied)
Ejemplo n.º 18
0
class UserPermissionCheckerTest(CheckPermissionsTestMixin, FluidinfoTestCase):

    resources = [('config', ConfigResource()),
                 ('cache', CacheResource()),
                 ('store', DatabaseResource())]

    def setUp(self):
        super(UserPermissionCheckerTest, self).setUp()
        self.system = createSystemData()
        UserAPI().create([(u'username', u'password', u'User',
                           u'*****@*****.**')])
        self.user = getUser(u'username')
        self.permissions = PermissionAPI(self.user)

    def testCheckOpenPermission(self):
        """
        L{checkPermissions} grants access when the policy is C{Policy.OPEN}
        and the L{User.id} is not in the exceptions list.
        """
        TagAPI(self.user).create([(u'username/tag', u'description')])
        self.permissions.set([(u'username/tag', Operation.UPDATE_TAG,
                               Policy.OPEN, [])])

        values = [(u'username/tag', Operation.UPDATE_TAG)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([], deniedOperations)

    def testCheckOpenPermissionWithException(self):
        """
        L{checkPermissions} denies access when the policy is C{Policy.OPEN}
        and the L{User.id} is in the exceptions list.
        """
        TagAPI(self.user).create([(u'username/tag', u'description')])
        self.permissions.set([(u'username/tag', Operation.UPDATE_TAG,
                               Policy.OPEN, [u'username'])])

        values = [(u'username/tag', Operation.UPDATE_TAG)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([(u'username/tag', Operation.UPDATE_TAG)],
                         list(deniedOperations))

    def testCheckClosedPermission(self):
        """
        L{checkPermissions} denies access when the policy is
        C{Policy.CLOSED} and the L{User.id} is not in the exceptions list.
        """
        TagAPI(self.user).create([(u'username/tag', u'description')])
        self.permissions.set([(u'username/tag', Operation.UPDATE_TAG,
                               Policy.CLOSED, [])])

        values = [(u'username/tag', Operation.UPDATE_TAG)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([(u'username/tag', Operation.UPDATE_TAG)],
                         deniedOperations)

    def testCheckClosedPermissionWithException(self):
        """
        L{checkPermissions} grants access when the policy is C{Policy.OPEN}
        and the L{User.id} is in the exceptions list.
        """
        TagAPI(self.user).create([(u'username/tag', u'description')])
        self.permissions.set([(u'username/tag', Operation.UPDATE_TAG,
                               Policy.CLOSED, [u'username'])])

        values = [(u'username/tag', Operation.UPDATE_TAG)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([], deniedOperations)

    def testCheckMultipleOpenPermissions(self):
        """L{checkPermissions} can check multiple permissions."""
        UserAPI().create([(u'user1', 'hash', u'User', u'*****@*****.**')])
        UserAPI().create([(u'user2', 'hash', u'User', u'*****@*****.**')])
        user1 = getUser(u'user1')
        user2 = getUser(u'user2')

        TagAPI(user1).create([(u'user1/tag', u'description')])
        self.permissions.set([(u'user1/tag', Operation.UPDATE_TAG,
                               Policy.OPEN, [u'user1', u'user2'])])

        TagAPI(user2).create([(u'user2/tag', u'description')])
        self.permissions.set([(u'user2/tag', Operation.WRITE_TAG_VALUE,
                               Policy.CLOSED, [u'username'])])

        values = [(u'user1/tag', Operation.UPDATE_TAG),
                  (u'user2/tag', Operation.WRITE_TAG_VALUE)]

        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([], deniedOperations)

    def testCheckUserWithUnknownPath(self):
        """
        L{checkPermissions} raises L{UnknownPathError} if a given path does
        not exist.
        """
        values = [(u'unknown/path', Operation.LIST_NAMESPACE)]
        error = self.assertRaises(UnknownPathError, checkPermissions,
                                  self.user, values)
        self.assertEqual([u'unknown/path'], error.paths)

    def testCheckUserWithImplicitTagPath(self):
        """
        L{checkPermissions} ignores an unknown path when a
        L{Operation.WRITE_TAG_VALUE} operation is requested and when the user
        has L{Operation.CREATE_NAMESPACE} access on the parent L{Namespace}.
        """
        values = [(u'username/unknown', Operation.WRITE_TAG_VALUE)]
        self.assertEqual([], checkPermissions(self.user, values))

    def testCheckUserWithImplicitNamespacePath(self):
        """
        L{checkPermissions} ignores an unknown path when a
        L{Operation.CREATE_NAMESPACE} operation is requested and when the user
        has L{Operation.CREATE_NAMESPACE} access on the final existing
        parent's L{Namespace}.
        """
        values = [(u'username/namespace', Operation.CREATE_NAMESPACE)]
        self.assertEqual([], checkPermissions(self.user, values))

    def testCheckUserWithImplicitTagAndNamespace(self):
        """
        L{checkPermissions} ignores an unknown path when a
        L{Operation.WRITE_TAG_VALUE} operation is requested and when the user
        has L{Operation.CREATE_NAMESPACE} access on the final existing
        parent's L{Namespace}.
        """
        values = set([(u'username/tag', Operation.WRITE_TAG_VALUE),
                      (u'username/namespace/tag', Operation.WRITE_TAG_VALUE)])
        self.assertEqual([], checkPermissions(self.user, values))

    def testCheckUserWithImplicitNestedNamespacePath(self):
        """
        L{checkPermissions} does a recursive check to find the parent
        L{Namespace} when a path includes many unknown segments.
        """
        values = [(u'username/nested/namespace', Operation.CREATE_NAMESPACE)]
        self.assertEqual([], checkPermissions(self.user, values))

    def testCheckUserWithFluidDBSlashIDVirtualPath(self):
        """
        An L{UnknownPathError} is not raised when the special C{fluiddb/id}
        virtual tag is encountered and L{Tag}-related permission checks always
        succeed.
        """
        values = [(u'fluiddb/id', Operation.READ_TAG_VALUE)]
        self.assertEqual([], checkPermissions(self.user, values))

    def testCheckUserWithMissingPermission(self):
        """
        L{checkPermissions} denies the operation if, for some
        reason, a permission is not available for the entity being requested.
        """
        TagAPI(self.user).create([(u'username/tag', u'description')])
        # FIXME: don't use data functions here.
        [(tag, permission)] = getTagPermissions([u'username/tag'])
        self.store.remove(permission)
        values = [(u'username/tag', Operation.UPDATE_TAG)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([(u'username/tag', Operation.UPDATE_TAG)],
                         deniedOperations)

    def testCheckReturnsMultipleDeniedPermissions(self):
        """
        L{checkPermissions} returns a C{list} of all denied paths and
        L{Operation}s for the requested actions.
        """
        UserAPI().create([(u'user1', 'hash', u'User', u'*****@*****.**')])
        UserAPI().create([(u'user2', 'hash', u'User', u'*****@*****.**')])
        user1 = getUser(u'user1')
        user2 = getUser(u'user2')

        TagAPI(user1).create([(u'user1/tag', u'description')])
        self.permissions.set([(u'user1/tag', Operation.UPDATE_TAG,
                               Policy.OPEN, [u'user1', u'user2'])])

        TagAPI(user2).create([(u'user2/tag', u'description')])
        self.permissions.set([(u'user2/tag', Operation.WRITE_TAG_VALUE,
                               Policy.OPEN, [u'username'])])

        values = [(u'user1/tag', Operation.UPDATE_TAG),
                  (u'user2/tag', Operation.WRITE_TAG_VALUE)]
        deniedOperations = checkPermissions(self.user, values)
        expected = [(u'user2/tag', Operation.WRITE_TAG_VALUE)]
        self.assertEqual(sorted(expected), sorted(deniedOperations))

    def testCheckUserManagerHasAccessToPerformUserOperations(self):
        """
        L{checkPermissions} always allows user L{Operation}s for
        L{Role.USER_MANAGER} users.
        """
        self.user.role = Role.USER_MANAGER
        values = [(u'username', Operation.CREATE_USER),
                  (u'username', Operation.UPDATE_USER),
                  (u'username', Operation.DELETE_USER)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([], deniedOperations)

    def testCheckCreateRootNamespaceIsAlwaysDeniedForNormalUser(self):
        """
        L{checkPermissions} always denies C{CREATE_NAMESPACE} access on the
        root namespace for normal users.
        """
        values = [(None, Operation.CREATE_NAMESPACE)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([(None, Operation.CREATE_NAMESPACE)],
                         deniedOperations)

    def testCheckDeleteRootNamespaceIsAlwaysDeniedForNormalUser(self):
        """
        L{checkPermissions} always denies C{DELETE_NAMESPACE} access on the
        root namespace for normal users.
        """
        values = [(u'username', Operation.DELETE_NAMESPACE)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([(u'username', Operation.DELETE_NAMESPACE)],
                         deniedOperations)

    def testCheckCreateObjectIsAlwaysGrantedForNormalUser(self):
        """
        L{checkPermissions} always grants C{CREATE_OBJECT} access for
        normal users.
        """
        values = [(u'', Operation.CREATE_OBJECT)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([], deniedOperations)

    def testCheckCreateUserIsAlwaysDeniedForNormalUser(self):
        """
        L{checkPermissions} always denies C{CREATE_USER} access for normal
        users.
        """
        values = [(u'username', Operation.CREATE_USER)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([(u'username', Operation.CREATE_USER)],
                         deniedOperations)

    def testCheckUpdateUserIsDeniedForOtherNormalUsers(self):
        """
        L{checkPermissions} denies C{UPDATE_USER} access for normal
        users except the own user.
        """
        UserAPI().create([(u'otheruser', u'password', u'User',
                           u'*****@*****.**')])
        values = [(u'otheruser', Operation.UPDATE_USER)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([(u'otheruser', Operation.UPDATE_USER)],
                         deniedOperations)

    def testCheckUpdateUserIsAllowedForTheOwnUser(self):
        """
        L{checkPermissions} allows C{UPDATE_USER} access for normal
        users if the requesting user is the same modified user.
        """
        values = [(u'username', Operation.UPDATE_USER)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([], deniedOperations)
Ejemplo n.º 19
0
class SuperuserPermissionCheckerTest(CheckPermissionsTestMixin,
                                     FluidinfoTestCase):

    resources = [('config', ConfigResource()),
                 ('cache', CacheResource()),
                 ('store', DatabaseResource())]

    def setUp(self):
        super(SuperuserPermissionCheckerTest, self).setUp()
        self.system = createSystemData()
        UserAPI().create([(u'username', u'password', u'User',
                           u'*****@*****.**')])
        self.user = getUser(u'username')
        self.permissions = PermissionAPI(self.user)

    def testCheckWithSuperuser(self):
        """
        L{checkPermissions} always grants access if the user is superuser.
        """
        TagAPI(self.user).create([(u'username/path', u'description')])
        NamespaceAPI(self.user).create([(u'username/path', u'description')])
        superuser = self.system.users[u'fluiddb']
        # Close all permissions for the tag
        values = [(u'username/path', operation, Policy.CLOSED, [])
                  for operation in Operation.PATH_OPERATIONS]
        self.permissions.set(values)

        values = [(u'username/path', operation)
                  for operation in Operation.PATH_OPERATIONS]
        deniedOperations = checkPermissions(superuser, values)
        self.assertEqual([], deniedOperations)

    def testCheckWithSuperuserUnknownPaths(self):
        """
        L{checkPermissions} raises L{UnknownPathError} if a superuser checks
        permissions for nonexistent tags.
        """
        superuser = self.system.users[u'fluiddb']
        values = [(u'unknown/path', operation)
                  for operation in Operation.PATH_OPERATIONS]
        self.assertRaises(UnknownPathError,
                          checkPermissions, superuser, values)

    def testCheckWithSuperuserWithImplicitPaths(self):
        """
        L{checkPermissions} raises L{UnknownPathError} if a superuser
        checks permissions for nonexistent tags, even if it might be possible
        to create them implicitly.
        """
        superuser = self.system.users[u'fluiddb']
        values = [(u'fluiddb/path', operation)
                  for operation in Operation.PATH_OPERATIONS]
        self.assertRaises(UnknownPathError,
                          checkPermissions, superuser, values)

    def testCheckWithSuperuserWithMissingPermission(self):
        """
        L{checkPermissions} always grants access if the user is superuser,
        even if there is no permission defined for the entity for which access
        is requested.
        """
        TagAPI(self.user).create([(u'username/path', u'description')])
        NamespaceAPI(self.user).create([(u'username/path', u'description')])
        superuser = self.system.users[u'fluiddb']
        # Close all permissions for the tag
        values = [(u'username/path', operation, Policy.CLOSED, [])
                  for operation in Operation.NAMESPACE_OPERATIONS]
        self.permissions.set(values)

        values = [(u'username/path', operation)
                  for operation in Operation.NAMESPACE_OPERATIONS]
        deniedOperations = checkPermissions(superuser, values)
        self.assertEqual([], deniedOperations)

    def testCheckSuperuserWithFluidDBSlashIDVirtualPath(self):
        """
        An L{UnknownPathError} is not raised when the special C{fluiddb/id}
        virtual tag is encountered and L{Tag}-related permission checks always
        succeed.
        """
        superuser = self.system.users[u'fluiddb']
        values = [(u'fluiddb/id', Operation.READ_TAG_VALUE)]
        self.assertEqual([], checkPermissions(superuser, values))
Ejemplo n.º 20
0
class FacadeNamespaceTest(FluidinfoTestCase):

    resources = [('cache', CacheResource()), ('config', ConfigResource()),
                 ('log', LoggingResource()), ('store', DatabaseResource()),
                 ('threadPool', ThreadPoolResource())]

    def setUp(self):
        super(FacadeNamespaceTest, self).setUp()
        createSystemData()
        self.transact = Transact(self.threadPool)
        factory = FluidinfoSessionFactory('API-9000')
        self.facade = Facade(self.transact, factory)
        UserAPI().create([(u'username', u'password', u'User',
                           u'*****@*****.**')])
        self.user = getUser(u'username')
        self.permissions = PermissionAPI(self.user)

    @inlineCallbacks
    def testGetNamespaceWithoutData(self):
        """
        L{Facade.getNamespace} raises a L{TNonexistentNamespace} exception if
        the requested L{Namespace.path} doesn't exist.
        """
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.getNamespace(session, u'username/unknown',
                                                False, False, False)
            yield self.assertFailure(deferred, TNonexistentNamespace)

    @inlineCallbacks
    def testGetNamespace(self):
        """
        L{Facade.getNamespace} returns a L{TNamespace} instance with
        information about the requested L{Namespace}.
        """
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            result = yield self.facade.getNamespace(session, u'username',
                                                    False, False, False)

        self.assertEqual(str(self.user.namespace.objectID), result.objectId)
        self.assertEqual(u'username', result.path)

    @inlineCallbacks
    def testGetNamespaceWithDescription(self):
        """
        L{Facade.getNamespace} includes the L{Namespace.description}, if it
        was requested.
        """
        namespaces = NamespaceAPI(self.user)
        namespaces.create([(u'username/name', u'A namespace.')])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            result = yield self.facade.getNamespace(session, u'username/name',
                                                    True, False, False)
        self.assertEqual(u'A namespace.', result.description)

    @inlineCallbacks
    def testGetNamespaceWithNamespaces(self):
        """
        L{Facade.getNamespace} includes child L{Namespace.name}s, if they were
        requested.
        """
        namespaces = NamespaceAPI(self.user)
        namespaces.create([(u'username/name', u'A namespace.')])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            result = yield self.facade.getNamespace(session, u'username',
                                                    False, True, False)
        self.assertEqual([u'name', u'private'], sorted(result.namespaces))

    @inlineCallbacks
    def testGetNamespaceWithTags(self):
        """
        L{Facade.getNamespace} includes child L{Tag.name}s, if they were
        requested.
        """
        createTag(self.user, self.user.namespace, u'tag')
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            result = yield self.facade.getNamespace(session, u'username',
                                                    False, False, True)
        self.assertEqual([u'tag'], result.tags)

    @inlineCallbacks
    def testGetNamespaceWithUnknownPath(self):
        """
        L{Facade.getNamespace} raises a L{TNonexistentNamespace} exception
        if the specified L{Namespace} doesn't exist.
        """
        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.getNamespace(session,
                                                u'unknown',
                                                returnDescription=False,
                                                returnNamespaces=False,
                                                returnTags=False)
            yield self.assertFailure(deferred, TNonexistentNamespace)

    @inlineCallbacks
    def testGetNamespaceWithPermissionDenied(self):
        """
        L{Facade.getNamespace} raises a L{TPathPermissionDenied} exception
        if the user doesn't have C{LIST} permissions on the specified
        L{Namespace}.
        """
        self.permissions.set([(u'username', Operation.LIST_NAMESPACE,
                               Policy.CLOSED, [])])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.getNamespace(session,
                                                u'username',
                                                returnDescription=True,
                                                returnNamespaces=True,
                                                returnTags=True)
            yield self.assertFailure(deferred, TPathPermissionDenied)

    @inlineCallbacks
    def testCreateNamespace(self):
        """L{Facade.createNamespace} creates a new L{Namespace}."""
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            objectID = yield self.facade.createNamespace(
                session, u'username', u'name', u'A namespace.')

        self.store.rollback()
        self.assertNotIdentical(None, objectID)
        objectID = UUID(objectID)
        namespace = getNamespaces(objectIDs=[objectID]).one()
        self.assertIdentical(self.user, namespace.creator)
        self.assertEqual(u'username/name', namespace.path)
        self.assertEqual(u'name', namespace.name)
        self.assertEqual(objectID, namespace.objectID)

    @inlineCallbacks
    def testCreateNamespaceWithExistingPath(self):
        """
        L{Facade.createNamespace} raises a L{TNamespaceAlreadyExists}
        exception if the new L{Namespace} already exists.
        """
        createNamespace(self.user, u'username/name', self.user.namespace.id)
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.createNamespace(session, u'username',
                                                   u'name', u'A namespace.')
            yield self.assertFailure(deferred, TNamespaceAlreadyExists)

    @inlineCallbacks
    def testCreateNamespaceWithUnknownParent(self):
        """
        L{Facade.createNamespace} raises a L{TNonexistentNamespace} exception
        if a non-existent parent L{Namespace} is specified.
        """
        createNamespace(self.user, u'username/name', self.user.namespace.id)
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.createNamespace(session, u'unknown/parent',
                                                   u'name', u'A  namespace.')
            yield self.assertFailure(deferred, TNonexistentNamespace)

    @inlineCallbacks
    def testCreateNamespaceWithInvalidPath(self):
        """
        L{Facade.createNamespace} raises a L{TInvalidPath} exception
        if the path of the L{Namespace} is not well formed.
        """
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.createNamespace(session, u'username',
                                                   u'bad name', u'description')
            yield self.assertFailure(deferred, TInvalidPath)

    @inlineCallbacks
    def testCreateNamespaceImplicitlyCreatesParent(self):
        """
        L{Facade.createNamespace} implicitly creates parent L{Namespace}s if
        they don't exist.
        """
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            objectID = yield self.facade.createNamespace(
                session, u'username/parent', u'name', u'A namespace.')
            namespace = yield self.facade.getNamespace(session,
                                                       u'username/parent/name',
                                                       returnDescription=False,
                                                       returnNamespaces=False,
                                                       returnTags=False)
            self.assertEqual(objectID, namespace.objectId)

    @inlineCallbacks
    def testCreateIsDenied(self):
        """
        L{Facade.createNamespace} raises a L{TPathPermissionDenied} exception
        if the user doesn't have C{CREATE} permissions on the parent
        L{Namespace}.
        """
        self.permissions.set([(u'username', Operation.CREATE_NAMESPACE,
                               Policy.CLOSED, [])])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.createNamespace(session, u'username',
                                                   u'test', u'description')
            yield self.assertFailure(deferred, TPathPermissionDenied)

    @inlineCallbacks
    def testUpdateNamespace(self):
        """
        L{Facade.updateNamespace} updates the description for an existing
        L{Namespace}.
        """
        namespaces = NamespaceAPI(self.user)
        namespaces.create([(u'username/name', u'A namespace.')])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            yield self.facade.updateNamespace(session, u'username/name',
                                              u'A new description.')

        self.store.rollback()
        result = namespaces.get([u'username/name'], withDescriptions=True)
        self.assertEqual(u'A new description.',
                         result[u'username/name']['description'])

    @inlineCallbacks
    def testUpdateNamespaceWithUnknownPath(self):
        """
        L{Facade.updateNamespace} raises a L{TNonexistentNamespace} exception
        if the requested L{Namespace.path} doesn't exist.
        """
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.updateNamespace(session,
                                                   u'username/unknown',
                                                   u'A new description.')
            yield self.assertFailure(deferred, TNonexistentNamespace)

    @inlineCallbacks
    def testUpdateIsDenied(self):
        """
        L{Facade.updateNamespace} raises a L{TPathPermissionDenied} exception
        if the user doesn't have C{UPDATE} permissions on the specified
        L{Namespace}.
        """
        self.permissions.set([(u'username', Operation.UPDATE_NAMESPACE,
                               Policy.CLOSED, [])])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.updateNamespace(session, u'username',
                                                   u'description')
            yield self.assertFailure(deferred, TPathPermissionDenied)

    @inlineCallbacks
    def testDeleteNamespace(self):
        """L{Facade.deleteNamespace} deletes a L{Namespace}."""
        namespaces = NamespaceAPI(self.user)
        namespaces.create([(u'username/name', u'A namespace.')])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            yield self.facade.deleteNamespace(session, u'username/name')

        self.store.rollback()
        self.assertEqual({}, namespaces.get([u'username/name']))

    @inlineCallbacks
    def testDeleteNamespaceWithUnknownPath(self):
        """
        L{Facade.deleteNamespace} raises a L{TNonexistentNamespace} exception
        if the requested L{Namespace.path} doesn't exist.
        """
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.deleteNamespace(session,
                                                   u'username/unknown')
            yield self.assertFailure(deferred, TNonexistentNamespace)

    @inlineCallbacks
    def testDeleteNamespaceWithData(self):
        """
        L{Facade.deleteNamespace} raises a L{TNamespaceNotEmpty} exception if
        the requested L{Namespace} has child data such as other L{Namespace}s
        or L{Tag}s.
        """
        namespaces = NamespaceAPI(self.user)
        namespaces.create([(u'username/parent', u'A parent namespace.')])
        namespaces.create([(u'username/parent/child', u'A child namespace.')])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.deleteNamespace(session, u'username/parent')
            yield self.assertFailure(deferred, TNamespaceNotEmpty)

    @inlineCallbacks
    def testDeleteIsDenied(self):
        """
        L{Facade.deleteNamespace} raises a L{TPathPermissionDenied} exception
        if the user doesn't have C{DELETE} permissions on the specified
        L{Namespace}.
        """
        namespaces = NamespaceAPI(self.user)
        namespaces.create([(u'username/test', u'description')])
        self.permissions.set([(u'username/test', Operation.DELETE_NAMESPACE,
                               Policy.OPEN, [u'username'])])
        self.store.commit()

        with login(u'username', self.user.objectID, self.transact) as session:
            deferred = self.facade.deleteNamespace(session, u'username/test')
            yield self.assertFailure(deferred, TPathPermissionDenied)
Ejemplo n.º 21
0
class UserPermissionCheckerTest(CheckPermissionsTestMixin, FluidinfoTestCase):

    resources = [('config', ConfigResource()), ('cache', CacheResource()),
                 ('store', DatabaseResource())]

    def setUp(self):
        super(UserPermissionCheckerTest, self).setUp()
        self.system = createSystemData()
        UserAPI().create([(u'username', u'password', u'User',
                           u'*****@*****.**')])
        self.user = getUser(u'username')
        self.permissions = PermissionAPI(self.user)

    def testCheckOpenPermission(self):
        """
        L{checkPermissions} grants access when the policy is C{Policy.OPEN}
        and the L{User.id} is not in the exceptions list.
        """
        TagAPI(self.user).create([(u'username/tag', u'description')])
        self.permissions.set([(u'username/tag', Operation.UPDATE_TAG,
                               Policy.OPEN, [])])

        values = [(u'username/tag', Operation.UPDATE_TAG)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([], deniedOperations)

    def testCheckOpenPermissionWithException(self):
        """
        L{checkPermissions} denies access when the policy is C{Policy.OPEN}
        and the L{User.id} is in the exceptions list.
        """
        TagAPI(self.user).create([(u'username/tag', u'description')])
        self.permissions.set([(u'username/tag', Operation.UPDATE_TAG,
                               Policy.OPEN, [u'username'])])

        values = [(u'username/tag', Operation.UPDATE_TAG)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([(u'username/tag', Operation.UPDATE_TAG)],
                         list(deniedOperations))

    def testCheckClosedPermission(self):
        """
        L{checkPermissions} denies access when the policy is
        C{Policy.CLOSED} and the L{User.id} is not in the exceptions list.
        """
        TagAPI(self.user).create([(u'username/tag', u'description')])
        self.permissions.set([(u'username/tag', Operation.UPDATE_TAG,
                               Policy.CLOSED, [])])

        values = [(u'username/tag', Operation.UPDATE_TAG)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([(u'username/tag', Operation.UPDATE_TAG)],
                         deniedOperations)

    def testCheckClosedPermissionWithException(self):
        """
        L{checkPermissions} grants access when the policy is C{Policy.OPEN}
        and the L{User.id} is in the exceptions list.
        """
        TagAPI(self.user).create([(u'username/tag', u'description')])
        self.permissions.set([(u'username/tag', Operation.UPDATE_TAG,
                               Policy.CLOSED, [u'username'])])

        values = [(u'username/tag', Operation.UPDATE_TAG)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([], deniedOperations)

    def testCheckMultipleOpenPermissions(self):
        """L{checkPermissions} can check multiple permissions."""
        UserAPI().create([(u'user1', 'hash', u'User', u'*****@*****.**')])
        UserAPI().create([(u'user2', 'hash', u'User', u'*****@*****.**')])
        user1 = getUser(u'user1')
        user2 = getUser(u'user2')

        TagAPI(user1).create([(u'user1/tag', u'description')])
        self.permissions.set([(u'user1/tag', Operation.UPDATE_TAG, Policy.OPEN,
                               [u'user1', u'user2'])])

        TagAPI(user2).create([(u'user2/tag', u'description')])
        self.permissions.set([(u'user2/tag', Operation.WRITE_TAG_VALUE,
                               Policy.CLOSED, [u'username'])])

        values = [(u'user1/tag', Operation.UPDATE_TAG),
                  (u'user2/tag', Operation.WRITE_TAG_VALUE)]

        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([], deniedOperations)

    def testCheckUserWithUnknownPath(self):
        """
        L{checkPermissions} raises L{UnknownPathError} if a given path does
        not exist.
        """
        values = [(u'unknown/path', Operation.LIST_NAMESPACE)]
        error = self.assertRaises(UnknownPathError, checkPermissions,
                                  self.user, values)
        self.assertEqual([u'unknown/path'], error.paths)

    def testCheckUserWithImplicitTagPath(self):
        """
        L{checkPermissions} ignores an unknown path when a
        L{Operation.WRITE_TAG_VALUE} operation is requested and when the user
        has L{Operation.CREATE_NAMESPACE} access on the parent L{Namespace}.
        """
        values = [(u'username/unknown', Operation.WRITE_TAG_VALUE)]
        self.assertEqual([], checkPermissions(self.user, values))

    def testCheckUserWithImplicitNamespacePath(self):
        """
        L{checkPermissions} ignores an unknown path when a
        L{Operation.CREATE_NAMESPACE} operation is requested and when the user
        has L{Operation.CREATE_NAMESPACE} access on the final existing
        parent's L{Namespace}.
        """
        values = [(u'username/namespace', Operation.CREATE_NAMESPACE)]
        self.assertEqual([], checkPermissions(self.user, values))

    def testCheckUserWithImplicitTagAndNamespace(self):
        """
        L{checkPermissions} ignores an unknown path when a
        L{Operation.WRITE_TAG_VALUE} operation is requested and when the user
        has L{Operation.CREATE_NAMESPACE} access on the final existing
        parent's L{Namespace}.
        """
        values = set([(u'username/tag', Operation.WRITE_TAG_VALUE),
                      (u'username/namespace/tag', Operation.WRITE_TAG_VALUE)])
        self.assertEqual([], checkPermissions(self.user, values))

    def testCheckUserWithImplicitNestedNamespacePath(self):
        """
        L{checkPermissions} does a recursive check to find the parent
        L{Namespace} when a path includes many unknown segments.
        """
        values = [(u'username/nested/namespace', Operation.CREATE_NAMESPACE)]
        self.assertEqual([], checkPermissions(self.user, values))

    def testCheckUserWithFluidDBSlashIDVirtualPath(self):
        """
        An L{UnknownPathError} is not raised when the special C{fluiddb/id}
        virtual tag is encountered and L{Tag}-related permission checks always
        succeed.
        """
        values = [(u'fluiddb/id', Operation.READ_TAG_VALUE)]
        self.assertEqual([], checkPermissions(self.user, values))

    def testCheckUserWithMissingPermission(self):
        """
        L{checkPermissions} denies the operation if, for some
        reason, a permission is not available for the entity being requested.
        """
        TagAPI(self.user).create([(u'username/tag', u'description')])
        # FIXME: don't use data functions here.
        [(tag, permission)] = getTagPermissions([u'username/tag'])
        self.store.remove(permission)
        values = [(u'username/tag', Operation.UPDATE_TAG)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([(u'username/tag', Operation.UPDATE_TAG)],
                         deniedOperations)

    def testCheckReturnsMultipleDeniedPermissions(self):
        """
        L{checkPermissions} returns a C{list} of all denied paths and
        L{Operation}s for the requested actions.
        """
        UserAPI().create([(u'user1', 'hash', u'User', u'*****@*****.**')])
        UserAPI().create([(u'user2', 'hash', u'User', u'*****@*****.**')])
        user1 = getUser(u'user1')
        user2 = getUser(u'user2')

        TagAPI(user1).create([(u'user1/tag', u'description')])
        self.permissions.set([(u'user1/tag', Operation.UPDATE_TAG, Policy.OPEN,
                               [u'user1', u'user2'])])

        TagAPI(user2).create([(u'user2/tag', u'description')])
        self.permissions.set([(u'user2/tag', Operation.WRITE_TAG_VALUE,
                               Policy.OPEN, [u'username'])])

        values = [(u'user1/tag', Operation.UPDATE_TAG),
                  (u'user2/tag', Operation.WRITE_TAG_VALUE)]
        deniedOperations = checkPermissions(self.user, values)
        expected = [(u'user2/tag', Operation.WRITE_TAG_VALUE)]
        self.assertEqual(sorted(expected), sorted(deniedOperations))

    def testCheckUserManagerHasAccessToPerformUserOperations(self):
        """
        L{checkPermissions} always allows user L{Operation}s for
        L{Role.USER_MANAGER} users.
        """
        self.user.role = Role.USER_MANAGER
        values = [(u'username', Operation.CREATE_USER),
                  (u'username', Operation.UPDATE_USER),
                  (u'username', Operation.DELETE_USER)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([], deniedOperations)

    def testCheckCreateRootNamespaceIsAlwaysDeniedForNormalUser(self):
        """
        L{checkPermissions} always denies C{CREATE_NAMESPACE} access on the
        root namespace for normal users.
        """
        values = [(None, Operation.CREATE_NAMESPACE)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([(None, Operation.CREATE_NAMESPACE)],
                         deniedOperations)

    def testCheckDeleteRootNamespaceIsAlwaysDeniedForNormalUser(self):
        """
        L{checkPermissions} always denies C{DELETE_NAMESPACE} access on the
        root namespace for normal users.
        """
        values = [(u'username', Operation.DELETE_NAMESPACE)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([(u'username', Operation.DELETE_NAMESPACE)],
                         deniedOperations)

    def testCheckCreateObjectIsAlwaysGrantedForNormalUser(self):
        """
        L{checkPermissions} always grants C{CREATE_OBJECT} access for
        normal users.
        """
        values = [(u'', Operation.CREATE_OBJECT)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([], deniedOperations)

    def testCheckCreateUserIsAlwaysDeniedForNormalUser(self):
        """
        L{checkPermissions} always denies C{CREATE_USER} access for normal
        users.
        """
        values = [(u'username', Operation.CREATE_USER)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([(u'username', Operation.CREATE_USER)],
                         deniedOperations)

    def testCheckUpdateUserIsDeniedForOtherNormalUsers(self):
        """
        L{checkPermissions} denies C{UPDATE_USER} access for normal
        users except the own user.
        """
        UserAPI().create([(u'otheruser', u'password', u'User',
                           u'*****@*****.**')])
        values = [(u'otheruser', Operation.UPDATE_USER)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([(u'otheruser', Operation.UPDATE_USER)],
                         deniedOperations)

    def testCheckUpdateUserIsAllowedForTheOwnUser(self):
        """
        L{checkPermissions} allows C{UPDATE_USER} access for normal
        users if the requesting user is the same modified user.
        """
        values = [(u'username', Operation.UPDATE_USER)]
        deniedOperations = checkPermissions(self.user, values)
        self.assertEqual([], deniedOperations)
Ejemplo n.º 22
0
class SuperuserPermissionCheckerTest(CheckPermissionsTestMixin,
                                     FluidinfoTestCase):

    resources = [('config', ConfigResource()), ('cache', CacheResource()),
                 ('store', DatabaseResource())]

    def setUp(self):
        super(SuperuserPermissionCheckerTest, self).setUp()
        self.system = createSystemData()
        UserAPI().create([(u'username', u'password', u'User',
                           u'*****@*****.**')])
        self.user = getUser(u'username')
        self.permissions = PermissionAPI(self.user)

    def testCheckWithSuperuser(self):
        """
        L{checkPermissions} always grants access if the user is superuser.
        """
        TagAPI(self.user).create([(u'username/path', u'description')])
        NamespaceAPI(self.user).create([(u'username/path', u'description')])
        superuser = self.system.users[u'fluiddb']
        # Close all permissions for the tag
        values = [(u'username/path', operation, Policy.CLOSED, [])
                  for operation in Operation.PATH_OPERATIONS]
        self.permissions.set(values)

        values = [(u'username/path', operation)
                  for operation in Operation.PATH_OPERATIONS]
        deniedOperations = checkPermissions(superuser, values)
        self.assertEqual([], deniedOperations)

    def testCheckWithSuperuserUnknownPaths(self):
        """
        L{checkPermissions} raises L{UnknownPathError} if a superuser checks
        permissions for nonexistent tags.
        """
        superuser = self.system.users[u'fluiddb']
        values = [(u'unknown/path', operation)
                  for operation in Operation.PATH_OPERATIONS]
        self.assertRaises(UnknownPathError, checkPermissions, superuser,
                          values)

    def testCheckWithSuperuserWithImplicitPaths(self):
        """
        L{checkPermissions} raises L{UnknownPathError} if a superuser
        checks permissions for nonexistent tags, even if it might be possible
        to create them implicitly.
        """
        superuser = self.system.users[u'fluiddb']
        values = [(u'fluiddb/path', operation)
                  for operation in Operation.PATH_OPERATIONS]
        self.assertRaises(UnknownPathError, checkPermissions, superuser,
                          values)

    def testCheckWithSuperuserWithMissingPermission(self):
        """
        L{checkPermissions} always grants access if the user is superuser,
        even if there is no permission defined for the entity for which access
        is requested.
        """
        TagAPI(self.user).create([(u'username/path', u'description')])
        NamespaceAPI(self.user).create([(u'username/path', u'description')])
        superuser = self.system.users[u'fluiddb']
        # Close all permissions for the tag
        values = [(u'username/path', operation, Policy.CLOSED, [])
                  for operation in Operation.NAMESPACE_OPERATIONS]
        self.permissions.set(values)

        values = [(u'username/path', operation)
                  for operation in Operation.NAMESPACE_OPERATIONS]
        deniedOperations = checkPermissions(superuser, values)
        self.assertEqual([], deniedOperations)

    def testCheckSuperuserWithFluidDBSlashIDVirtualPath(self):
        """
        An L{UnknownPathError} is not raised when the special C{fluiddb/id}
        virtual tag is encountered and L{Tag}-related permission checks always
        succeed.
        """
        superuser = self.system.users[u'fluiddb']
        values = [(u'fluiddb/id', Operation.READ_TAG_VALUE)]
        self.assertEqual([], checkPermissions(superuser, values))
Ejemplo n.º 23
0
 def __init__(self, user):
     self._api = PermissionAPI(user, factory=CachingAPIFactory())
Ejemplo n.º 24
0
 def permissions(self, user):
     """Get a new L{PermissionAPI} instance."""
     from fluiddb.model.permission import PermissionAPI
     return PermissionAPI(user)