예제 #1
0
    def before_update_object(self, session, data, view_kwargs):
        """
        before update method to verify if session is locked before updating session object
        :param event:
        :param data:
        :param view_kwargs:
        :return:
        """
        is_organizer = has_access('is_admin') or has_access(
            'is_organizer', event_id=session.event_id)
        if session.is_locked and not is_organizer:
            raise ForbiddenError(
                {'pointer': '/data/attributes/is-locked'},
                "Locked sessions cannot be edited",
            )

        new_state = data.get('state')

        if (new_state and new_state != session.state and
            (is_organizer or
             (session.ends_at and session.ends_at > datetime.now(pytz.utc)))):
            # State change detected. Verify that state change is allowed
            g.send_email = new_state in [
                'accepted',
                'rejected',
                'confirmed',
                'rejected',
                'canceled',
                'withdrawn',
            ]
            key = 'speaker'
            if is_organizer:
                key = 'organizer'
            state_dict = SESSION_STATE_DICT[key]
            try:
                state_dict[session.state][new_state]
            except KeyError:
                raise ForbiddenError(
                    {'pointer': '/data/attributes/state'},
                    f'You cannot change a session state from "{session.state}" to "{new_state}"',
                )

        # We allow organizers and admins to edit session without validations
        complex_field_values = data.get('complex_field_values', 'absent')
        # Set default to 'absent' to differentiate between None and not sent
        is_absent = complex_field_values == 'absent'
        # True if values are not sent in data JSON
        is_same = data.get(
            'complex_field_values') == session.complex_field_values
        # Using original value to ensure None instead of absent
        # We stop checking validations for organizers only if they may result in data change or absent. See test_session_forms_api.py for more info
        if not (is_organizer and (is_absent or is_same)):
            data[
                'complex_field_values'] = validate_custom_form_constraints_request(
                    'session', self.resource.schema, session, data)
예제 #2
0
    def before_post(self, args, kwargs, data=None):
        """
        method to add user_id to view_kwargs before post
        :param args:
        :param kwargs:
        :param data:
        :return:
        """
        data['user'] = current_user.id
        require_relationship(['event', 'user'], data)

        if not has_access('is_coorganizer', event_id=data['event']):
            event = db.session.query(Event).filter_by(id=data['event']).one()
            if event.state == "draft":
                raise ObjectNotFound(
                    {'parameter': 'event_id'},
                    "Event: {} not found".format(data['event']),
                )

        if (get_count(
                db.session.query(Event).filter_by(
                    id=int(data['event']), is_sessions_speakers_enabled=False))
                > 0):
            raise ForbiddenError({'pointer': ''},
                                 "Speakers are disabled for this Event")

        check_email_override(data, data['event'])

        if (data.get('email') and get_count(
                db.session.query(Speaker).filter_by(event_id=int(
                    data['event']),
                                                    email=data['email'],
                                                    deleted_at=None)) > 0):
            raise ForbiddenError({'pointer': ''},
                                 'Speaker with this Email ID already exists')

        if 'sessions' in data:
            session_ids = data['sessions']
            for session_id in session_ids:
                if not has_access('is_session_self_submitted',
                                  session_id=session_id):
                    raise ObjectNotFound(
                        {'parameter': 'session_id'},
                        f"Session: {session_id} not found",
                    )

        excluded = []
        if not data.get('email'):
            # Don't check requirement of email if overriden
            excluded = ['email']
        data[
            'complex_field_values'] = validate_custom_form_constraints_request(
                'speaker', self.schema, Speaker(event_id=data['event']), data,
                excluded)
    def before_post(self, args, kwargs, data=None):
        """
        method to add user_id to view_kwargs before post
        :param args:
        :param kwargs:
        :param data:
        :return:
        """
        require_relationship(['event', 'user'], data)

        if not has_access('is_coorganizer', event_id=data['event']):
            event = db.session.query(Event).filter_by(id=data['event']).one()
            if event.state == "draft":
                raise ObjectNotFound(
                    {'parameter': 'event_id'},
                    "Event: {} not found".format(data['event_id']),
                )

        if (get_count(
                db.session.query(Event).filter_by(
                    id=int(data['event']), is_sessions_speakers_enabled=False))
                > 0):
            raise ForbiddenError({'pointer': ''},
                                 "Speakers are disabled for this Event")

        if (not data.get('is_email_overridden') and get_count(
                db.session.query(Speaker).filter_by(event_id=int(
                    data['event']),
                                                    email=data['email'],
                                                    deleted_at=None)) > 0):
            raise ForbiddenError({'pointer': ''},
                                 'Speaker with this Email ID already exists')

        if data.get('is_email_overridden') and not has_access(
                'is_organizer', event_id=data['event']):
            raise ForbiddenError(
                {'pointer': 'data/attributes/is_email_overridden'},
                'Organizer access required to override email',
            )
        elif (data.get('is_email_overridden')
              and has_access('is_organizer', event_id=data['event'])
              and not data.get('email')):
            data['email'] = current_user.email

        if 'sessions' in data:
            session_ids = data['sessions']
            for session_id in session_ids:
                if not has_access('is_session_self_submitted',
                                  session_id=session_id):
                    raise ObjectNotFound(
                        {'parameter': 'session_id'},
                        "Session: {} not found".format(session_id),
                    )
