Skip to content

Commit

Permalink
API, sharable: deserialize users_shared_with
Browse files Browse the repository at this point in the history
- Adds a deserializer for users_shared_with. PUT a list of user ids
to update who an item is shared with.
- Invalid users are skipped, bad ids error
- (Only affects histories ATM)
- Tests added to test_HistoryManager
  • Loading branch information
carlfeberhard committed May 10, 2016
1 parent dc1924b commit 7ffa8aa
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 30 deletions.
59 changes: 29 additions & 30 deletions lib/galaxy/managers/sharable.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ def share_with( self, item, user, flush=True ):
"""
Get or create a share for the given user (or users if `user` is a list).
"""
# precondition: user has been validated
# allow user to be a list and call recursivly
if isinstance( user, list ):
return map( lambda user: self.share_with( item, user, flush=False ), user )
Expand Down Expand Up @@ -307,19 +308,7 @@ def create_unique_slug( self, item, flush=True ):
self.session().flush()
return item

# def by_slug( self, user, **kwargs ):
# """
# """
# pass

# .... display
# def display_by_username_and_slug( self, username, slug ):
# """ Display item by username and slug. """

# def set_public_username( self, id, username, **kwargs ):
# """ Set user's public username and delegate to sharing() """
# def sharing( self, id, **kwargs ):
# """ Handle item sharing. """
# TODO: def by_slug( self, user, **kwargs ):


class SharableModelSerializer( base.ModelSerializer,
Expand Down Expand Up @@ -348,14 +337,6 @@ def serialize_username_and_slug( self, item, key, **context ):
return None
return ( '/' ).join(( 'u', item.user.username, self.SINGLE_CHAR_ABBR, item.slug ) )

# def serialize_username_and_slug( self, item, key, **context ):
# """
# """
# #TODO: replace the above with this
# url = self.url_for(controller='history', action="display_by_username_and_slug",
# username=item.user.username, slug=item.slug )
# return url

# the only ones that needs any fns:
# user/user_id
# username_and_slug?
Expand All @@ -375,8 +356,9 @@ def add_deserializers( self ):
ratable.RatableDeserializerMixin.add_deserializers( self )

self.deserializers.update({
'published' : self.deserialize_published,
'importable' : self.deserialize_importable,
'published' : self.deserialize_published,
'importable' : self.deserialize_importable,
'users_shared_with' : self.deserialize_users_shared_with,
})

def deserialize_published( self, item, key, val, **context ):
Expand All @@ -403,15 +385,32 @@ def deserialize_importable( self, item, key, val, **context ):
self.manager.make_importable( item, flush=False )
else:
self.manager.make_non_importable( item, flush=False )
return item.published
return item.importable

# TODO: def deserialize_slug( self, item, val, **context ):

def deserialize_users_shared_with( self, item, key, val, **context ):
"""
Accept a list of encoded user_ids, validate them as users, and then
add or remove user shares in order to update the users_shared_with to
match the given list finally returning the new list of shares.
"""
unencoded_ids = [ self.app.security.decode_id( id_ ) for id_ in val ]
new_users_shared_with = set( self.manager.user_manager.by_ids( unencoded_ids ) )
current_shares = self.manager.get_share_assocs( item )
currently_shared_with = set([ share.user for share in current_shares ])

needs_adding = new_users_shared_with - currently_shared_with
for user in needs_adding:
current_shares.append( self.manager.share_with( item, user, flush=False ) )

# def deserialize_slug( self, item, val, **context ):
# """
# """
# #TODO: call manager.set_slug
# pass
needs_removing = currently_shared_with - new_users_shared_with
for user in needs_removing:
current_shares.remove( self.manager.unshare_with( item, user, flush=False ) )

# def deserialize_user_shares():
self.manager.session().flush()
# TODO: or should this return the list of ids?
return current_shares


class SharableModelFilters( base.ModelFilterParser,
Expand Down
36 changes: 36 additions & 0 deletions test/unit/managers/test_HistoryManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,42 @@ def test_ratings( self ):
deserializer.deserialize( item, { 'community_rating' : 4 }, user=user2 )
self.assertEqual( manager.ratings_count( item ), 1 )

def test_sharable( self ):
manager = self.history_manager
deserializer = self.history_deserializer

user2 = self.user_manager.create( **user2_data )
item = manager.create( name='history1', user=user2 )
non_owner = self.user_manager.create( **user3_data )

self.log( 'should allow adding a share by adding a user id to users_shared_with' )
non_owner_id = self.app.security.encode_id( non_owner.id )
deserializer.deserialize( item, { 'users_shared_with' : [ non_owner_id ] }, user=user2 )
user_shares = manager.get_share_assocs( item )
self.assertEqual( len( user_shares ), 1 )
self.assertEqual( user_shares[0].user_id, non_owner.id )

self.log( 're-adding an existing user id should do nothing' )
deserializer.deserialize( item, { 'users_shared_with' : [ non_owner_id, non_owner_id ] }, user=user2 )
user_shares = manager.get_share_assocs( item )
self.assertEqual( len( user_shares ), 1 )
self.assertEqual( user_shares[0].user_id, non_owner.id )

self.log( 'should allow removing a share by not having it in users_shared_with' )
deserializer.deserialize( item, { 'users_shared_with' : [] }, user=user2 )
user_shares = manager.get_share_assocs( item )
self.assertEqual( len( user_shares ), 0 )

self.log( 'adding a bad user id should error' )
self.assertRaises( AttributeError,
deserializer.deserialize, item, { 'users_shared_with' : [ None ] }, user=user2 )

self.log( 'adding a non-existing user id should do nothing' )
non_user_id = self.app.security.encode_id( 99 )
deserializer.deserialize( item, { 'users_shared_with' : [ non_user_id ] }, user=user2 )
user_shares = manager.get_share_assocs( item )
self.assertEqual( len( user_shares ), 0 )


# =============================================================================
class HistoryFiltersTestCase( BaseTestCase ):
Expand Down

0 comments on commit 7ffa8aa

Please sign in to comment.