From 63bf2bbfa703fcb19225c5f11f5ba017dd8a49c4 Mon Sep 17 00:00:00 2001 From: prateekj117 Date: Sat, 6 Jul 2019 11:05:50 +0530 Subject: [PATCH 1/5] Restrict unverified user from making free orders. --- app/api/attendees.py | 17 +---------------- app/api/orders.py | 17 +++++++++++------ 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/app/api/attendees.py b/app/api/attendees.py index d42f18c3a2..7666e235df 100644 --- a/app/api/attendees.py +++ b/app/api/attendees.py @@ -1,7 +1,7 @@ from datetime import datetime from flask import Blueprint, request, jsonify, abort, make_response -from flask_jwt import current_identity, jwt_required +from flask_jwt import current_identity from flask_rest_jsonapi import ResourceDetail, ResourceList, ResourceRelationship from flask_rest_jsonapi.exceptions import ObjectNotFound from sqlalchemy.orm.exc import NoResultFound @@ -170,21 +170,6 @@ def before_update_object(self, obj, data, kwargs): # if not has_access('is_registrar', event_id=obj.event_id): # raise ForbiddenException({'source': 'User'}, 'You are not authorized to access this.') - if 'ticket' in data: - user = safe_query(self, User, 'id', current_identity.id, 'user_id') - ticket = db.session.query(Ticket).filter_by( - id=int(data['ticket']), deleted_at=None - ).first() - if ticket is None: - raise UnprocessableEntity( - {'pointer': '/data/relationships/ticket'}, "Invalid Ticket" - ) - if not user.is_verified and ticket.price == 0: - raise UnprocessableEntity( - {'pointer': '/data/relationships/ticket'}, - "Unverified user cannot buy free tickets" - ) - if 'device_name_checkin' in data: if 'checkin_times' not in data or data['checkin_times'] is None: raise UnprocessableEntity( diff --git a/app/api/orders.py b/app/api/orders.py index 4d19df2c1a..c3daa55519 100644 --- a/app/api/orders.py +++ b/app/api/orders.py @@ -1,8 +1,8 @@ -from datetime import datetime -from flask import request, jsonify, Blueprint, url_for, redirect -import omise import logging +from datetime import datetime +import omise +from flask import request, jsonify, Blueprint, url_for, redirect from flask_jwt import current_identity as current_user from flask_rest_jsonapi import ResourceDetail, ResourceList, ResourceRelationship from marshmallow_jsonapi import fields @@ -12,7 +12,6 @@ from app.api.bootstrap import api from app.api.data_layers.ChargesLayer import ChargesLayer from app.api.helpers.db import save_to_db, safe_query, safe_query_without_soft_deleted_entries -from app.api.helpers.storage import generate_hash, UPLOAD_PATHS from app.api.helpers.errors import BadRequestError from app.api.helpers.exceptions import ForbiddenException, UnprocessableEntity, ConflictException from app.api.helpers.files import make_frontend_url @@ -22,10 +21,12 @@ send_notif_ticket_cancel from app.api.helpers.order import delete_related_attendees_for_order, set_expiry_for_order, \ create_pdf_tickets_for_holder, create_onsite_attendees_for_order +from app.api.helpers.payment import AliPayPaymentsManager, OmisePaymentsManager from app.api.helpers.payment import PayPalPaymentsManager from app.api.helpers.permission_manager import has_access from app.api.helpers.permissions import jwt_required from app.api.helpers.query import event_query +from app.api.helpers.storage import generate_hash, UPLOAD_PATHS from app.api.helpers.ticketing import TicketingManager from app.api.helpers.utilities import dasherize, require_relationship from app.api.schema.orders import OrderSchema @@ -34,8 +35,6 @@ from app.models.order import Order, OrderTicket, get_updatable_fields from app.models.ticket_holder import TicketHolder from app.models.user import User -from app.api.helpers.payment import AliPayPaymentsManager, OmisePaymentsManager - order_misc_routes = Blueprint('order_misc', __name__, url_prefix='/v1') alipay_blueprint = Blueprint('alipay_blueprint', __name__, url_prefix='/v1/alipay') @@ -56,6 +55,12 @@ def before_post(self, args, kwargs, data=None): """ require_relationship(['event'], data) + if not current_user.is_verified and data['payment_mode'] == 'free': + raise UnprocessableEntity( + {'pointer': '/data/relationships/order'}, + "Unverified user cannot place free orders" + ) + # Create on site attendees. if request.args.get('onsite', False): create_onsite_attendees_for_order(data) From 84cc9f8d341977e69708569f4e24138b9fec1dd9 Mon Sep 17 00:00:00 2001 From: prateekj117 Date: Sun, 7 Jul 2019 00:48:54 +0530 Subject: [PATCH 2/5] Check ticket-type rather than payment-mode --- app/api/orders.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/app/api/orders.py b/app/api/orders.py index c3daa55519..5d1e6c6b08 100644 --- a/app/api/orders.py +++ b/app/api/orders.py @@ -33,6 +33,7 @@ from app.models import db from app.models.discount_code import DiscountCode, TICKET from app.models.order import Order, OrderTicket, get_updatable_fields +from app.models.ticket import Ticket from app.models.ticket_holder import TicketHolder from app.models.user import User @@ -55,12 +56,6 @@ def before_post(self, args, kwargs, data=None): """ require_relationship(['event'], data) - if not current_user.is_verified and data['payment_mode'] == 'free': - raise UnprocessableEntity( - {'pointer': '/data/relationships/order'}, - "Unverified user cannot place free orders" - ) - # Create on site attendees. if request.args.get('onsite', False): create_onsite_attendees_for_order(data) @@ -79,6 +74,7 @@ def before_create_object(self, data, view_kwargs): :param view_kwargs: :return: """ + for ticket_holder in data['ticket_holders']: # Ensuring that the attendee exists and doesn't have an associated order. try: @@ -91,6 +87,16 @@ def before_create_object(self, data, view_kwargs): raise ConflictException({'pointer': '/data/relationships/attendees'}, "Attendee with id {} does not exists".format(str(ticket_holder))) + ticket = db.session.query(Ticket).filter_by( + id=int(ticket_holder_object.ticket_id), deleted_at=None + ).first() + + if not current_user.is_verified and ticket.type == 'free': + raise UnprocessableEntity( + {'pointer': '/data/relationships/order'}, + "Unverified user cannot place free orders" + ) + if data.get('cancel_note'): del data['cancel_note'] From 5319edb80fa6039f898c1696a6899604e4930ce3 Mon Sep 17 00:00:00 2001 From: prateekj117 Date: Sun, 7 Jul 2019 00:54:10 +0530 Subject: [PATCH 3/5] No need to revert the old PR --- app/api/attendees.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/api/attendees.py b/app/api/attendees.py index 7666e235df..7629b975ab 100644 --- a/app/api/attendees.py +++ b/app/api/attendees.py @@ -170,6 +170,21 @@ def before_update_object(self, obj, data, kwargs): # if not has_access('is_registrar', event_id=obj.event_id): # raise ForbiddenException({'source': 'User'}, 'You are not authorized to access this.') + if 'ticket' in data: + user = safe_query(self, User, 'id', current_identity.id, 'user_id') + ticket = db.session.query(Ticket).filter_by( + id=int(data['ticket']), deleted_at=None + ).first() + if ticket is None: + raise UnprocessableEntity( + {'pointer': '/data/relationships/ticket'}, "Invalid Ticket" + ) + if not user.is_verified and ticket.price == 0: + raise UnprocessableEntity( + {'pointer': '/data/relationships/ticket'}, + "Unverified user cannot buy free tickets" + ) + if 'device_name_checkin' in data: if 'checkin_times' not in data or data['checkin_times'] is None: raise UnprocessableEntity( From fccecc6d518e921b68c9606df56b5ea32e6c17d1 Mon Sep 17 00:00:00 2001 From: prateekj117 Date: Thu, 11 Jul 2019 13:15:21 +0530 Subject: [PATCH 4/5] Check if order contains all free tickets. --- app/api/orders.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/app/api/orders.py b/app/api/orders.py index f522e61380..3f6c0c6fa5 100644 --- a/app/api/orders.py +++ b/app/api/orders.py @@ -75,6 +75,8 @@ def before_create_object(self, data, view_kwargs): :return: """ + free_ticket_quantity = 0 + for ticket_holder in data['ticket_holders']: # Ensuring that the attendee exists and doesn't have an associated order. try: @@ -87,11 +89,14 @@ def before_create_object(self, data, view_kwargs): raise ConflictException({'pointer': '/data/relationships/attendees'}, "Attendee with id {} does not exists".format(str(ticket_holder))) - ticket = db.session.query(Ticket).filter_by( - id=int(ticket_holder_object.ticket_id), deleted_at=None - ).first() + ticket = db.session.query(Ticket).filter_by( + id=int(ticket_holder_object.ticket_id), deleted_at=None + ).first() + + if not current_user.is_verified and ticket.type == 'free': + free_ticket_quantity += 1 - if not current_user.is_verified and ticket.type == 'free': + if free_ticket_quantity == len(data['ticket_holders']): raise UnprocessableEntity( {'pointer': '/data/relationships/order'}, "Unverified user cannot place free orders" From a809c043a4cf7b1a4c77138e3f3a3d98a2565f01 Mon Sep 17 00:00:00 2001 From: prateekj117 Date: Fri, 12 Jul 2019 15:00:27 +0530 Subject: [PATCH 5/5] Required changes --- app/api/orders.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/app/api/orders.py b/app/api/orders.py index de2ba972e7..783bcea7c8 100644 --- a/app/api/orders.py +++ b/app/api/orders.py @@ -33,7 +33,6 @@ from app.models import db from app.models.discount_code import DiscountCode, TICKET from app.models.order import Order, OrderTicket, get_updatable_fields -from app.models.ticket import Ticket from app.models.ticket_holder import TicketHolder from app.models.user import User @@ -89,14 +88,10 @@ def before_create_object(self, data, view_kwargs): raise ConflictException({'pointer': '/data/relationships/attendees'}, "Attendee with id {} does not exists".format(str(ticket_holder))) - ticket = db.session.query(Ticket).filter_by( - id=int(ticket_holder_object.ticket_id), deleted_at=None - ).first() - - if not current_user.is_verified and ticket.type == 'free': + if ticket_holder_object.ticket.type == 'free': free_ticket_quantity += 1 - if free_ticket_quantity == len(data['ticket_holders']): + if not current_user.is_verified and free_ticket_quantity == len(data['ticket_holders']): raise UnprocessableEntity( {'pointer': '/data/relationships/order'}, "Unverified user cannot place free orders"