Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion app/api/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@

from app import get_settings
from app import limiter
from app.api.helpers.db import save_to_db, get_count, safe_query
from app.api.helpers.auth import AuthManager
from app.api.helpers.db import save_to_db, get_count
from app.api.helpers.errors import ForbiddenError, UnprocessableEntityError, NotFoundError, BadRequestError
from app.api.helpers.files import make_frontend_url
from app.api.helpers.mail import send_email_to_attendees
from app.api.helpers.mail import send_email_with_action, \
send_email_confirmation
from app.api.helpers.notification import send_notification_with_action
Expand All @@ -26,6 +27,7 @@
from app.api.helpers.storage import generate_hash
from app.api.helpers.third_party_auth import GoogleOAuth, FbOAuth, TwitterOAuth, InstagramOAuth
from app.api.helpers.utilities import get_serializer, str_generator
from app.api.helpers.permission_manager import has_access
from app.models import db
from app.models.mail import PASSWORD_RESET, PASSWORD_CHANGE, \
PASSWORD_RESET_AND_VERIFY
Expand Down Expand Up @@ -363,3 +365,38 @@ def decorated(*args, **kwargs):
def environment_details():
envdump = EnvironmentDump(include_config=False)
return envdump.dump_environment()


@ticket_blueprint.route('/orders/resend-email', methods=['POST'])
@limiter.limit(
'5/minute', key_func=lambda: request.json['data']['user'], error_message='Limit for this action exceeded'
)
@limiter.limit(
'60/minute', key_func=get_remote_address, error_message='Limit for this action exceeded'
)
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])
Copy link
Member

@mrsaicharan1 mrsaicharan1 Jul 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that attachments should be empty for placed orders as they're meant for offline tickets?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think placed orders should have tickets too. They are meant to show this ticket when they reach event venue

Copy link
Member

@mrsaicharan1 mrsaicharan1 Jul 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think placed orders should have tickets too. They are meant to show this ticket when they reach event venue

Agreed 👍

return jsonify(status=True, message="Verification emails for order : {} has been sent succesfully".
format(order_identifier))
else:
return UnprocessableEntityError({'source': 'data/order'},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it returning instead of raising?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iamareebjamal because these errors are actually a subclass of ErrorResponse and not actual errors. To make them work we need to initiate their respond function (the same error classes have been used all through this file)

"Only placed and completed orders have confirmation").respond()
else:
return ForbiddenError({'source': ''}, "Co-Organizer Access Required").respond()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same