예제 #4
0
def validate_event(user, data):
    if not user.can_create_event():
        raise ForbiddenError({'source': ''}, "Please verify your Email")

    if data.get('state', None) == 'published' and not user.can_publish_event():
        raise ForbiddenError({'source': ''},
                             "Only verified accounts can publish events")

    if not data.get('name', None) and data.get('state', None) == 'published':
        raise ConflictError(
            {'pointer': '/data/attributes/name'},
            "Event Name is required to publish the event",
        )
예제 #5
0
    def validate_fields(self, data, original_data):
        is_patch_request = 'id' in original_data['data']
        if is_patch_request:
            try:
                session = Session.query.filter_by(
                    id=original_data['data']['id']).one()
            except NoResultFound:
                raise ObjectNotFound({'parameter': '{id}'},
                                     "Session: not found")

            if 'starts_at' not in data:
                data['starts_at'] = session.starts_at

            if 'ends_at' not in data:
                data['ends_at'] = session.ends_at

            if 'event' not in data:
                data['event'] = session.event_id

        if data['starts_at'] and data['ends_at']:
            if data['starts_at'] >= data['ends_at']:
                raise UnprocessableEntityError(
                    {'pointer': '/data/attributes/ends-at'},
                    "ends-at should be after starts-at",
                )
            if not is_patch_request and datetime.timestamp(
                    data['starts_at']) <= datetime.timestamp(datetime.now()):
                raise UnprocessableEntityError(
                    {'pointer': '/data/attributes/starts-at'},
                    "starts-at should be after current date-time",
                )

        if 'state' in data:
            if data['state'] not in ('draft', 'pending'):
                if not has_access('is_coorganizer', event_id=data['event']):
                    raise ForbiddenError({'source': ''},
                                         'Co-organizer access is required.')

        if 'track' in data:
            if not has_access('is_coorganizer', event_id=data['event']):
                raise ForbiddenError({'source': ''},
                                     'Co-organizer access is required.')

        if 'microlocation' in data:
            if not has_access('is_coorganizer', event_id=data['event']):
                raise ForbiddenError({'source': ''},
                                     'Co-organizer access is required.')

        validate_complex_fields_json(self, data, original_data)
 def before_post(self, args, kwargs, data):
     """
     before get method to get the resource id for fetching details
     :param args:
     :param kwargs:
     :param data:
     :return:
     """
     require_relationship(['group', 'role'], data)
     group = Group.query.get(data['group'])
     role = Role.query.get(data['role'])
     if group.user != current_user:
         raise ForbiddenError({'pointer': 'group'}, 'Owner access is required.')
     if role.name != 'organizer':
         raise ForbiddenError({'pointer': 'role'}, 'Only organizer role is allowed.')
예제 #7
0
    def before_create_object(self, data, view_kwargs):
        """
        before create object method for GroupListPost Class
        :param data:
        :param view_kwargs:
        :return:
        """
        data['user_id'] = current_user.id
        if not current_user.is_verified:
            raise ForbiddenError({'source': ''}, 'Access Forbidden')

        for event in data.get('events', []):
            if not has_access('is_owner', event_id=event):
                raise ForbiddenError({'source': ''},
                                     "Event owner access required")
