Ejemplo n.º 1
0
    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
Ejemplo n.º 3
0
 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"')
Ejemplo n.º 4
0
 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 = []
Ejemplo n.º 5
0
    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'])
Ejemplo n.º 7
0
 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'])
Ejemplo n.º 9
0
    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")
Ejemplo n.º 10
0
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",
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
    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'])
Ejemplo n.º 13
0
    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()
Ejemplo n.º 14
0
    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)