def handle(self, *args, **options): self.stdout.write('Starting fill db') site = Site.objects.get(pk=1) site.domain = site.name = settings.DOMAIN site.save() user = User.objects.create_superuser(email='*****@*****.**', password='') user.set_password('admin') user.save() accounts = AccountFactory.create_batch(2) for account in Account.objects.all(): admin = AdminFactory(accounts=[account]) membership = admin.get_membership(account) BillingSettingsFactory(account=account) board_of_directors = CommitteeFactory(name=_('Board of Directors'), account=account) membership.committees.add(board_of_directors) UserFactory.create_batch(5, accounts=accounts) for account in Account.objects.all(): CommitteeFactory.create_batch(10, account=account) for membership in Membership.objects.filter(user__in=User.objects.select_related().exclude(is_superuser=True)): membership.committees.add(*random.sample(set(Committee.objects.filter(account_id=membership.account_id)), 2)) MeetingFactory.create_batch(10) DocumentFactory.create_batch(5) self.stdout.write('Completed fill db')
def test_publish_and_reminder(self): self.login_admin() # Committee both to have predictable memberships count and also to overcome current permissions issue: to edit meetings # one needs to be either meeting's committee chair or chair of any other committee (if meetings doesn't have any selected) committee = CommitteeFactory(account=self.account, chairman=self.membership_admin) committee.memberships.add(self.membership) committee.memberships.add(self.membership_admin) meeting_json = self._create_simple_meeting(committee=committee.id) # Test reminder can't be send for unpublished meetings self.acc_post_json('api-meetings-meetings-reminder', json_data={}, pk=meeting_json['id'], assert_status_code=403) mail.outbox = [] self.acc_post_json('api-meetings-meetings-publish', json_data={}, pk=meeting_json['id'], assert_status_code=200) meeting_json = self.get_meeting(meeting_json['id']) self.assertEqual(1, meeting_json['status']) self.assertEqual(2, len(mail.outbox)) mail.outbox = [] self.acc_post_json('api-meetings-meetings-reminder', json_data={}, pk=meeting_json['id'], assert_status_code=200) self.assertEqual( 1, len(mail.outbox) ) # 1 because currently reminder isn't sent to initiating user
def test_members_count(self): self.account = AccountFactory() self.admin = AdminFactory(accounts=[self.account]) self.login_admin() resp = self.client.get( reverse('board_members', kwargs={'url': self.account.url})) self.assertContains(resp, 'class="member"', 1) UserFactory.create_batch(5, accounts=[self.account]) resp = self.client.get( reverse('board_members', kwargs={'url': self.account.url})) self.assertContains(resp, 'class="member"', 6) self.account = AccountFactory() self.user = UserFactory(accounts=[self.account]) resp = self.client.get( reverse('board_members', kwargs={'url': self.account.url})) self.assertContains(resp, 'class="member"', 6) self.client.logout() self.login_member() self.membership = self.user.get_membership(account=self.account) resp = self.client.get( reverse('board_members', kwargs={'url': self.account.url})) self.assertContains(resp, 'class="member"', 1) self.assertNotContains(resp, 'data-chairman="true"') CommitteeFactory(chairman=self.membership) resp = self.client.get( reverse('board_members', kwargs={'url': self.account.url})) self.assertContains(resp, 'class="member"', 1) self.assertContains(resp, 'data-chairman="true"')
def setUp(self): self.create_init_data() self.committee = CommitteeFactory(account=self.account, chairman=self.membership_admin) self.user.get_membership(self.account).committees.add(self.committee) self.admin.get_membership(self.account).committees.add(self.committee) self.membership.committees.add(self.committee) self.meetings = MeetingFactory(account=self.account, committee=self.committee) mail.outbox = []
def create_init_data(self): from committees.models import Committee from profiles.models import User, Membership from accounts.factories import AccountFactory from profiles.factories import AdminFactory, UserFactory from meetings.factories import MeetingFactory from committees.factories import CommitteeFactory from django.contrib.contenttypes.models import ContentType from dashboard.models import RecentActivity from meetings.models import Meeting self.create_manual_migrations_if_needed() self.account = AccountFactory() self.admin = AdminFactory(accounts=[self.account]) UserFactory.create_batch(5, accounts=[self.account]) CommitteeFactory.create_batch(5) for membership in Membership.objects.filter(user__in=User.objects.select_related().exclude(is_superuser=True)): membership.committees.add(*random.sample(set(Committee.objects.filter(account_id=membership.account_id)), 2)) # Set last membership as comittee chairman (comittee_set) membership.committee_set.add(*random.sample(set(Committee.objects.filter(account_id=membership.account_id)), 1)) self.meetings = MeetingFactory.create_batch(2) # Document creation is broken and needs fixing # for meeting in self.meetings: # DocumentFactory.create_batch(2, meeting=meeting) self.membership = Membership.objects.filter(is_admin=False, account=self.account).order_by('pk')[0] self.membership_admin = Membership.objects.filter(is_admin=True, account=self.account)[0] self.user = self.membership.user for meeting in self.meetings: RecentActivity.objects.create(init_user=self.user, account=self.account, content_type=ContentType.objects.get_for_model(Meeting), object_id=meeting.id, action_flag=RecentActivity.ADDITION)
def test_list_next_repetition_date(self): self.login_admin() # Committee both to have predictable memberships count and also to overcome current permissions issue: to edit meetings # one needs to be either meeting's committee chair or chair of any other committee (if meetings doesn't have any selected) committee = CommitteeFactory(account=self.account, chairman=self.membership_admin) committee.memberships.add(self.membership_admin) meeting_json = self.acc_post_json( 'api-meetings-meetings-list', { # Note: dates are in past 'start': (now().replace(tzinfo=pytz.utc, hour=12, minute=0, second=0, microsecond=0) - timedelta(days=3)).isoformat(), 'end': (now().replace(tzinfo=pytz.utc, hour=13, minute=0, second=0, microsecond=0) - timedelta(days=3)).isoformat(), 'name': 'Test meeting', 'description': 'describe it! Now.', 'location': 'in memory', 'committee': None, 'extra_members': [], 'repeat_type': Meeting.REPEAT_TYPES.every_day, 'repeat_interval': 1, 'repeat_max_count': 100, }).json() self.acc_post_json('api-meetings-meetings-publish', json_data={}, pk=meeting_json['id'], assert_status_code=200) meetings = self.acc_get('api-meetings-meetings-list').json() meeting = next(m for m in meetings['results'] if m['id'] == meeting_json['id']) self.assertEqual(now().replace(tzinfo=pytz.utc).date().isoformat(), meeting['next_repetition_date'])
def test_delete_meeting_forbidden(self): self.login_admin() new_acc = AccountFactory() new_committee = CommitteeFactory(chairman=self.membership_admin, account=new_acc) new_meeting = MeetingFactory(committee=new_committee, account=new_acc) url = reverse('meetings:delete', kwargs={ 'pk': new_meeting.pk, 'url': get_current_account(self).url }) response = self.ajax(url) self.assertEqual(response.status_code, 404)
def test_meeting_attendance(self): self.login_admin() committee = CommitteeFactory(account=self.account, chairman=self.membership_admin) committee.memberships.add(self.membership) committee.memberships.add(self.membership_admin) meeting_json = self._create_simple_meeting(committee=committee.id, publish=True) # Not allowed for future meetings meeting_id = meeting_json['id'] self.acc_post_json( 'api-meetings-meetings-attendance', pk=meeting_id, json_data={ 'user': self.user.id, 'present': MeetingAttendance.PRESENT_TYPES.attended_in_person }, assert_status_code=403) Meeting.objects.filter(pk=meeting_id).update(start=timezone.now() - timedelta(hours=2)) meeting_json = self.get_meeting(meeting_id) self.assertEqual( None, meeting_json['details']['rsvp_responses'][0]['present']) self.assertEqual( None, meeting_json['details']['rsvp_responses'][1]['present']) self.acc_post_json( 'api-meetings-meetings-attendance', pk=meeting_id, json_data={ 'user': self.user.id, 'present': MeetingAttendance.PRESENT_TYPES.attended_in_person }) meeting_json = self.get_meeting(meeting_id) responses = sorted( meeting_json['details']['rsvp_responses'], key=lambda r: r['user_id'] == self.user.id) # put him first self.assertEqual(MeetingAttendance.PRESENT_TYPES.attended_in_person, responses[0]['present']) self.assertEqual(None, responses[1]['present'])
def _setup(self): Page.objects.filter(id=2).delete() root = Page.get_first_root_node() homepage = HomePage( title="St Louis DSA", banner_title="Welcome to St Louis DSA!", mission_statement=fake.sentence(10), values_statement=fake.sentence(10), highlighted_campaign=f"{' '.join(fake.words(2)).title()} Campaign", highlighted_description=fake.paragraph(5), ) root.add_child(instance=homepage) site = Site( hostname="localhost", root_page=homepage, is_default_site=True, site_name="stldsa.org", ) site.save() newsindexpage = NewsIndexPage( title="Updates", slug="updates", show_in_menus=True, ) homepage.add_child(instance=newsindexpage) newsindexpage.has_children_in_menu = False newsindexpage.sub_menu = None NewsPage = apps.get_model("news.NewsPage") newspage = NewsPage( title=fake.sentence(), main_story_heading=fake.sentence(), main_story_copy=fake.paragraph(10), related_stories=[ ( "related_story", { "heading": fake.sentence(4), "copy": fake.paragraph(5), }, ), ( "related_story", { "heading": fake.sentence(4), "copy": fake.paragraph(4), }, ), ], show_in_menus=False, ) newsindexpage.add_child(instance=newspage) event_menu_page = EventsPage(title="Events", show_in_menus=True, link_url="/events/") homepage.add_child(instance=event_menu_page) formation_index = InfoPage(title="All Formation Groups", show_in_menus=True) homepage.add_child(instance=formation_index) for formation_type_name in [ "Priority Resolutions", "Committees", "Working Groups", "Caucuses", ]: formation_type = CommitteesPage( title=formation_type_name, slug=stringcase.spinalcase(formation_type_name), show_in_menus=True, ) formation_index.add_child(instance=formation_type) formation_list = CommitteeFactory.build_batch(4) for formation in formation_list: formation_type.add_child(instance=formation) revision = formation.save_revision() revision.publish() formation.save() future_event = Event( title="Event Title", description=fake.paragraph(), start=fake.future_datetime( end_date=datetime.timedelta(days=6), tzinfo=datetime.timezone.utc, ), formation=formation, ) future_event.save() revision = formation_type.save_revision() revision.publish() formation_type.save() formation_index.save() Group.objects.create(name="Members")
from django.core.management.base import BaseCommand from wagtail.models import Page, Site from events.models import Event, EventsPage from home.models import HomePage from news.models import NewsIndexPage, InfoPage from committees.models import CommitteesPage from committees.factories import CommitteeFactory from django.contrib.auth.models import Group fake = Faker() User = get_user_model() logger = logging.getLogger("setup_page_tree") committee_list = CommitteeFactory.build_batch(8) class Command(BaseCommand): """ this command is used to create the initial wagtail cms page tree """ help = "creates initial wagtail cms page tree" requires_system_checks = False def _setup(self): Page.objects.filter(id=2).delete() root = Page.get_first_root_node() homepage = HomePage( title="St Louis DSA",
def test_update(self): self.init_second_account() self.login_admin() meeting_json = self._create_simple_meeting() meeting = Meeting.objects.get(pk=meeting_json['id']) # Update _, m3 = self.create_membership() meeting_json['extra_members'] = [m3.id] meeting_json['name'] = 'Update it!' committee = Committee.objects.filter(account=self.account).first() meeting_json['committee'] = committee.id meeting_json = self.acc_put_json('api-meetings-meetings-detail', pk=meeting.id, json_data=meeting_json).json() meeting = Meeting.objects.get(pk=meeting_json['id']) self.assertEqual([m3.id], list( meeting.extra_members.values_list('id', flat=True))) self.assertEqual('Update it!', meeting.name) self.assertEqual(committee, meeting.committee) self.assertTrue( RecentActivity.objects.filter( content_type=ContentType.objects.get_for_model(meeting), object_id=meeting.id, action_flag=RecentActivity.CHANGE).exists(), "Recent activity should be logged.") # Wrong committee/membership - from other account: c2 = CommitteeFactory(account=self.account2) mm1 = dict(meeting_json) mm1['committee'] = c2.id error = self.acc_put_json('api-meetings-meetings-detail', pk=meeting.id, json_data=mm1, assert_status_code=400).json() self.assertEqual( { 'committee': ['Invalid pk "%d" - object does not exist.' % c2.id], 'detail': WRONG_REQUEST }, error) mm2 = dict(meeting_json) mm2['extra_members'] = [self.membership2.id] error = self.acc_put_json('api-meetings-meetings-detail', pk=meeting.id, json_data=mm2, assert_status_code=400).json() self.assertEqual( { 'extra_members': [ 'Invalid pk "%d" - object does not exist.' % self.membership2.id ], 'detail': WRONG_REQUEST }, error) # Can reset those values mm3 = dict(meeting_json) mm3['committee'] = None mm3['extra_members'] = [] meeting_json = self.acc_put_json('api-meetings-meetings-detail', pk=meeting.id, json_data=mm3).json() meeting = Meeting.objects.get(pk=meeting_json['id']) self.assertEqual([], list( meeting.extra_members.values_list('id', flat=True))) self.assertEqual(None, meeting.committee)
def test_rsvp(self): self.login_admin() committee = CommitteeFactory(account=self.account, chairman=self.membership_admin) committee.memberships.add(self.membership) committee.memberships.add(self.membership_admin) meeting_json = self._create_simple_meeting(committee=committee.id, publish=True) meeting_json['repeat_type'] = Meeting.REPEAT_TYPES.every_week meeting_json['repeat_max_count'] = 20 self.acc_put_json('api-meetings-meetings-detail', pk=meeting_json['id'], json_data=meeting_json) meeting_json = self.get_meeting(meeting_json['id']) self.assertEqual( None, meeting_json['details']['current_repetition']['rsvp_response']) # Global rsvp for all dates self.acc_post_json('api-meetings-meetings-rsvp', pk=meeting_json['id'], json_data={ 'response': RsvpResponse.ACCEPT, 'accept_type': RsvpResponse.IN_PERSON, 'note': 'Rsvp note here!', 'meeting_repetition': None }) meeting_json = self.get_meeting(meeting_json['id']) details = meeting_json['details'] self.assertEqual(RsvpResponse.ACCEPT, details['current_repetition']['rsvp_response']) self.assertEqual(RsvpResponse.IN_PERSON, details['current_repetition']['rsvp_accept_type']) self.assertEqual('Rsvp note here!', details['current_repetition']['rsvp_note']) self.assertEqual(RsvpResponse.ACCEPT, details['future_repetitions'][2]['rsvp_response']) self.assertEqual(RsvpResponse.IN_PERSON, details['future_repetitions'][2]['rsvp_accept_type']) self.assertEqual('Rsvp note here!', details['future_repetitions'][2]['rsvp_note']) # Now local RSVP for single date self.acc_post_json('api-meetings-meetings-rsvp', pk=meeting_json['id'], json_data={ 'response': RsvpResponse.TENTATIVE, 'accept_type': 0, 'note': 'Sorry guys', 'meeting_repetition': details['future_repetitions'][2]['id'], }) meeting_json = self.get_meeting(meeting_json['id']) details = meeting_json['details'] # as it was before self.assertEqual(RsvpResponse.ACCEPT, details['current_repetition']['rsvp_response']) self.assertEqual(RsvpResponse.IN_PERSON, details['current_repetition']['rsvp_accept_type']) self.assertEqual('Rsvp note here!', details['current_repetition']['rsvp_note']) # changed self.assertEqual(RsvpResponse.TENTATIVE, details['future_repetitions'][2]['rsvp_response']) self.assertEqual(RsvpResponse.IN_PERSON, details['future_repetitions'][2]['rsvp_accept_type']) self.assertEqual('Sorry guys', details['future_repetitions'][2]['rsvp_note'])
def test_share(self): root = Folder.objects.get_account_root(self.account) committee = CommitteeFactory(chairman=self.membership_admin) folder = Folder.objects.create(parent=committee.folder, account=self.account, name="sub_folder") self.login_member() self.acc_get('api-documents-folders-detail', pk=folder.id, assert_status_code=403) self.login_admin() self.acc_post_json('api-documents-folders-share', pk=folder.id, json_data={ 'memberships': [self.membership.id], 'permission': 'view', }) self.login_member() folder_json = self.acc_get('api-documents-folders-detail', pk=folder.id).json() self.assertEqual('sub_folder', folder_json['name']) # Should fail self.acc_delete('api-documents-folders-share', pk=folder.id, json_data={ 'id': folder_json['permissions'][0]['id'] }, assert_status_code=403) # Drop permission: Should be no access again # ------------------------------------------- self.login_admin() self.acc_delete('api-documents-folders-share', pk=folder.id, json_data={ 'permission_id': folder_json['permissions'][0]['id'] }) self.login_member() self.acc_get('api-documents-folders-detail', pk=folder.id, assert_status_code=403) # Try role permissions # -------------------- self.login_admin() self.acc_post_json('api-documents-folders-share', pk=folder.id, json_data={ 'role': Membership.ROLES.member, 'permission': 'edit', }) self.login_member() folder_json = self.acc_get('api-documents-folders-detail', pk=folder.id).json() self.assertEqual('sub_folder', folder_json['name']) folder_json['name'] = 'Surprise!' self.acc_put_json('api-documents-folders-detail', pk=folder.id, json_data=folder_json) folder.refresh_from_db() self.assertEqual('Surprise!', folder.name) # Try wrong role permissions # -------------------------- self.login_admin() folder_json = self.acc_get('api-documents-folders-detail', pk=folder.id).json() self.acc_delete('api-documents-folders-share', pk=folder.id, json_data={ 'permission_id': folder_json['permissions'][0]['id'] }) self.acc_post_json('api-documents-folders-share', pk=folder.id, json_data={ 'role': Membership.ROLES.guest, # <------- NOTE: "guest" 'permission': 'edit', }) self.login_member() self.acc_get('api-documents-folders-detail', pk=folder.id, assert_status_code=403).json()
def test_access(self): # All previous tests used admin, which is kind of a god, i.e. can do anything. Let's test common member. self.login_member() root = Folder.objects.get_account_root(self.account) # User can't create folders in root self.acc_post_json('api-documents-folders-list', { 'name': "The folder", 'parent': root.id }, assert_status_code=403) # Nor documents self.acc_post_json('api-documents-documents-list', { 'body': base64_encode('File contents')[0], 'name': 'The file.docx', 'folder': root.id, }, assert_status_code=403) # He can, inside his own folder folder = self.acc_post_json('api-documents-folders-list', { 'name': "The folder", 'parent': self.membership.private_folder.id }).json() # And subfolder of it sub_folder = self.acc_post_json('api-documents-folders-list', { 'name': "The subfolder", 'parent': folder['id'] }).json() # And files document = self.acc_post_json('api-documents-documents-list', { 'body': base64_encode('File contents')[0], 'name': 'The file.docx', 'folder': self.membership.private_folder.id, }).json() # And move documents document['folder'] = sub_folder['id'] self.acc_put_json('api-documents-documents-detail', pk=document['id'], json_data=document) # But not in other's folder: self.acc_post_json('api-documents-folders-list', { 'name': "The folder", 'parent': self.membership_admin.private_folder.id, }, assert_status_code=403) # Nor documents self.acc_post_json('api-documents-documents-list', { 'body': base64_encode('File contents')[0], 'name': 'The file.docx', 'folder': self.membership_admin.private_folder.id, }, assert_status_code=403) # And can't into committee he isn't in committee = CommitteeFactory(chairman=self.membership_admin) self.assertTrue(committee.folder) self.acc_post_json('api-documents-folders-list', { 'name': "The folder", 'parent': committee.folder.id, }, assert_status_code=403) # Nor documents self.acc_post_json('api-documents-documents-list', { 'body': base64_encode('File contents')[0], 'name': 'The file.docx', 'folder': committee.folder.id, }, assert_status_code=403) # But can as soon as he becomes a member committee.memberships.add(self.membership) self.acc_post_json('api-documents-folders-list', { 'name': "The folder", 'parent': committee.folder.id, }) # Nor documents self.acc_post_json('api-documents-documents-list', { 'body': base64_encode('File contents')[0], 'name': 'The file.docx', 'folder': committee.folder.id, }) # Other account must have no access to our documents, let's just check it self.init_second_account() self.login_admin2() self.acc_get('api-documents-documents-list', assert_status_code=403) self.acc_post_json('api-documents-documents-list', { 'body': base64_encode('File contents')[0], 'name': 'The file.docx', 'folder': root.id, }, assert_status_code=403)