예제 #8
0
def check_same_event(room_ids):
    rooms = Microlocation.query.filter(Microlocation.id.in_(room_ids)).all()
    event_ids = set()
    for room in rooms:
        event_ids.add(room.event_id)
        if len(event_ids) > 1:
            raise ForbiddenError(
                {'pointer': '/data/relationships/rooms'},
                'Video Stream can only be created/edited with rooms of a single event',
            )
    if not has_access('is_coorganizer', event_id=event_ids.pop()):
        raise ForbiddenError(
            {'pointer': '/data/relationships/rooms'},
            "You don't have access to the event of provided rooms",
        )
예제 #9
0
def validate_event(user, modules, data):
    if not user.can_create_event():
        raise ForbiddenError({'source': ''}, "Please verify your Email")
    elif not modules.ticket_include:
        raise ForbiddenError({'source': ''},
                             "Ticketing is not enabled in the system")
    if (data.get('can_pay_by_paypal', False)
            or data.get('can_pay_by_cheque', False)
            or data.get('can_pay_by_bank', False)
            or data.get('can_pay_by_stripe', False)):
        if not modules.payment_include:
            raise ForbiddenError({'source': ''},
                                 "Payment is not enabled in the system")
    if data.get('is_donation_enabled', False) and not modules.donation_include:
        raise ForbiddenError(
            {'source': '/data/attributes/is-donation-enabled'},
            "Donation is not enabled in the system",
        )

    if data.get('state', None) == 'published' and not user.can_publish_event():
        raise ForbiddenError({'source': ''},
                             "Only verified accounts can publish events")

    if (not data.get('is_event_online')
            and data.get('state', None) == 'published'
            and not data.get('location_name', None)):
        raise ConflictError(
            {'pointer': '/data/attributes/location-name'},
            "Location is required to publish the event",
        )

    if data.get('location_name', None) and data.get('is_event_online'):
        raise ConflictError(
            {'pointer': '/data/attributes/location-name'},
            "Online Event does not have any locaton",
        )

    if not data.get('name', None) and data.get('state', None) == 'published':
        raise ConflictError(
            {'pointer': '/data/attributes/location-name'},
            "Event Name is required to publish the event",
        )

    if data.get('searchable_location_name') and data.get('is_event_online'):
        raise ConflictError(
            {'pointer': '/data/attributes/searchable-location-name'},
            "Online Event does not have any locaton",
        )
예제 #10
0
 def before_update_object(self, ticket, data, view_kwargs):
     """
     method to check if paid ticket has payment method before updating ticket object
     :param ticket:
     :param data:
     :param view_kwargs:
     :return:
     """
     if ticket.type == 'paid' or ticket.type == 'donation':
         try:
             event = (
                 db.session.query(Event)
                 .filter_by(id=ticket.event.id, deleted_at=None)
                 .one()
             )
         except NoResultFound:
             raise UnprocessableEntityError(
                 {'event_id': ticket.event.id}, "Event does not exist"
             )
         if not event.is_payment_enabled():
             raise UnprocessableEntityError(
                 {'event_id': ticket.event.id},
                 "Event having paid ticket must have a payment method",
             )
     
     if (data.get('deleted_at') and ticket.has_current_orders):
         raise ForbiddenError(
             {'param': 'ticket_id'},
             "Can't delete a ticket that has sales",
         )
예제 #11
0
    def test_errors(self):
        """Method to test the status code of all errors"""

        with app.test_request_context():
            # Forbidden Error
            forbidden_error = ForbiddenError({'source': ''},
                                             'Super admin access is required')
            self.assertEqual(forbidden_error.status, 403)

            # Not Found Error
            not_found_error = NotFoundError({'source': ''},
                                            'Object not found.')
            self.assertEqual(not_found_error.status, 404)

            # Server Error
            server_error = ServerError({'source': ''}, 'Internal Server Error')
            self.assertEqual(server_error.status, 500)

            # UnprocessableEntity Error
            unprocessable_entity_error = UnprocessableEntityError(
                {'source': ''}, 'Entity cannot be processed')
            self.assertEqual(unprocessable_entity_error.status, 422)

            # Bad Request Error
            bad_request_error = BadRequestError({'source': ''},
                                                'Request cannot be served')
            self.assertEqual(bad_request_error.status, 400)
