Skip to content
Snippets Groups Projects
test_invite.py 35.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • import unittest
    import datetime
    import time
    
    
    from flask import url_for, session, current_app
    
    
    # These imports are required, because otherwise we get circular imports?!
    from uffd import user
    from uffd.ldap import ldap
    
    from uffd import create_app, db
    from uffd.invite.models import Invite, InviteGrant, InviteSignup
    from uffd.user.models import User, Group
    from uffd.role.models import Role
    
    from uffd.session.views import login_get_user
    
    
    from utils import dump, UffdTestCase, db_flush
    
    class TestInviteModel(UffdTestCase):
    	def test_expire(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60))
    		self.assertFalse(invite.expired)
    		self.assertTrue(invite.active)
    		invite.valid_until = datetime.datetime.now() - datetime.timedelta(seconds=60)
    		self.assertTrue(invite.expired)
    		self.assertFalse(invite.active)
    
    	def test_void(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), single_use=False)
    		self.assertFalse(invite.voided)
    		self.assertTrue(invite.active)
    		invite.used = True
    		self.assertFalse(invite.voided)
    		self.assertTrue(invite.active)
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), single_use=True)
    		self.assertFalse(invite.voided)
    		self.assertTrue(invite.active)
    		invite.used = True
    		self.assertTrue(invite.voided)
    		self.assertFalse(invite.active)
    
    
    	def test_permitted(self):
    		role = Role(name='testrole')
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True, roles=[role])
    		self.assertTrue(invite.permitted)
    		self.assertTrue(invite.active)
    		invite.creator_dn = 'uid=doesnotexist,ou=users,dc=example,dc=com'
    		self.assertFalse(invite.permitted)
    		self.assertFalse(invite.active)
    		invite.creator_dn = 'uid=testadmin,ou=users,dc=example,dc=com'
    		self.assertTrue(invite.permitted)
    		self.assertTrue(invite.active)
    		invite.creator_dn = 'uid=testuser,ou=users,dc=example,dc=com'
    		self.assertFalse(invite.permitted)
    		self.assertFalse(invite.active)
    		role.moderator_group_dn = 'cn=uffd_access,ou=groups,dc=example,dc=com'
    		current_app.config['ACL_SIGNUP_GROUP'] = 'uffd_access'
    		self.assertTrue(invite.permitted)
    		self.assertTrue(invite.active)
    		role.moderator_group_dn = None
    		self.assertFalse(invite.permitted)
    		self.assertFalse(invite.active)
    		role.moderator_group_dn = 'cn=uffd_access,ou=groups,dc=example,dc=com'
    		current_app.config['ACL_SIGNUP_GROUP'] = 'uffd_admin'
    		self.assertFalse(invite.permitted)
    		self.assertFalse(invite.active)
    
    
    	def test_disable(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60))
    		self.assertTrue(invite.active)
    		invite.disable()
    		self.assertFalse(invite.active)
    
    	def test_reset_disabled(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60))
    		invite.disable()
    		self.assertFalse(invite.active)
    		invite.reset()
    		self.assertTrue(invite.active)
    
    	def test_reset_expired(self):
    		invite = Invite(valid_until=datetime.datetime.now() - datetime.timedelta(seconds=60))
    		self.assertFalse(invite.active)
    		invite.reset()
    		self.assertFalse(invite.active)
    
    
    	def test_reset_single_use(self):
    
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), single_use=False)
    		invite.used = True
    		invite.disable()
    		self.assertFalse(invite.active)
    		invite.reset()
    		self.assertTrue(invite.active)
    
    
    	def test_short_token(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60))
    		db.session.add(invite)
    		db.session.commit()
    		self.assertTrue(len(invite.short_token) <= len(invite.token)/3)
    
    
    class TestInviteGrantModel(UffdTestCase):
    	def test_success(self):
    		user = User.query.get('uid=testuser,ou=users,dc=example,dc=com')
    		group0 = Group.query.get('cn=uffd_access,ou=groups,dc=example,dc=com')
    		role0 = Role(name='baserole', groups=[group0])
    		db.session.add(role0)
    		user.roles.add(role0)
    		user.update_groups()
    		group1 = Group.query.get('cn=uffd_admin,ou=groups,dc=example,dc=com')
    		role1 = Role(name='testrole1', groups=[group1])
    		db.session.add(role1)
    		role2 = Role(name='testrole2')
    		db.session.add(role2)
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), roles=[role1, role2])
    		self.assertIn(role0, user.roles)
    		self.assertNotIn(role1, user.roles)
    		self.assertNotIn(role2, user.roles)
    		self.assertIn(group0, user.groups)
    		self.assertNotIn(group1, user.groups)
    		self.assertFalse(invite.used)
    		grant = InviteGrant(invite=invite, user=user)
    		success, msg = grant.apply()
    		self.assertTrue(success)
    		self.assertIn(role0, user.roles)
    		self.assertIn(role1, user.roles)
    		self.assertIn(role2, user.roles)
    		self.assertIn(group0, user.groups)
    		self.assertIn(group1, user.groups)
    		self.assertTrue(invite.used)
    		db.session.commit()
    		ldap.session.commit()
    		db_flush()
    		user = User.query.get('uid=testuser,ou=users,dc=example,dc=com')
    		self.assertIn('baserole', [role.name for role in user.roles])
    		self.assertIn('testrole1', [role.name for role in user.roles])
    		self.assertIn('testrole2', [role.name for role in user.roles])
    		self.assertIn('cn=uffd_access,ou=groups,dc=example,dc=com', [group.dn for group in user.groups])
    		self.assertIn('cn=uffd_admin,ou=groups,dc=example,dc=com', [group.dn for group in user.groups])
    
    	def test_inactive(self):
    		user = User.query.get('uid=testuser,ou=users,dc=example,dc=com')
    		group = Group.query.get('cn=uffd_admin,ou=groups,dc=example,dc=com')
    		role = Role(name='testrole1', groups=[group])
    		db.session.add(role)
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), roles=[role], single_use=True, used=True)
    		self.assertFalse(invite.active)
    		grant = InviteGrant(invite=invite, user=user)
    		success, msg = grant.apply()
    		self.assertFalse(success)
    		self.assertIsInstance(msg, str)
    		self.assertNotIn(role, user.roles)
    		self.assertNotIn(group, user.groups)
    
    	def test_no_roles(self):
    		user = User.query.get('uid=testuser,ou=users,dc=example,dc=com')
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60))
    		self.assertTrue(invite.active)
    		grant = InviteGrant(invite=invite, user=user)
    		success, msg = grant.apply()
    		self.assertFalse(success)
    		self.assertIsInstance(msg, str)
    
    	def test_no_new_roles(self):
    		user = User.query.get('uid=testuser,ou=users,dc=example,dc=com')
    		role = Role(name='testrole1')
    		db.session.add(role)
    		user.roles.add(role)
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), roles=[role])
    		self.assertTrue(invite.active)
    		grant = InviteGrant(invite=invite, user=user)
    		success, msg = grant.apply()
    		self.assertFalse(success)
    		self.assertIsInstance(msg, str)
    
    class TestInviteSignupModel(UffdTestCase):
    	def create_base_roles(self):
    		self.app.config['ROLES_BASEROLES'] = ['base']
    		baserole = Role(name='base')
    		baserole.groups.add(Group.query.get('cn=uffd_access,ou=groups,dc=example,dc=com'))
    		baserole.groups.add(Group.query.get('cn=users,ou=groups,dc=example,dc=com'))
    		db.session.add(baserole)
    		db.session.commit()
    
    	def test_success(self):
    		self.create_base_roles()
    		base_role = Role.query.filter_by(name='base').one()
    		base_group1 = Group.query.get('cn=uffd_access,ou=groups,dc=example,dc=com')
    		base_group2 = Group.query.get('cn=users,ou=groups,dc=example,dc=com')
    		group = Group.query.get('cn=uffd_admin,ou=groups,dc=example,dc=com')
    		role1 = Role(name='testrole1', groups=[group])
    		db.session.add(role1)
    		role2 = Role(name='testrole2')
    		db.session.add(role2)
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), roles=[role1, role2], allow_signup=True)
    		signup = InviteSignup(invite=invite, loginname='newuser', displayname='New User', mail='test@example.com', password='notsecret')
    		self.assertFalse(invite.used)
    		valid, msg = signup.validate()
    		self.assertTrue(valid)
    		self.assertFalse(invite.used)
    		user, msg = signup.finish('notsecret')
    		self.assertIsInstance(user, User)
    		self.assertTrue(invite.used)
    		self.assertEqual(user.loginname, 'newuser')
    		self.assertEqual(user.displayname, 'New User')
    		self.assertEqual(user.mail, 'test@example.com')
    		self.assertEqual(signup.user.dn, user.dn)
    		self.assertIn(base_role, user.roles)
    		self.assertIn(role1, user.roles)
    		self.assertIn(role2, user.roles)
    		self.assertIn(base_group1, user.groups)
    		self.assertIn(base_group2, user.groups)
    		self.assertIn(group, user.groups)
    		db.session.commit()
    		ldap.session.commit()
    		db_flush()
    		self.assertEqual(len(User.query.filter_by(loginname='newuser').all()), 1)
    
    	def test_success_no_roles(self):
    		self.create_base_roles()
    		base_role = Role.query.filter_by(name='base').one()
    		base_group1 = Group.query.get('cn=uffd_access,ou=groups,dc=example,dc=com')
    		base_group2 = Group.query.get('cn=users,ou=groups,dc=example,dc=com')
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True)
    		signup = InviteSignup(invite=invite, loginname='newuser', displayname='New User', mail='test@example.com', password='notsecret')
    		self.assertFalse(invite.used)
    		valid, msg = signup.validate()
    		self.assertTrue(valid)
    		self.assertFalse(invite.used)
    		user, msg = signup.finish('notsecret')
    		self.assertIsInstance(user, User)
    		self.assertTrue(invite.used)
    		self.assertEqual(user.loginname, 'newuser')
    		self.assertEqual(user.displayname, 'New User')
    		self.assertEqual(user.mail, 'test@example.com')
    		self.assertEqual(signup.user.dn, user.dn)
    		self.assertIn(base_role, user.roles)
    		self.assertEqual(len(user.roles), 1)
    		self.assertIn(base_group1, user.groups)
    		self.assertIn(base_group2, user.groups)
    		self.assertEqual(len(user.groups), 2)
    		db.session.commit()
    		ldap.session.commit()
    		db_flush()
    		self.assertEqual(len(User.query.filter_by(loginname='newuser').all()), 1)
    
    	def test_inactive(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True, single_use=True, used=True)
    		self.assertFalse(invite.active)
    		signup = InviteSignup(invite=invite, loginname='newuser', displayname='New User', mail='test@example.com', password='notsecret')
    		valid, msg = signup.validate()
    		self.assertFalse(valid)
    		self.assertIsInstance(msg, str)
    		user, msg = signup.finish('notsecret')
    		self.assertIsNone(user)
    		self.assertIsInstance(msg, str)
    
    	def test_invalid(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True)
    		self.assertTrue(invite.active)
    		signup = InviteSignup(invite=invite, loginname='', displayname='New User', mail='test@example.com', password='notsecret')
    		valid, msg = signup.validate()
    		self.assertFalse(valid)
    		self.assertIsInstance(msg, str)
    
    	def test_invalid2(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True)
    		self.assertTrue(invite.active)
    		signup = InviteSignup(invite=invite, loginname='newuser', displayname='New User', mail='test@example.com', password='notsecret')
    		user, msg = signup.finish('wrongpassword')
    		self.assertIsNone(user)
    		self.assertIsInstance(msg, str)
    
    	def test_no_signup(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=False)
    		self.assertTrue(invite.active)
    		signup = InviteSignup(invite=invite, loginname='newuser', displayname='New User', mail='test@example.com', password='notsecret')
    		valid, msg = signup.validate()
    		self.assertFalse(valid)
    		self.assertIsInstance(msg, str)
    		user, msg = signup.finish('notsecret')
    		self.assertIsNone(user)
    		self.assertIsInstance(msg, str)
    
    
    class TestInviteAdminViews(UffdTestCase):
    
    	def setUpApp(self):
    		self.app.config['SELF_SIGNUP'] = False
    		self.app.last_mail = None
    
    	def login_admin(self):
    		self.client.post(path=url_for('session.login'),
    			data={'loginname': 'testadmin', 'password': 'adminpassword'}, follow_redirects=True)
    
    	def login_user(self):
    		self.client.post(path=url_for('session.login'),
    			data={'loginname': 'testuser', 'password': 'userpassword'}, follow_redirects=True)
    
    	def test_index(self):
    		valid_until = datetime.datetime.now() + datetime.timedelta(seconds=60)
    		valid_until_expired = datetime.datetime.now() - datetime.timedelta(seconds=60)
    		user1 = User.query.get('uid=testuser,ou=users,dc=example,dc=com')
    		user2 = User.query.get('uid=testadmin,ou=users,dc=example,dc=com')
    		role1 = Role(name='testrole1')
    		db.session.add(role1)
    		role2 = Role(name='testrole2')
    		db.session.add(role2)
    		# All possible states
    		db.session.add(Invite(valid_until=valid_until, single_use=False))
    		db.session.add(Invite(valid_until=valid_until, single_use=True, used=False))
    		db.session.add(Invite(valid_until=valid_until, single_use=True, used=True, signups=[InviteSignup(user=user1)]))
    		db.session.add(Invite(valid_until=valid_until_expired))
    		db.session.add(Invite(valid_until=valid_until, disabled=True))
    		# Different permissions
    		db.session.add(Invite(valid_until=valid_until, allow_signup=True))
    		db.session.add(Invite(valid_until=valid_until, allow_signup=False))
    		db.session.add(Invite(valid_until=valid_until, allow_signup=True, roles=[role1], grants=[InviteGrant(user=user2)]))
    		db.session.add(Invite(valid_until=valid_until, allow_signup=False, roles=[role1, role2]))
    		db.session.commit()
    		self.login_admin()
    		r = self.client.get(path=url_for('invite.index'), follow_redirects=True)
    		dump('invite_index', r)
    		self.assertEqual(r.status_code, 200)
    
    	def test_index_empty(self):
    		self.login_admin()
    		r = self.client.get(path=url_for('invite.index'), follow_redirects=True)
    		dump('invite_index_empty', r)
    		self.assertEqual(r.status_code, 200)
    
    	def test_index_nologin(self):
    		r = self.client.get(path=url_for('invite.index'), follow_redirects=True)
    		dump('invite_index_nologin', r)
    		self.assertEqual(r.status_code, 200)
    
    	def test_index_noaccess(self):
    		self.login_user()
    		r = self.client.get(path=url_for('invite.index'), follow_redirects=True)
    		dump('invite_index_noaccess', r)
    		self.assertEqual(r.status_code, 200)
    
    		self.assertIn('Access denied'.encode(), r.data)
    
    	def test_index_signupperm(self):
    		current_app.config['ACL_SIGNUP_GROUP'] = 'uffd_access'
    		valid_until = datetime.datetime.now() + datetime.timedelta(seconds=60)
    		invite1 = Invite(valid_until=valid_until, allow_signup=True, creator_dn='uid=testadmin,ou=users,dc=example,dc=com')
    		db.session.add(invite1)
    		invite2 = Invite(valid_until=valid_until, allow_signup=True, creator_dn='uid=testuser,ou=users,dc=example,dc=com')
    		db.session.add(invite2)
    		invite3 = Invite(valid_until=valid_until, allow_signup=True)
    		db.session.add(invite3)
    		db.session.commit()
    		token1 = invite1.short_token
    		token2 = invite2.short_token
    		token3 = invite3.short_token
    		self.login_user()
    		r = self.client.get(path=url_for('invite.index'), follow_redirects=True)
    		self.assertEqual(r.status_code, 200)
    		self.assertNotIn('Access denied'.encode(), r.data)
    		self.assertNotIn(token1.encode(), r.data)
    		self.assertIn(token2.encode(), r.data)
    		self.assertNotIn(token3.encode(), r.data)
    
    	def test_index_rolemod(self):
    		role1 = Role(name='testrole1')
    		db.session.add(role1)
    		role2 = Role(name='testrole2', moderator_group_dn='cn=uffd_access,ou=groups,dc=example,dc=com')
    		db.session.add(role2)
    		valid_until = datetime.datetime.now() + datetime.timedelta(seconds=60)
    		db.session.add(Invite(valid_until=valid_until, roles=[role1]))
    		db.session.add(Invite(valid_until=valid_until, roles=[role2]))
    		db.session.commit()
    		self.login_user()
    		r = self.client.get(path=url_for('invite.index'), follow_redirects=True)
    		self.assertEqual(r.status_code, 200)
    		self.assertNotIn('Access denied'.encode(), r.data)
    		self.assertNotIn('testrole1'.encode(), r.data)
    		self.assertIn('testrole2'.encode(), r.data)
    
    
    	def test_new(self):
    		self.login_admin()
    		role = Role(name='testrole1')
    		db.session.add(role)
    		db.session.commit()
    		role_id = role.id
    		r = self.client.get(path=url_for('invite.new'), follow_redirects=True)
    		dump('invite_new', r)
    		self.assertEqual(r.status_code, 200)
    		valid_until = (datetime.datetime.now() + datetime.timedelta(seconds=60)).isoformat()
    		self.assertListEqual(Invite.query.all(), [])
    		r = self.client.post(path=url_for('invite.new_submit'),
    			data={'single-use': '1', 'valid-until': valid_until,
    			      'allow-signup': '1', 'role-%d'%role_id: '1'}, follow_redirects=True)
    		dump('invite_new_submit', r)
    		invite = Invite.query.one()
    		role = Role.query.get(role_id)
    		self.assertTrue(invite.active)
    		self.assertTrue(invite.single_use)
    		self.assertTrue(invite.allow_signup)
    		self.assertListEqual(invite.roles, [role])
    
    
    	def test_new_noperm(self):
    		current_app.config['ACL_SIGNUP_GROUP'] = 'uffd_access'
    		self.login_user()
    		role = Role(name='testrole1')
    		db.session.add(role)
    		db.session.commit()
    		role_id = role.id
    		valid_until = (datetime.datetime.now() + datetime.timedelta(seconds=60)).isoformat()
    		r = self.client.post(path=url_for('invite.new_submit'),
    			data={'single-use': '1', 'valid-until': valid_until,
    			      'allow-signup': '1', 'role-%d'%role_id: '1'}, follow_redirects=True)
    		dump('invite_new_noperm', r)
    		self.assertIsNone(Invite.query.first())
    
    	def test_new_empty(self):
    		current_app.config['ACL_SIGNUP_GROUP'] = 'uffd_access'
    		self.login_user()
    		valid_until = (datetime.datetime.now() + datetime.timedelta(seconds=60)).isoformat()
    		r = self.client.post(path=url_for('invite.new_submit'),
    			data={'single-use': '1', 'valid-until': valid_until,
    			      'allow-signup': '0'}, follow_redirects=True)
    		dump('invite_new_empty', r)
    		self.assertIsNone(Invite.query.first())
    
    
    	def test_disable(self):
    		self.login_admin()
    		valid_until = datetime.datetime.now() + datetime.timedelta(seconds=60)
    		invite = Invite(valid_until=valid_until)
    		db.session.add(invite)
    		db.session.commit()
    
    		id = invite.id
    		self.assertTrue(Invite.query.get(id).active)
    		r = self.client.post(path=url_for('invite.disable', invite_id=id), follow_redirects=True)
    
    		dump('invite_disable', r)
    
    		self.assertTrue(Invite.query.get(id).disabled)
    
    	def test_disable_own(self):
    		current_app.config['ACL_SIGNUP_GROUP'] = 'uffd_access'
    		self.login_user()
    		valid_until = datetime.datetime.now() + datetime.timedelta(seconds=60)
    		invite = Invite(valid_until=valid_until, creator_dn='uid=testuser,ou=users,dc=example,dc=com')
    		db.session.add(invite)
    		db.session.commit()
    		id = invite.id
    		self.assertTrue(Invite.query.get(id).active)
    		r = self.client.post(path=url_for('invite.disable', invite_id=id), follow_redirects=True)
    		dump('invite_disable', r)
    		self.assertTrue(Invite.query.get(id).disabled)
    
    	def test_disable_rolemod(self):
    		self.login_user()
    		valid_until = datetime.datetime.now() + datetime.timedelta(seconds=60)
    		role = Role(name='testrole', moderator_group_dn='cn=uffd_access,ou=groups,dc=example,dc=com')
    		db.session.add(role)
    		invite = Invite(valid_until=valid_until, creator_dn='uid=testadmin,ou=users,dc=example,dc=com', roles=[role])
    		db.session.add(invite)
    		db.session.commit()
    		id = invite.id
    		self.assertTrue(Invite.query.get(id).active)
    		r = self.client.post(path=url_for('invite.disable', invite_id=id), follow_redirects=True)
    		self.assertTrue(Invite.query.get(id).disabled)
    
    	def test_disable_noperm(self):
    		self.login_user()
    		valid_until = datetime.datetime.now() + datetime.timedelta(seconds=60)
    		db.session.add(Role(name='testrole1', moderator_group_dn='cn=uffd_access,ou=groups,dc=example,dc=com'))
    		role = Role(name='testrole2', moderator_group_dn='cn=uffd_admin,ou=groups,dc=example,dc=com')
    		db.session.add(role)
    		invite = Invite(valid_until=valid_until, creator_dn='uid=testadmin,ou=users,dc=example,dc=com', roles=[role])
    		db.session.add(invite)
    		db.session.commit()
    		id = invite.id
    		r = self.client.post(path=url_for('invite.disable', invite_id=id), follow_redirects=True)
    		self.assertFalse(Invite.query.get(id).disabled)
    		self.assertTrue(Invite.query.get(id).active)
    
    
    	def test_reset_disabled(self):
    		self.login_admin()
    		valid_until = datetime.datetime.now() + datetime.timedelta(seconds=60)
    		invite = Invite(valid_until=valid_until, disabled=True)
    		db.session.add(invite)
    		db.session.commit()
    
    		id = invite.id
    		self.assertFalse(Invite.query.get(id).active)
    		r = self.client.post(path=url_for('invite.reset', invite_id=id), follow_redirects=True)
    
    		dump('invite_reset_disabled', r)
    
    		self.assertTrue(Invite.query.get(id).active)
    
    
    	def test_reset_voided(self):
    		self.login_admin()
    		valid_until = datetime.datetime.now() + datetime.timedelta(seconds=60)
    		invite = Invite(valid_until=valid_until, single_use=True, used=True)
    		db.session.add(invite)
    		db.session.commit()
    
    		id = invite.id
    		self.assertFalse(Invite.query.get(id).active)
    		r = self.client.post(path=url_for('invite.reset', invite_id=id), follow_redirects=True)
    
    		dump('invite_reset_voided', r)
    
    		self.assertTrue(Invite.query.get(id).active)
    
    	def test_reset_own(self):
    		current_app.config['ACL_SIGNUP_GROUP'] = 'uffd_access'
    		self.login_user()
    		valid_until = datetime.datetime.now() + datetime.timedelta(seconds=60)
    		invite = Invite(valid_until=valid_until, disabled=True, creator_dn='uid=testuser,ou=users,dc=example,dc=com')
    		db.session.add(invite)
    		db.session.commit()
    		id = invite.id
    		self.assertFalse(Invite.query.get(id).active)
    		r = self.client.post(path=url_for('invite.reset', invite_id=id), follow_redirects=True)
    		dump('invite_reset_own', r)
    		self.assertTrue(Invite.query.get(id).active)
    
    	def test_reset_foreign(self):
    		self.login_user()
    		valid_until = datetime.datetime.now() + datetime.timedelta(seconds=60)
    		role = Role(name='testrole', moderator_group_dn='cn=uffd_access,ou=groups,dc=example,dc=com')
    		db.session.add(role)
    		invite = Invite(valid_until=valid_until, disabled=True, creator_dn='uid=testadmin,ou=users,dc=example,dc=com', roles=[role])
    		db.session.add(invite)
    		db.session.commit()
    		id = invite.id
    		self.assertFalse(Invite.query.get(id).active)
    		r = self.client.post(path=url_for('invite.reset', invite_id=id), follow_redirects=True)
    		self.assertFalse(Invite.query.get(id).active)
    
    class TestInviteUseViews(UffdTestCase):
    	def setUpApp(self):
    		self.app.config['SELF_SIGNUP'] = False
    		self.app.last_mail = None
    
    	def login_user(self):
    		self.client.post(path=url_for('session.login'),
    			data={'loginname': 'testuser', 'password': 'userpassword'}, follow_redirects=True)
    
    
    	def test_use(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True, roles=[Role(name='testrole1'), Role(name='testrole2')])
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		r = self.client.get(path=url_for('invite.use', token=token), follow_redirects=True)
    		dump('invite_use', r)
    		self.assertEqual(r.status_code, 200)
    
    	def test_use_loggedin(self):
    		self.login_user()
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True, roles=[Role(name='testrole1'), Role(name='testrole2')])
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		r = self.client.get(path=url_for('invite.use', token=token), follow_redirects=True)
    		dump('invite_use_loggedin', r)
    		self.assertEqual(r.status_code, 200)
    
    	def test_use_inactive(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), disabled=True)
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		r = self.client.get(path=url_for('invite.use', token=token), follow_redirects=True)
    		dump('invite_use_inactive', r)
    		self.assertEqual(r.status_code, 200)
    
    	# TODO: test cases for {logged in, not logged in} x (signup-only, grant-only, both, none?}
    
    	def test_grant(self):
    		user = User.query.get('uid=testuser,ou=users,dc=example,dc=com')
    		group0 = Group.query.get('cn=uffd_access,ou=groups,dc=example,dc=com')
    		role0 = Role(name='baserole', groups=[group0])
    		db.session.add(role0)
    		user.roles.add(role0)
    		user.update_groups()
    		group1 = Group.query.get('cn=uffd_admin,ou=groups,dc=example,dc=com')
    		role1 = Role(name='testrole1', groups=[group1])
    		db.session.add(role1)
    		role2 = Role(name='testrole2')
    		db.session.add(role2)
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), roles=[role1, role2])
    		db.session.add(invite)
    		db.session.commit()
    		ldap.session.commit()
    		token = invite.token
    		self.assertIn(role0, user.roles)
    		self.assertNotIn(role1, user.roles)
    		self.assertNotIn(role2, user.roles)
    		self.assertIn(group0, user.groups)
    		self.assertNotIn(group1, user.groups)
    		self.assertFalse(invite.used)
    		self.login_user()
    		r = self.client.post(path=url_for('invite.grant', token=token), follow_redirects=True)
    		dump('invite_grant', r)
    		self.assertEqual(r.status_code, 200)
    		db_flush()
    
    		invite = Invite.query.filter_by(token=token).first()
    
    		user = User.query.get('uid=testuser,ou=users,dc=example,dc=com')
    		self.assertTrue(invite.used)
    		self.assertIn('baserole', [role.name for role in user.roles])
    		self.assertIn('testrole1', [role.name for role in user.roles])
    		self.assertIn('testrole2', [role.name for role in user.roles])
    		self.assertIn('cn=uffd_access,ou=groups,dc=example,dc=com', [group.dn for group in user.groups])
    		self.assertIn('cn=uffd_admin,ou=groups,dc=example,dc=com', [group.dn for group in user.groups])
    
    	def test_grant_invalid_invite(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), disabled=True)
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		self.login_user()
    		r = self.client.post(path=url_for('invite.grant', token=token), follow_redirects=True)
    		dump('invite_grant_invalid_invite', r)
    		self.assertEqual(r.status_code, 200)
    
    		self.assertFalse(Invite.query.filter_by(token=token).first().used)
    
    
    	def test_grant_no_roles(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60))
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		self.login_user()
    		r = self.client.post(path=url_for('invite.grant', token=token), follow_redirects=True)
    		dump('invite_grant_no_roles', r)
    		self.assertEqual(r.status_code, 200)
    
    		self.assertFalse(Invite.query.filter_by(token=token).first().used)
    
    
    	def test_grant_no_new_roles(self):
    		user = User.query.get('uid=testuser,ou=users,dc=example,dc=com')
    		role = Role(name='testrole')
    		db.session.add(role)
    		user.roles.add(role)
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), roles=[role])
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		self.login_user()
    		r = self.client.post(path=url_for('invite.grant', token=token), follow_redirects=True)
    		dump('invite_grant_no_new_roles', r)
    		self.assertEqual(r.status_code, 200)
    
    		self.assertFalse(Invite.query.filter_by(token=token).first().used)
    
    
    	def test_signup(self):
    		self.app.config['ROLES_BASEROLES'] = ['base']
    		baserole = Role(name='base')
    		baserole.groups.add(Group.query.get('cn=uffd_access,ou=groups,dc=example,dc=com'))
    		baserole.groups.add(Group.query.get('cn=users,ou=groups,dc=example,dc=com'))
    		db.session.add(baserole)
    		group = Group.query.get('cn=uffd_admin,ou=groups,dc=example,dc=com')
    		role1 = Role(name='testrole1', groups=[group])
    		db.session.add(role1)
    		role2 = Role(name='testrole2')
    		db.session.add(role2)
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), roles=[role1, role2], allow_signup=True)
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		r = self.client.get(path=url_for('invite.signup_start', token=token), follow_redirects=True)
    		dump('invite_signup_start', r)
    		self.assertEqual(r.status_code, 200)
    		r = self.client.post(path=url_for('invite.signup_submit', token=token),
    			data={'loginname': 'newuser', 'displayname': 'New User', 'mail': 'test@example.com',
                'password1': 'notsecret', 'password2': 'notsecret'}, follow_redirects=True)
    		dump('invite_signup_submit', r)
    		self.assertEqual(r.status_code, 200)
    		signup = InviteSignup.query.one()
    		self.assertEqual(signup.loginname, 'newuser')
    		self.assertEqual(signup.displayname, 'New User')
    		self.assertEqual(signup.mail, 'test@example.com')
    		self.assertIn(signup.token, str(self.app.last_mail.get_content()))
    		self.assertTrue(signup.check_password('notsecret'))
    		self.assertTrue(signup.validate()[0])
    
    	def test_signup_invalid_invite(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True, disabled=True)
    		db.session.add(invite)
    		db.session.commit()
    		r = self.client.get(path=url_for('invite.signup_start', token=invite.token), follow_redirects=True)
    		dump('invite_signup_invalid_invite', r)
    		self.assertEqual(r.status_code, 200)
    
    	def test_signup_nosignup(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=False)
    		db.session.add(invite)
    		db.session.commit()
    		r = self.client.get(path=url_for('invite.signup_start', token=invite.token), follow_redirects=True)
    		dump('invite_signup_nosignup', r)
    		self.assertEqual(r.status_code, 200)
    
    	def test_signup_wrongpassword(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True)
    		db.session.add(invite)
    		db.session.commit()
    		r = self.client.post(path=url_for('invite.signup_submit', token=invite.token),
    			data={'loginname': 'newuser', 'displayname': 'New User', 'mail': 'test@example.com',
    			      'password1': 'notsecret', 'password2': 'notthesame'}, follow_redirects=True)
    		dump('invite_signup_wrongpassword', r)
    		self.assertEqual(r.status_code, 200)
    
    	def test_signup_invalid(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True)
    		db.session.add(invite)
    		db.session.commit()
    		r = self.client.post(path=url_for('invite.signup_submit', token=invite.token),
    			data={'loginname': '', 'displayname': 'New User', 'mail': 'test@example.com',
    			      'password1': 'notsecret', 'password2': 'notsecret'}, follow_redirects=True)
    		dump('invite_signup_invalid', r)
    		self.assertEqual(r.status_code, 200)
    
    	def test_signup_mailerror(self):
    		self.app.config['MAIL_SKIP_SEND'] = 'fail'
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True)
    		db.session.add(invite)
    		db.session.commit()
    		r = self.client.post(path=url_for('invite.signup_submit', token=invite.token),
    			data={'loginname': 'newuser', 'displayname': 'New User', 'mail': 'test@example.com',
    			      'password1': 'notsecret', 'password2': 'notsecret'}, follow_redirects=True)
    		dump('invite_signup_mailerror', r)
    		self.assertEqual(r.status_code, 200)
    
    	def test_signup_hostlimit(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True)
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		for i in range(20):
    			r = self.client.post(path=url_for('invite.signup_submit', token=token),
    				data={'loginname': 'newuser%d'%i, 'displayname': 'New User', 'mail': 'test%d@example.com'%i,
    							'password1': 'notsecret', 'password2': 'notsecret'}, follow_redirects=True)
    			self.assertEqual(r.status_code, 200)
    		self.app.last_mail = None
    		r = self.client.post(path=url_for('invite.signup_submit', token=token),
    			data={'loginname': 'newuser', 'displayname': 'New User', 'mail': 'test@example.com',
    			      'password1': 'notsecret', 'password2': 'notsecret'}, follow_redirects=True)
    		dump('invite_signup_hostlimit', r)
    		self.assertEqual(r.status_code, 200)
    		self.assertEqual(InviteSignup.query.filter_by(loginname='newuser').all(), [])
    		self.assertIsNone(self.app.last_mail)
    
    	def test_signup_mailimit(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True)
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		for i in range(3):
    			r = self.client.post(path=url_for('invite.signup_submit', token=token),
    				data={'loginname': 'newuser%d'%i, 'displayname': 'New User', 'mail': 'test@example.com',
    							'password1': 'notsecret', 'password2': 'notsecret'}, follow_redirects=True)
    			self.assertEqual(r.status_code, 200)
    		self.app.last_mail = None
    		r = self.client.post(path=url_for('invite.signup_submit', token=token),
    			data={'loginname': 'newuser', 'displayname': 'New User', 'mail': 'test@example.com',
    			      'password1': 'notsecret', 'password2': 'notsecret'}, follow_redirects=True)
    		dump('invite_signup_maillimit', r)
    		self.assertEqual(r.status_code, 200)
    		self.assertEqual(InviteSignup.query.filter_by(loginname='newuser').all(), [])
    		self.assertIsNone(self.app.last_mail)
    
    	def test_signup_check(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True)
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		r = self.client.post(path=url_for('invite.signup_check', token=token), follow_redirects=True,
    		                     data={'loginname': 'newuser'})
    		self.assertEqual(r.status_code, 200)
    		self.assertEqual(r.content_type, 'application/json')
    		self.assertEqual(r.json['status'], 'ok')
    
    	def test_signup_check_invalid(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True)
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		r = self.client.post(path=url_for('invite.signup_check', token=token), follow_redirects=True,
    		                     data={'loginname': ''})
    		self.assertEqual(r.status_code, 200)
    		self.assertEqual(r.content_type, 'application/json')
    		self.assertEqual(r.json['status'], 'invalid')
    
    	def test_signup_check_exists(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True)
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		r = self.client.post(path=url_for('invite.signup_check', token=token), follow_redirects=True,
    		                     data={'loginname': 'testuser'})
    		self.assertEqual(r.status_code, 200)
    		self.assertEqual(r.content_type, 'application/json')
    		self.assertEqual(r.json['status'], 'exists')
    
    	def test_signup_check_nosignup(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=False)
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		r = self.client.post(path=url_for('invite.signup_check', token=token), follow_redirects=True,
    		                     data={'loginname': 'testuser'})
    		self.assertEqual(r.status_code, 403)
    		self.assertEqual(r.content_type, 'application/json')
    		self.assertEqual(r.json['status'], 'error')
    
    	def test_signup_check_error(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True, disabled=True)
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		r = self.client.post(path=url_for('invite.signup_check', token=token), follow_redirects=True,
    		                     data={'loginname': 'testuser'})
    		self.assertEqual(r.status_code, 403)
    		self.assertEqual(r.content_type, 'application/json')
    		self.assertEqual(r.json['status'], 'error')
    
    	def test_signup_check_ratelimited(self):
    		invite = Invite(valid_until=datetime.datetime.now() + datetime.timedelta(seconds=60), allow_signup=True)
    		db.session.add(invite)
    		db.session.commit()
    		token = invite.token
    		for i in range(20):
    			r = self.client.post(path=url_for('invite.signup_check', token=token), follow_redirects=True,
    													 data={'loginname': 'testuser'})
    			self.assertEqual(r.status_code, 200)
    			self.assertEqual(r.content_type, 'application/json')
    		r = self.client.post(path=url_for('invite.signup_check', token=token), follow_redirects=True,
    		                     data={'loginname': 'testuser'})
    		self.assertEqual(r.status_code, 200)
    		self.assertEqual(r.content_type, 'application/json')
    		self.assertEqual(r.json['status'], 'ratelimited')
    
    
    class TestInviteUseViewsOL(TestInviteUseViews):