Example #1
0
    def testDeleteTag(self):
        """L{FacadeTagMixin.deleteTag} deletes a L{Tag}."""
        tags = TagAPI(self.user)
        tags.create([(u'username/name', u'A tag.')])
        self.store.commit()
        with login(u'username', uuid4(), self.transact) as session:
            yield self.facade.deleteTag(session, u'username/name')

        self.store.rollback()
        self.assertEqual({}, tags.get([u'username/name']))
Example #2
0
    def testUpdateTag(self):
        """
        L{FacadeTagMixin.updateTag} updates the description for an existing
        L{Tag}.
        """
        tags = TagAPI(self.user)
        tags.create([(u'username/name', u'A tag.')])
        self.store.commit()
        with login(u'username', uuid4(), self.transact) as session:
            yield self.facade.updateTag(session, u'username/name',
                                        u'A new description.')

        self.store.rollback()
        result = tags.get([u'username/name'], withDescriptions=True)
        self.assertEqual(u'A new description.',
                         result[u'username/name']['description'])
Example #3
0
class CachingTagAPI(object):
    """The public API to cached tag-related logic in the model.

    @param user: The L{User} to perform operations on behalf of.
    """

    def __init__(self, user):
        self._api = TagAPI(user, factory=CachingAPIFactory())

    def create(self, values):
        """See L{TagAPI.create}."""
        return self._api.create(values)

    def delete(self, paths):
        """See L{TagAPI.delete}.

        Permissions for deleted L{Tag}s are removed from the cache.
        """
        if isgenerator(paths):
            paths = list(paths)
        # FIXME getObjectIDs is called twice--once here and once in
        # TagAPI.delete.  It would be better if we only did this once, not to
        # mention that this breaks encapsulation by bypassing the model layer
        # and accessing the data layer directly. -jkakar
        objectIDs = set(getObjectIDs(paths))
        RecentObjectActivityCache().clear(objectIDs)
        usernames = set([path.split('/')[0] for path in paths])
        RecentUserActivityCache().clear(usernames)
        PermissionCache().clearTagPermissions(paths)
        return self._api.delete(paths)

    def get(self, paths, withDescriptions=None):
        """See L{TagAPI.get}."""
        return self._api.get(paths, withDescriptions=withDescriptions)

    def set(self, values):
        """Set L{TagAPI.set}."""
        return self._api.set(values)
Example #4
0
class CachingTagAPI(object):
    """The public API to cached tag-related logic in the model.

    @param user: The L{User} to perform operations on behalf of.
    """
    def __init__(self, user):
        self._api = TagAPI(user, factory=CachingAPIFactory())

    def create(self, values):
        """See L{TagAPI.create}."""
        return self._api.create(values)

    def delete(self, paths):
        """See L{TagAPI.delete}.

        Permissions for deleted L{Tag}s are removed from the cache.
        """
        if isgenerator(paths):
            paths = list(paths)
        # FIXME getObjectIDs is called twice--once here and once in
        # TagAPI.delete.  It would be better if we only did this once, not to
        # mention that this breaks encapsulation by bypassing the model layer
        # and accessing the data layer directly. -jkakar
        objectIDs = set(getObjectIDs(paths))
        RecentObjectActivityCache().clear(objectIDs)
        usernames = set([path.split('/')[0] for path in paths])
        RecentUserActivityCache().clear(usernames)
        PermissionCache().clearTagPermissions(paths)
        return self._api.delete(paths)

    def get(self, paths, withDescriptions=None):
        """See L{TagAPI.get}."""
        return self._api.get(paths, withDescriptions=withDescriptions)

    def set(self, values):
        """Set L{TagAPI.set}."""
        return self._api.set(values)