예제 #12
0
    def test_exceptions(self):
        """Method to test all exceptions."""

        # Unprocessable Entity Exception
        with self.assertRaises(UnprocessableEntityError):
            raise UnprocessableEntityError(
                {'pointer': '/data/attributes/min-quantity'},
                "min-quantity should be less than max-quantity",
            )

        # Conflict Exception
        with self.assertRaises(ConflictError):
            raise ConflictError({'pointer': '/data/attributes/email'},
                                "Email already exists")

        # Forbidden Exception
        with self.assertRaises(ForbiddenError):
            raise ForbiddenError({'source': ''}, "Access Forbidden")

        # Not Found Error
        with self.assertRaises(NotFoundError):
            raise NotFoundError({'source': ''}, "Not Found")

        # Server Error
        with self.assertRaises(ServerError):
            raise ServerError({'source': ''}, "Internal Server Error")

        # Bad Request Error
        with self.assertRaises(BadRequestError):
            raise BadRequestError({'source': ''}, "Bad Request")

        # Method Not Allowed Exception
        with self.assertRaises(MethodNotAllowed):
            raise MethodNotAllowed({'source': ''}, "Method Not Allowed")
예제 #13
0
def is_coorganizer_endpoint_related_to_event(view, view_args, view_kwargs,
                                             *args, **kwargs):
    """
     If the authorization header is present (but expired)
     and the eventbeing accessed is not published
     - And the user is related to the event (organizer, co-organizer etc) show a 401
     - Else show a 404

    :param view:
    :param view_args:
    :param view_kwargs:
    :param args:
    :param kwargs:
    :return:
    """
    user = get_identity()

    if user.is_staff:
        verify_jwt_in_request()
        return view(*view_args, **view_kwargs)

    if user.has_event_access(kwargs['event_id']):
        verify_jwt_in_request()
        return view(*view_args, **view_kwargs)

    raise ForbiddenError({'source': ''}, 'Co-organizer access is required.')
예제 #14
0
def is_coorganizer_but_not_admin(view, view_args, view_kwargs, *args, **kwargs):
    user = current_user

    if user.has_event_access(kwargs['event_id']):
        return view(*view_args, **view_kwargs)

    return ForbiddenError({'source': ''}, 'Co-organizer access is required.').respond()
 def decorated_function(*args, **kwargs):
     user = current_identity
     if not user.is_admin and not user.is_super_admin:
         return ForbiddenError({
             'source': ''
         }, 'Admin access is required').respond()
     return f(*args, **kwargs)
예제 #16
0
def reject_invite(speaker_invite_id):
    try:
        speaker_invite = SpeakerInvite.query.filter_by(
            id=speaker_invite_id).one()
    except NoResultFound:
        raise NotFoundError({'source': ''}, 'Speaker Invite Not Found')
    else:
        if not current_user.email == speaker_invite.email:
            raise ForbiddenError({'source': ''}, 'Invitee access is required.')
        elif speaker_invite.status == 'accepted':
            raise ConflictError(
                {'pointer': '/data/status'},
                'Accepted speaker invite can not be rejected.',
            )
        elif speaker_invite.status == 'rejected':
            raise ConflictError(
                {'pointer': '/data/status'},
                'Speaker invite is already rejected.',
            )
        try:
            speaker_invite.status = 'rejected'
            save_to_db(speaker_invite, {'speaker invite rejected'})
        except Exception:
            raise UnprocessableEntityError(
                {'source': ''}, 'error while rejecting speaker invite.')
    return jsonify(
        success=True,
        message="Speaker invite rejected successfully",
    )
