diff --git a/controller/Users.py b/controller/Users.py index 53d43a1..0b8623b 100644 --- a/controller/Users.py +++ b/controller/Users.py @@ -1351,10 +1351,14 @@ class Users( object ): if params.get( u"recurring" ) != u"1": raise Payment_error( u"invalid recurring", params ) user.rate_plan = plan_index - self.__database.save( user ) + self.__database.save( user, commit = False ) + self.__update_groups( user ) + self.__database.commit() elif txn_type == u"subscr_cancel": user.rate_plan = 0 # return the user to the free account level - self.__database.save( user ) + self.__database.save( user, commit = False ) + self.__update_groups( user ) + self.__database.commit() elif txn_type in ( u"subscr_payment", u"subscr_failed" ): pass # for now, ignore payments and let paypal handle them else: @@ -1362,6 +1366,51 @@ class Users( object ): return dict() + def __update_groups( self, user ): + """ + Update a user's group membership as a result of a rate plan change. This method does not commit + the current database transaction. + """ + rate_plan = self.__rate_plans[ user.rate_plan ] + + # if the user has a rate plan with admin capabilities + if rate_plan.get( u"user_admin" ) is True: + has_an_admin_group = False + groups = self.__database.select_many( Group, user.sql_load_groups() ) + + # determine whether the user is the admin of at least one group + for group in groups: + if group.admin is False: continue + has_an_admin_group = True + + # set all users in this group to the same rate plan as the admin + group_users = self.__database.select_many( User, group.sql_load_users() ) + for group_user in group_users: + group_user.rate_plan = plan_index + self.__database.save( group_user ) + + # if the user is not an admin of any group, create one for them and make them the admin + if has_an_admin_group is False: + group_id = self.__database.next_id( Group, commit = False ) + group = Group.create( group_id, name = u"my group", admin = True ) + self.__database.save( group, commit = False ) + self.__database.execute( user.sql_save_group( group_id, admin = True ), commit = False ) + + return + + # otherwise, downgrade the user's group admin access to normal group membership + groups = self.__database.select_many( Group, user.sql_load_groups() ) + + for group in groups: + if group.admin is False: continue + self.__database.execute( user.sql_update_group_admin( group.object_id, admin = False ), commit = False ) + + # also return all users in this group to the free account level + group_users = self.__database.select_many( User, group.sql_load_users() ) + for group_user in group_users: + group_user.rate_plan = 0 + self.__database.save( group_user ) + @expose( view = Main_page ) @end_transaction @grab_user_id diff --git a/controller/test/Test_controller.py b/controller/test/Test_controller.py index b25a510..7a71adf 100644 --- a/controller/test/Test_controller.py +++ b/controller/test/Test_controller.py @@ -243,6 +243,18 @@ class Test_controller( object ): User.sql_in_group = lambda self, group_id, admin = False: \ lambda database: sql_in_group( self, group_id, admin, database ) + def sql_update_group_admin( self, group_id, admin, database ): + for ( user_id, group_infos ) in database.user_group.items(): + for group_info in group_infos: + ( db_group_id, db_admin ) = group_info + + if self.object_id == user_id and group_id == db_group_id: + group_infos.remove( group_info ) + group_infos.append( ( db_group_id, admin ) ) + + User.sql_update_group_admin = lambda self, group_id, admin = False: \ + lambda database: sql_update_group_admin( self, group_id, admin, database ) + def sql_revoke_invite_access( notebook_id, trash_id, email_address, database ): invites = [] diff --git a/controller/test/Test_users.py b/controller/test/Test_users.py index d7afaa4..f15714d 100644 --- a/controller/test/Test_users.py +++ b/controller/test/Test_users.py @@ -3050,6 +3050,48 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + + def __assert_has_admin_group( self ): + user_group_infos = self.database.user_group.get( self.user.object_id ) + found_admin = False + group_id = None + + # look through the user's groups and try to find at least one admin group + for user_group_info in user_group_infos: + assert user_group_info + assert len( user_group_info ) == 2 + ( group_id, admin ) = user_group_info + assert group_id + if admin is True: + found_admin = True + break + + assert found_admin is True + + # load the group itself and make sure it looks kosher + group = self.database.load( Group, group_id ) + assert group + assert group.name == u"my group" + assert group.admin is True + + def __assert_no_admin_group( self ): + user_group_infos = self.database.user_group.get( self.user.object_id ) + found_admin = False + group_id = None + + # look through the user's groups and make sure there are no admin groups + for user_group_info in user_group_infos: + assert user_group_info + assert len( user_group_info ) == 2 + ( group_id, admin ) = user_group_info + assert group_id + if admin is True: + found_admin = True + break + + assert found_admin is False + def test_paypal_notify_signup_yearly( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = self.user.object_id @@ -3069,6 +3111,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_signup_invalid( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = self.user.object_id @@ -3082,6 +3126,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_incorrect_receiver_email( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = self.user.object_id @@ -3092,6 +3138,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_incorrect_currency( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = self.user.object_id @@ -3102,6 +3150,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_invalid_item_number( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = self.user.object_id @@ -3112,6 +3162,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_incorrect_gross( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = self.user.object_id @@ -3122,6 +3174,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_incorrect_amount( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = self.user.object_id @@ -3132,6 +3186,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_incorrect_item_name( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = self.user.object_id @@ -3142,6 +3198,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_invalid_period1( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = self.user.object_id @@ -3152,6 +3210,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_invalid_period1( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = self.user.object_id @@ -3162,6 +3222,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_invalid_period3( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = self.user.object_id @@ -3172,6 +3234,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_yearly_period3_with_monthly_amount( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = self.user.object_id @@ -3182,6 +3246,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_yearly_amount_with_monthly_period3( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = self.user.object_id @@ -3192,6 +3258,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_missing_custom( self ): data = dict( self.SUBSCRIPTION_DATA ) result = self.http_post( "/users/paypal_notify", data ); @@ -3200,6 +3268,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_invalid_custom( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = u"(&^(*&" @@ -3209,6 +3279,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_unknown_custom( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"custom" ] = u"1337" @@ -3218,6 +3290,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_missing_recurring( self ): data = dict( self.SUBSCRIPTION_DATA ) del( data[ u"recurring" ] ) @@ -3227,6 +3301,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_signup_invalid_recurring( self ): data = dict( self.SUBSCRIPTION_DATA ) data[ u"recurring" ] = u"0" @@ -3236,6 +3312,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_modify( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3256,6 +3334,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_modify_yearly( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3279,6 +3359,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_modify_invalid( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3296,6 +3378,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_modify_incorrect_receiver_email( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3310,6 +3394,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_modify_incorrect_currency( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3324,6 +3410,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_modify_invalid_item_number( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3338,6 +3426,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_modify_incorrect_gross( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3352,6 +3442,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_modify_incorrect_amount( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3366,6 +3458,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_modify_incorrect_item_name( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3380,6 +3474,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_modify_invalid_period1( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3394,6 +3490,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_modify_invalid_period1( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3408,6 +3506,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_modify_invalid_period3( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3422,6 +3522,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_modify_missing_custom( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3434,6 +3536,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_modify_invalid_custom( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3447,6 +3551,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_modify_unknown_custom( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3460,6 +3566,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_modify_missing_recurring( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3473,6 +3581,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_modify_invalid_recurring( self ): self.user.rate_plan = 2 user = self.database.save( self.user ) @@ -3486,9 +3596,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 2 + self.__assert_no_admin_group() + def test_paypal_notify_cancel( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3506,9 +3619,19 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + + def __create_admin_group( self ): + group_id = self.database.next_id( Group, commit = False ) + group = Group.create( group_id, name = u"my group", admin = True ) + self.database.save( group, commit = False ) + self.database.user_group[ self.user.object_id ].append( ( group_id, True ) ) + self.database.commit() + def test_paypal_notify_cancel_yearly( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3529,9 +3652,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 0 + self.__assert_no_admin_group() + def test_paypal_notify_cancel_invalid( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3546,9 +3672,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_cancel_incorrect_receiver_email( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3560,9 +3689,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_cancel_incorrect_currency( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3574,9 +3706,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_cancel_invalid_item_number( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3588,9 +3723,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_cancel_incorrect_gross( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3602,9 +3740,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_cancel_incorrect_amount( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3616,9 +3757,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_cancel_incorrect_item_name( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3630,9 +3774,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_cancel_invalid_period1( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3644,9 +3791,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_cancel_invalid_period1( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3658,9 +3808,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_cancel_invalid_period3( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3672,9 +3825,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_cancel_missing_custom( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3684,9 +3840,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_cancel_invalid_custom( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3697,9 +3856,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_cancel_unknown_custom( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3710,9 +3872,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_cancel_missing_recurring( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3723,9 +3888,12 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + def test_paypal_notify_cancel_invalid_recurring( self ): self.user.rate_plan = 1 user = self.database.save( self.user ) + self.__create_admin_group() data = dict( self.SUBSCRIPTION_DATA ) data[ u"txn_type" ] = u"subscr_cancel" @@ -3736,6 +3904,8 @@ class Test_users( Test_controller ): user = self.database.load( User, self.user.object_id ) assert user.rate_plan == 1 + self.__assert_has_admin_group() + REFUND_DATA = { u"last_name": u"User", u"txn_id": u"txn",