Example #5
0
class SecureObjectAPIWithAnonymousRoleTest(FluidinfoTestCase):

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

    def setUp(self):
        super(SecureObjectAPIWithAnonymousRoleTest, self).setUp()
        system = createSystemData()
        self.anon = system.users[u'anon']
        UserAPI().create([(u'username', u'password', u'User',
                           u'*****@*****.**')])
        self.user = getUser(u'username')
        self.tags = TagAPI(self.user)
        self.tags.create([(u'username/tag', u'description')])
        self.permissions = CachingPermissionAPI(self.user)
        self.objects = SecureObjectAPI(self.anon)

    def testCreateIsDenied(self):
        """
        L{SecureObjectAPI.create} raises a L{PermissionDeniedError} if it's
        invoked by a L{User} with the L{Role.ANONYMOUS}.
        """
        objects = SecureObjectAPI(self.anon)
        error = self.assertRaises(PermissionDeniedError, objects.create)
        self.assertEqual(self.anon.username, error.username)
        self.assertEqual([(None, Operation.CREATE_OBJECT)],
                         error.pathsAndOperations)

    def testGetTagsByObjectsPathIsAllowed(self):
        """
        L{SecureObjectAPI.getTagsByObjects} will return all the tags for
        which the anonymous user has C{Operation.READ_TAG_VALUE} permissions.
        """
        objectID = uuid4()
        values = {objectID: {u'username/tag': 16}}
        SecureTagValueAPI(self.user).set(values)
        self.permissions.set([(u'username/tag', Operation.READ_TAG_VALUE,
                               Policy.OPEN, [])])
        self.assertEqual({objectID: [u'username/tag']},
                         self.objects.getTagsByObjects([objectID]))

    def testGetTagsByObjectsReturnsOnlyAllowedTags(self):
        """
        L{SecureObjectAPI.getTagsByObjects} will return all the tags for
        which the anonymous user has C{Operation.READ_TAG_VALUE} permissions,
        but not those for which the user doesn't have.
        """
        self.tags.create([(u'username/tag1', u'description'),
                          (u'username/tag2', u'description')])
        objectID = uuid4()

        values = {objectID: {u'username/tag1': 16,
                             u'username/tag2': 16}}
        SecureTagValueAPI(self.user).set(values)

        self.permissions.set([(u'username/tag1', Operation.READ_TAG_VALUE,
                               Policy.CLOSED, []),
                              (u'username/tag2', Operation.READ_TAG_VALUE,
                               Policy.OPEN, [])])

        result = self.objects.getTagsByObjects([objectID])
        expected = {objectID: [u'username/tag2']}
        self.assertEqual(expected, result)

    def testGetTagsByObjectsReturnsNoneIfDenied(self):
        """
        L{SecureObjectAPI.getTagsByObjects} will return an empty C{dict} if
        the L{User} does not have C{Operation.READ_TAG_VALUE} permission on
        none of the L{Tag}s an object has.
        """
        self.tags.create([(u'username/tag1', u'description'),
                          (u'username/tag2', u'description')])
        objectID = uuid4()

        values = {objectID: {u'username/tag1': 16,
                             u'username/tag2': 16}}
        SecureTagValueAPI(self.user).set(values)

        self.permissions.set([(u'username/tag1', Operation.READ_TAG_VALUE,
                               Policy.CLOSED, []),
                              (u'username/tag2', Operation.READ_TAG_VALUE,
                               Policy.CLOSED, [])])

        result = self.objects.getTagsByObjects([objectID])
        self.assertEqual({}, result)

    def testGetTagsByObjectsWithCustomPermission(self):
        """
        L{SecureObjectAPI.getTagsByObjects} optionally accepts a permission
        type to check for instead of L{Operation.READ_TAG_VALUE}).
        """
        TagAPI(self.user).create([(u'username/open', u'An accessible tag'),
                                  (u'username/closed', u'A denied tag')])
        objectID = uuid4()
        SecureTagValueAPI(self.user).set({objectID: {u'username/open': 13,
                                                     u'username/closed': 17}})
        self.permissions.set([(u'username/closed', Operation.DELETE_TAG_VALUE,
                               Policy.CLOSED, [])])
        result = self.objects.getTagsByObjects(
            [objectID], permission=Operation.DELETE_TAG_VALUE)
        # Result is empty because anonymous users are never allowed to delete
        # values.
        self.assertEqual({}, result)

    def testGetTagsForObjectsOnlyReturnsAccessibleTags(self):
        """
        L{SecureObjectAPI.getTagsForObjects} only returns L{Tag.path}s that
        the user has C{Operation.READ_TAG_VALUE} permissions for.
        """
        TagAPI(self.user).create([(u'username/tag1', u'description'),
                                  (u'username/tag2', u'description')])
        objectID = uuid4()
        SecureTagValueAPI(self.user).set({objectID: {u'username/tag1': 13,
                                                     u'username/tag2': 17}})
        self.permissions.set([(u'username/tag2', Operation.READ_TAG_VALUE,
                               Policy.CLOSED, [])])
        self.assertEqual([u'username/tag1'],
                         self.objects.getTagsForObjects([objectID]))

    @inlineCallbacks
    def testSearch(self):
        """
        L{SecureObjectAPI.search} resolves the specified L{Query}s if the
        anonymous user has C{Operation.READ_TAG_VALUE} permissions on the
        requested L{Tag.path}s.
        """
        objectID = uuid4()
        index = ObjectIndex(self.client)
        yield index.update({objectID: {u'username/tag': 42}})
        yield self.client.commit()
        query = parseQuery(u'username/tag = 42')
        result = self.objects.search([query])
        result = yield result.get()
        self.assertEqual({query: set([objectID])}, result)

    @inlineCallbacks
    def testSearchWithoutPermission(self):
        """
        L{SecureObjectAPI.search} raises a L{PermissionDeniedError} if the
        anonymous user doesn't have C{Operation.READ_TAG_VALUE} permissions on
        the requested L{Tag.path}s.
        """
        objectID = uuid4()
        index = ObjectIndex(self.client)
        yield index.update({objectID: {u'username/tag': 42}})
        yield self.client.commit()
        self.permissions.set([(u'username/tag', Operation.READ_TAG_VALUE,
                               Policy.CLOSED, [])])
        query = parseQuery(u'username/tag = 42')
        error = self.assertRaises(PermissionDeniedError, self.objects.search,
                                  [query])
        self.assertEqual(u'anon', error.username)
        self.assertEqual([('username/tag', Operation.READ_TAG_VALUE)],
                         error.pathsAndOperations)

    @inlineCallbacks
    def testSearchWithImplicitObjectCreation(self):
        """
        L{SecureObjectAPI.search} doesn't raise a L{PermissionDeniedError} if
        the anonymous user tries to create new objects using C{fluiddb/about}
        queries, instead an empty result is returned.
        """
        query = parseQuery(u'fluiddb/about = "TestObject"')
        result = self.objects.search([query], True)
        result = yield result.get()
        self.assertEqual({query: set()}, result)