예제 #17
0
def resend_emails():
    """
    Sends confirmation email for pending and completed orders on organizer request
    :param order_identifier:
    :return: JSON response if the email was succesfully sent
    """
    order_identifier = request.json['data']['order']
    order = safe_query(db, Order, 'identifier', order_identifier, 'identifier')
    if (has_access('is_coorganizer', event_id=order.event_id)):
        if order.status == 'completed' or order.status == 'placed':
            # fetch tickets attachment
            order_identifier = order.identifier
            key = UPLOAD_PATHS['pdf']['tickets_all'].format(identifier=order_identifier)
            ticket_path = 'generated/tickets/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'
            key = UPLOAD_PATHS['pdf']['order'].format(identifier=order_identifier)
            invoice_path = 'generated/invoices/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'

            # send email.
            send_email_to_attendees(order=order, purchaser_id=current_user.id, attachments=[ticket_path, invoice_path])
            return jsonify(status=True, message="Verification emails for order : {} has been sent succesfully".
                           format(order_identifier))
        else:
            return UnprocessableEntityError({'source': 'data/order'},
                                            "Only placed and completed orders have confirmation").respond()
    else:
        return ForbiddenError({'source': ''}, "Co-Organizer Access Required").respond()
예제 #18
0
 def before_post(self, args, kwargs, data):
     require_relationship(['event'], data)
     if not has_access('is_coorganizer', event_id=data['event']):
         raise ForbiddenError(
             {'pointer': '/data/relationships/event'},
             'Co-organizer access is required.',
         )
예제 #19
0
class VideoStreamModeratorList(ResourceList):
    def before_post(self, args, kwargs, data):
        require_relationship(['video_stream'], data)
        stream = safe_query_kwargs(VideoStream, data, 'video_stream')
        if not has_access('is_coorganizer', event_id=stream.event_id):
            raise ForbiddenError({'pointer': 'user_id'},
                                 'Co-Organizer access required')

    def after_create_object(self, video_stream_moderator, data, view_kwargs):
        send_email_to_moderator(video_stream_moderator)

    def query(self, view_kwargs):
        query_ = self.session.query(VideoStreamModerator)
        if user_id := view_kwargs.get('user_id'):
            if current_user.id != int(user_id):
                raise ForbiddenError({'pointer': 'user_id'},
                                     "Cannot access other user's data")
            user = safe_query_kwargs(User, view_kwargs, 'user_id')
            query_ = query_.filter_by(email=user.email)
        elif view_kwargs.get('video_stream_id'):
            stream = safe_query_kwargs(VideoStream, view_kwargs,
                                       'video_stream_id')
            if not has_access('is_coorganizer', event_id=stream.event_id):
                raise ForbiddenError({'pointer': 'user_id'},
                                     'Co-Organizer access required')
            query_ = query_.filter_by(
                video_stream_id=view_kwargs['video_stream_id'])
예제 #20
0
def is_speaker_for_session(view, view_args, view_kwargs, *args, **kwargs):
    """
    Allows admin and super admin access to any resource irrespective of id.
    Otherwise the user can only access his/her resource.
    """
    user = current_user
    if user.is_admin or user.is_super_admin:
        return view(*view_args, **view_kwargs)

    if user.is_staff:
        return view(*view_args, **view_kwargs)

    try:
        session = Session.query.filter(Session.id == view_kwargs['id']).one()
    except NoResultFound:
        return NotFoundError({
            'parameter': 'id'
        }, 'Session not found.').respond()

    if user.has_event_access(session.event_id):
        return view(*view_args, **view_kwargs)

    if session.speakers:
        for speaker in session.speakers:
            if speaker.user_id == user.id:
                return view(*view_args, **view_kwargs)

    if session.creator_id == user.id:
        return view(*view_args, **view_kwargs)

    return ForbiddenError({'source': ''}, 'Access denied.').respond()
def is_coorganizer_endpoint_related_to_event(view, view_args, view_kwargs,
                                             *args, **kwargs):
    """
     If the authorization header is present (but expired) and the event being accessed is not published
     - And the user is related to the event (organizer, co-organizer etc) show a 401
     - Else show a 404

    :param view:
    :param view_args:
    :param view_kwargs:
    :param args:
    :param kwargs:
    :return:
    """
    user = get_identity()

    if user.is_staff:
        _jwt_required(app.config['JWT_DEFAULT_REALM'])
        return view(*view_args, **view_kwargs)

    if user.is_organizer(kwargs['event_id']) or user.is_coorganizer(
            kwargs['event_id']):
        _jwt_required(app.config['JWT_DEFAULT_REALM'])
        return view(*view_args, **view_kwargs)

    return ForbiddenError({
        'source': ''
    }, 'Co-organizer access is required.').respond()
예제 #22
0
    def before_update_object(self, event, data, view_kwargs):
        """
        method to save image urls before updating event object
        :param event:
        :param data:
        :param view_kwargs:
        :return:
        """
        is_date_updated = (data.get('starts_at') != event.starts_at
                           or data.get('ends_at') != event.ends_at)
        is_draft_published = event.state == "draft" and data.get(
            'state') == "published"
        is_event_restored = event.deleted_at and not data.get('deleted_at')

        if is_date_updated or is_draft_published or is_event_restored:
            validate_date(event, data)

        if has_access(
                'is_admin') and data.get('deleted_at') != event.deleted_at:
            if len(event.orders) != 0 and not has_access('is_super_admin'):
                raise ForbiddenError(
                    {'source': ''},
                    "Event associated with orders cannot be deleted")
            event.deleted_at = data.get('deleted_at')

        if (data.get('original_image_url')
                and data['original_image_url'] != event.original_image_url):
            start_image_resizing_tasks(event, data['original_image_url'])
예제 #23
0
def can_edit_after_cfs_ends(event_id):
    """
    Method to check that user has permission to edit the speaker or session
    after the CFS ends
    """
    speakers_call = SpeakersCall.query.filter_by(
        event_id=event_id, deleted_at=None
    ).one_or_none()
    not_allowed = not (
        has_access('is_admin')
        or has_access('is_organizer', event_id=event_id)
        or has_access('is_coorganizer', event_id=event_id)
    )
    if speakers_call:
        speakers_call_tz = speakers_call.ends_at.tzinfo
        return not (
            speakers_call.ends_at <= datetime.now().replace(tzinfo=speakers_call_tz)
            and not_allowed
        )
    elif not_allowed:
        raise ForbiddenError(
            {'source': '/data/event-id'},
            f'Speaker Calls for event {event_id} not found',
        )
    return True
def is_session_self_submitted(view, view_args, view_kwargs, *args, **kwargs):
    """
    Allows admin and super admin access to any resource irrespective of id.
    Otherwise the user can only access his/her resource.
    """
    user = current_identity
    if user.is_admin or user.is_super_admin:
        return view(*view_args, **view_kwargs)

    if user.is_staff:
        return view(*view_args, **view_kwargs)

    try:
        session = Session.query.filter(
            Session.id == kwargs['session_id']).one()
    except NoResultFound:
        return NotFoundError({
            'parameter': 'session_id'
        }, 'Session not found.').respond()

    if user.is_organizer(session.event_id) or user.is_coorganizer(
            session.event_id):
        return view(*view_args, **view_kwargs)

    if session.creator_id == user.id:
        return view(*view_args, **view_kwargs)

    return ForbiddenError({'source': ''}, 'Access denied.').respond()
예제 #25
0
    def before_update_object(self, speaker, data, view_kwargs):
        """
        method to save image urls before updating speaker object
        :param speaker:
        :param data:
        :param view_kwargs:
        :return:
        """
        if not can_edit_after_cfs_ends(speaker.event_id):
            raise ForbiddenError(
                {'source': ''},
                "Cannot edit speaker after the call for speaker is ended")

        if data.get('photo_url') and data['photo_url'] != speaker.photo_url:
            start_image_resizing_tasks(speaker, data['photo_url'])

        check_email_override(data, speaker.event_id)

        excluded = []
        if not data.get('email'):
            # Don't check requirement of email if overriden
            excluded = ['email']
        data[
            'complex_field_values'] = validate_custom_form_constraints_request(
                'speaker', self.resource.schema, speaker, data, excluded)
예제 #26
0
 def before_post(self, args, kwargs, data):
     """
     before get method to get the resource id for fetching details
     :param args:
     :param kwargs:
     :param data:
     :return:
     """
     require_relationship(['session', 'event'], data)
     if not has_access('is_speaker_for_session', id=data['session']):
         raise ForbiddenError({'source': ''}, 'Speaker access is required.')
     if data.get('status'):
         if not data['status'] == 'pending':
             raise ForbiddenError(
                 {'source': ''},
                 'Speaker Invite can not created with accepted status.')
 def after_get_object(self, video_recording, view_kwargs):
     if not has_access('is_organizer',
                       event_id=video_recording.video_stream.event_id):
         raise ForbiddenError(
             {'pointer': 'event_id'},
             'You need to be the event organizer to access video recordings.',
         )
예제 #28
0
    def before_get_object(self, view_kwargs):
        """
        before get method to get the resource id for fetching details
        :param view_kwargs:
        :return:
        """
        if view_kwargs.get('attendee_id'):
            attendee = safe_query_kwargs(TicketHolder, view_kwargs,
                                         'attendee_id')
            view_kwargs['id'] = attendee.order.id
        if view_kwargs.get('order_identifier'):
            order = safe_query_kwargs(Order, view_kwargs, 'order_identifier',
                                      'identifier')
            view_kwargs['id'] = order.id
        elif view_kwargs.get('id'):
            order = safe_query_by_id(Order, view_kwargs['id'])

        if not has_access(
                'is_coorganizer_or_user_itself',
                event_id=order.event_id,
                user_id=order.user_id,
        ):
            raise ForbiddenError(
                {'source': ''},
                'You can only access your orders or your event\'s orders')

        # expire the initializing order if time limit is over.
        set_expiry_for_order(order)
예제 #29
0
def send_receipt():
    """
    Send receipts to attendees related to the provided order.
    :return:
    """
    order_identifier = request.json.get('order-identifier')
    if order_identifier:
        try:
            order = db.session.query(Order).filter_by(
                identifier=order_identifier).one()
        except NoResultFound:
            return NotFoundError({
                'parameter': '{order_identifier}'
            }, "Order not found").respond()

        if (order.user_id != current_user.id) and (not has_access(
                'is_registrar', event_id=order.event_id)):
            return ForbiddenError({
                'source': ''
            }, 'You need to be the event organizer or order buyer to send receipts.'
                                  ).respond()
        elif order.status != 'completed':
            abort(
                make_response(
                    jsonify(
                        error="Cannot send receipt for an incomplete order"),
                    409))
        else:
            send_email_to_attendees(order, current_user.id)
            return jsonify(message="receipt sent to attendees")
    else:
        return UnprocessableEntityError({
            'source': ''
        }, 'Order identifier missing').respond()
예제 #30
0
    def query(self, view_kwargs):
        """
        query method for Attendees List
        :param view_kwargs:
        :return:
        """
        query_ = self.session.query(TicketHolder)

        if view_kwargs.get('order_identifier'):
            order = safe_query_kwargs(
                Order,
                view_kwargs,
                'order_identifier',
                'identifier',
            )

            is_coorganizer = has_access(
                'is_coorganizer',
                event_id=order.event_id,
            )
            if not (
                is_coorganizer
                or current_user.id == order.user_id
                or order.is_attendee(current_user)
            ):
                raise ForbiddenError({'source': ''}, 'Access Forbidden')
            query_ = query_.join(Order).filter(Order.id == order.id)
            if not is_coorganizer and current_user.id != order.user_id:
                query_ = query_.filter(TicketHolder.user == current_user)

        if view_kwargs.get('ticket_id'):
            ticket = safe_query_kwargs(Ticket, view_kwargs, 'ticket_id')
            # if not has_access('is_registrar', event_id=ticket.event_id):
            #     raise ForbiddenError({'source': ''}, 'Access Forbidden')
            query_ = query_.join(Ticket).filter(Ticket.id == ticket.id)

        if view_kwargs.get('user_id'):
            user = safe_query_kwargs(User, view_kwargs, 'user_id')
            if not has_access('is_user_itself', user_id=user.id):
                raise ForbiddenError({'source': ''}, 'Access Forbidden')
            query_ = query_.join(User, User.email == TicketHolder.email).filter(
                User.id == user.id
            )

        query_ = event_query(query_, view_kwargs, restrict=True)
        return query_