Skip to content

Commit 5163c4c

Browse files
chore: Release v1.4.0 (#6257)
chore: Release v1.4.0
2 parents d1ca881 + 78fb877 commit 5163c4c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+694
-492
lines changed

.travis.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
language: python
22

3-
sudo: required
4-
53
services:
64
- docker
75

app/__init__.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from flask_migrate import Migrate, MigrateCommand
1111
from flask_script import Manager
1212
from flask_login import current_user
13-
from flask_jwt import JWT
13+
from flask_jwt_extended import JWTManager
1414
from flask_limiter import Limiter
1515
from datetime import timedelta
1616
from flask_cors import CORS
@@ -26,7 +26,7 @@
2626
import stripe
2727
from app.settings import get_settings
2828
from app.models import db
29-
from app.api.helpers.jwt import jwt_authenticate, jwt_identity
29+
from app.api.helpers.jwt import jwt_user_loader
3030
from app.api.helpers.cache import cache
3131
from werkzeug.middleware.profiler import ProfilerMiddleware
3232
from app.views import BlueprintsManager
@@ -102,10 +102,11 @@ def create_app():
102102
app.logger.setLevel(logging.ERROR)
103103

104104
# set up jwt
105-
app.config['JWT_AUTH_USERNAME_KEY'] = 'email'
106-
app.config['JWT_EXPIRATION_DELTA'] = timedelta(seconds=24 * 60 * 60)
107-
app.config['JWT_AUTH_URL_RULE'] = '/auth/session'
108-
_jwt = JWT(app, jwt_authenticate, jwt_identity)
105+
app.config['JWT_HEADER_TYPE'] = 'JWT'
106+
app.config['JWT_ACCESS_TOKEN_EXPIRES'] = timedelta(days=1)
107+
app.config['JWT_ERROR_MESSAGE_KEY'] = 'error'
108+
_jwt = JWTManager(app)
109+
_jwt.user_loader_callback_loader(jwt_user_loader)
109110

110111
# setup celery
111112
app.config['CELERY_BROKER_URL'] = app.config['REDIS_URL']

app/api/__init__.py

Lines changed: 79 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,90 @@
1+
from app.api.access_codes import AccessCodeList, AccessCodeListPost, AccessCodeDetail, AccessCodeRelationshipRequired, \
2+
AccessCodeRelationshipOptional
3+
from app.api.activities import ActivityList, ActivityDetail
4+
from app.api.admin_sales.discounted import AdminSalesDiscountedList
5+
from app.api.admin_sales.events import AdminSalesByEventsList
6+
from app.api.admin_sales.fees import AdminSalesFeesList
7+
from app.api.admin_sales.invoices import AdminSalesInvoicesList
8+
from app.api.admin_sales.locations import AdminSalesByLocationList
9+
from app.api.admin_sales.marketer import AdminSalesByMarketerList
10+
from app.api.admin_sales.organizer import AdminSalesByOrganizersList
11+
from app.api.admin_statistics_api.events import AdminStatisticsEventDetail
12+
from app.api.admin_statistics_api.mails import AdminStatisticsMailDetail
13+
from app.api.admin_statistics_api.sessions import AdminStatisticsSessionDetail
14+
from app.api.admin_statistics_api.users import AdminStatisticsUserDetail
15+
from app.api.attendees import AttendeeList, AttendeeDetail, AttendeeRelationshipOptional, \
16+
AttendeeRelationshipRequired, AttendeeListPost
117
from app.api.bootstrap import api
2-
from app.api.event_orga import EventOrgaDetail
3-
from app.api.stripe_authorization import StripeAuthorizationDetail, StripeAuthorizationRelationship, \
4-
StripeAuthorizationListPost
5-
from app.api.ticket_fees import TicketFeeList, TicketFeeDetail
6-
from app.api.users import UserList, UserDetail, UserRelationship
7-
from app.api.user_emails import UserEmailListAdmin, UserEmailListPost, UserEmailList, UserEmailDetail, \
8-
UserEmailRelationship
9-
from app.api.user_favourite_events import UserFavouriteEventListPost, UserFavouriteEventList, \
10-
UserFavouriteEventDetail, UserFavouriteEventRelationship
11-
from app.api.notifications import NotificationList, NotificationListAdmin, NotificationDetail,\
12-
NotificationRelationship, NotificationActionDetail, NotificationActionRelationship, NotificationActionList
18+
from app.api.custom_forms import CustomFormList, CustomFormListPost, CustomFormDetail, CustomFormRelationshipRequired
19+
from app.api.custom_placeholders import CustomPlaceholderList, CustomPlaceholderDetail, CustomPlaceholderRelationship
20+
from app.api.custom_system_roles import CustomSystemRoleList, CustomSystemRoleDetail, CustomSystemRoleRelationship
21+
from app.api.discount_codes import DiscountCodeList, DiscountCodeDetail, DiscountCodeRelationshipOptional, \
22+
DiscountCodeRelationshipRequired, DiscountCodeListPost
1323
from app.api.email_notifications import EmailNotificationList, EmailNotificationListAdmin, EmailNotificationDetail, \
1424
EmailNotificationRelationshipOptional, EmailNotificationRelationshipRequired
15-
from app.api.tickets import TicketList, TicketListPost, TicketDetail, TicketRelationshipRequired, \
16-
TicketRelationshipOptional
17-
from app.api.events import EventList, EventDetail, EventRelationship, EventCopyResource
18-
from app.api.event_types import EventTypeList, EventTypeDetail, EventTypeRelationship
25+
from app.api.event_copyright import EventCopyrightListPost, EventCopyrightDetail, EventCopyrightRelationshipRequired
26+
from app.api.event_image_sizes import EventImageSizeDetail
27+
from app.api.event_invoices import EventInvoiceList, EventInvoiceDetail, \
28+
EventInvoiceRelationshipRequired, EventInvoiceRelationshipOptional
1929
from app.api.event_locations import EventLocationList
20-
from app.api.event_topics import EventTopicList, EventTopicDetail, EventTopicRelationship
30+
from app.api.event_orga import EventOrgaDetail
31+
from app.api.event_statistics import EventStatisticsGeneralDetail
2132
from app.api.event_sub_topics import EventSubTopicList, EventSubTopicListPost, EventSubTopicDetail, \
2233
EventSubTopicRelationshipRequired, EventSubTopicRelationshipOptional
34+
from app.api.event_topics import EventTopicList, EventTopicDetail, EventTopicRelationship
35+
from app.api.event_types import EventTypeList, EventTypeDetail, EventTypeRelationship
36+
from app.api.events import EventList, EventDetail, EventRelationship, EventCopyResource
37+
from app.api.events_role_permission import EventsRolePermissionList, EventsRolePermissionDetail, \
38+
EventsRolePermissionRelationship
39+
from app.api.faq_types import FaqTypeList, FaqTypeListPost, FaqTypeDetail, FaqTypeRelationshipOptional, \
40+
FaqTypeRelationshipRequired
41+
from app.api.faqs import FaqListPost, FaqList, FaqDetail, FaqRelationshipRequired, FaqRelationshipOptional
42+
from app.api.feedbacks import FeedbackListPost, FeedbackList, FeedbackDetail, \
43+
FeedbackRelationship
44+
from app.api.full_text_search.events import EventSearchResultList
45+
from app.api.import_jobs import ImportJobList, ImportJobDetail
46+
from app.api.mails import MailList, MailDetail
47+
from app.api.message_settings import MessageSettingsList, MessageSettingsDetail
2348
from app.api.microlocations import MicrolocationList, MicrolocationListPost, MicrolocationDetail, \
2449
MicrolocationRelationshipRequired, MicrolocationRelationshipOptional
50+
from app.api.modules import ModuleDetail
51+
from app.api.notifications import NotificationList, NotificationListAdmin, NotificationDetail, \
52+
NotificationRelationship, NotificationActionDetail, NotificationActionRelationship, NotificationActionList
53+
from app.api.order_statistics.events import OrderStatisticsEventDetail
54+
from app.api.order_statistics.tickets import OrderStatisticsTicketDetail
55+
from app.api.orders import OrdersList, OrderDetail, OrderRelationship, ChargeList, OrdersListPost
56+
from app.api.pages import PageList, PageDetail
57+
from app.api.panel_permissions import PanelPermissionList, PanelPermissionDetail, \
58+
PanelPermissionRelationship
59+
from app.api.role_invites import RoleInviteListPost, RoleInviteList, RoleInviteDetail, RoleInviteRelationship
60+
from app.api.roles import RoleList, RoleDetail
61+
from app.api.service import ServiceList, ServiceDetail
62+
from app.api.session_types import SessionTypeList, SessionTypeListPost, SessionTypeDetail, \
63+
SessionTypeRelationshipRequired, SessionTypeRelationshipOptional
2564
from app.api.sessions import SessionList, SessionListPost, SessionDetail, SessionRelationshipRequired, \
2665
SessionRelationshipOptional
66+
from app.api.settings import SettingDetail
67+
from app.api.social_links import SocialLinkList, SocialLinkListPost, SocialLinkDetail, SocialLinkRelationship
68+
from app.api.speaker_image_sizes import SpeakerImageSizeDetail
2769
from app.api.speakers import SpeakerList, SpeakerListPost, SpeakerDetail, SpeakerRelationshipRequired, \
2870
SpeakerRelationshipOptional
29-
from app.api.service import ServiceList, ServiceDetail
30-
from app.api.social_links import SocialLinkList, SocialLinkListPost, SocialLinkDetail, SocialLinkRelationship
31-
from app.api.sponsors import SponsorList, SponsorListPost, SponsorDetail, SponsorRelationship
32-
from app.api.tracks import TrackList, TrackListPost, TrackDetail, TrackRelationshipOptional, TrackRelationshipRequired
3371
from app.api.speakers_calls import SpeakersCallList, SpeakersCallDetail, SpeakersCallRelationship
34-
from app.api.event_invoices import EventInvoiceList, EventInvoiceDetail, \
35-
EventInvoiceRelationshipRequired, EventInvoiceRelationshipOptional
36-
from app.api.role_invites import RoleInviteListPost, RoleInviteList, RoleInviteDetail, RoleInviteRelationship
37-
from app.api.event_image_sizes import EventImageSizeDetail
38-
from app.api.speaker_image_sizes import SpeakerImageSizeDetail
39-
from app.api.roles import RoleList, RoleDetail
40-
from app.api.custom_system_roles import CustomSystemRoleList, CustomSystemRoleDetail, CustomSystemRoleRelationship
41-
from app.api.session_types import SessionTypeList, SessionTypeListPost, SessionTypeDetail, \
42-
SessionTypeRelationshipRequired, SessionTypeRelationshipOptional
43-
from app.api.event_copyright import EventCopyrightListPost, EventCopyrightDetail, EventCopyrightRelationshipRequired
44-
from app.api.pages import PageList, PageDetail
45-
from app.api.user_permission import UserPermissionList, UserPermissionDetail
46-
from app.api.events_role_permission import EventsRolePermissionList, EventsRolePermissionDetail, \
47-
EventsRolePermissionRelationship
48-
from app.api.panel_permissions import PanelPermissionList, PanelPermissionDetail, \
49-
PanelPermissionRelationship
50-
from app.api.message_settings import MessageSettingsList, MessageSettingsDetail
72+
from app.api.sponsors import SponsorList, SponsorListPost, SponsorDetail, SponsorRelationship
73+
from app.api.stripe_authorization import StripeAuthorizationDetail, StripeAuthorizationRelationship, \
74+
StripeAuthorizationListPost
5175
from app.api.tax import TaxList, TaxDetail, TaxRelationship
52-
from app.api.settings import SettingDetail
53-
from app.api.discount_codes import DiscountCodeList, DiscountCodeDetail, DiscountCodeRelationshipOptional, \
54-
DiscountCodeRelationshipRequired, DiscountCodeListPost
76+
from app.api.ticket_fees import TicketFeeList, TicketFeeDetail
5577
from app.api.ticket_tags import TicketTagList, TicketTagListPost, TicketTagDetail, TicketTagRelationshipOptional, \
5678
TicketTagRelationshipRequired
57-
from app.api.attendees import AttendeeList, AttendeeDetail, AttendeeRelationshipOptional, \
58-
AttendeeRelationshipRequired, AttendeeListPost
59-
from app.api.access_codes import AccessCodeList, AccessCodeListPost, AccessCodeDetail, AccessCodeRelationshipRequired, \
60-
AccessCodeRelationshipOptional
61-
from app.api.custom_forms import CustomFormList, CustomFormListPost, CustomFormDetail, CustomFormRelationshipRequired
62-
from app.api.faqs import FaqListPost, FaqList, FaqDetail, FaqRelationshipRequired, FaqRelationshipOptional
63-
from app.api.feedbacks import FeedbackListPost, FeedbackList, FeedbackDetail, \
64-
FeedbackRelationship
65-
from app.api.modules import ModuleDetail
66-
from app.api.custom_placeholders import CustomPlaceholderList, CustomPlaceholderDetail, CustomPlaceholderRelationship
67-
from app.api.activities import ActivityList, ActivityDetail
68-
from app.api.orders import OrdersList, OrderDetail, OrderRelationship, ChargeList, OrdersListPost
69-
from app.api.event_statistics import EventStatisticsGeneralDetail
70-
from app.api.mails import MailList, MailDetail
71-
from app.api.admin_statistics_api.sessions import AdminStatisticsSessionDetail
72-
from app.api.admin_statistics_api.events import AdminStatisticsEventDetail
73-
from app.api.admin_statistics_api.users import AdminStatisticsUserDetail
74-
from app.api.admin_statistics_api.mails import AdminStatisticsMailDetail
75-
from app.api.order_statistics.events import OrderStatisticsEventDetail
76-
from app.api.order_statistics.tickets import OrderStatisticsTicketDetail
77-
from app.api.faq_types import FaqTypeList, FaqTypeListPost, FaqTypeDetail, FaqTypeRelationshipOptional, \
78-
FaqTypeRelationshipRequired
79-
from app.api.admin_sales.events import AdminSalesByEventsList
80-
from app.api.admin_sales.organizer import AdminSalesByOrganizersList
81-
from app.api.admin_sales.locations import AdminSalesByLocationList
82-
from app.api.admin_sales.marketer import AdminSalesByMarketerList
83-
from app.api.admin_sales.discounted import AdminSalesDiscountedList
84-
from app.api.admin_sales.fees import AdminSalesFeesList
85-
from app.api.admin_sales.invoices import AdminSalesInvoicesList
86-
from app.api.full_text_search.events import EventSearchResultList
87-
from app.api.import_jobs import ImportJobList, ImportJobDetail
79+
from app.api.tickets import TicketList, TicketListPost, TicketDetail, TicketRelationshipRequired, \
80+
TicketRelationshipOptional
81+
from app.api.tracks import TrackList, TrackListPost, TrackDetail, TrackRelationshipOptional, TrackRelationshipRequired
82+
from app.api.user_emails import UserEmailListAdmin, UserEmailListPost, UserEmailList, UserEmailDetail, \
83+
UserEmailRelationship
84+
from app.api.user_favourite_events import UserFavouriteEventListPost, UserFavouriteEventList, \
85+
UserFavouriteEventDetail, UserFavouriteEventRelationship
86+
from app.api.user_permission import UserPermissionList, UserPermissionDetail
87+
from app.api.users import UserList, UserDetail, UserRelationship
8888

8989
# users
9090
api.route(UserList, 'user_list', '/users')
@@ -462,6 +462,8 @@
462462
'/event-invoices/<int:id>/relationships/user')
463463
api.route(EventInvoiceRelationshipRequired, 'event_invoice_event',
464464
'/event-invoices/<int:id>/relationships/event')
465+
api.route(EventInvoiceRelationshipRequired, 'event_invoice_order',
466+
'/event-invoices/<int:id>/relationships/order')
465467
api.route(EventInvoiceRelationshipOptional, 'event_invoice_discount_code',
466468
'/event-invoices/<int:id>/relationships/discount-code')
467469

@@ -472,7 +474,8 @@
472474
'/tickets/<int:ticket_id>/discount-codes')
473475
api.route(DiscountCodeDetail, 'discount_code_detail', '/discount-codes/<int:id>',
474476
'/events/<int:event_id>/discount-code', '/event-invoices/<int:event_invoice_id>/discount-code',
475-
'/discount-codes/<code>')
477+
'/events/<int:discount_event_id>/discount-codes/<code>',
478+
'/events/<discount_event_identifier>/discount-codes/<code>')
476479
api.route(DiscountCodeRelationshipRequired, 'discount_code_event',
477480
'/discount-codes/<int:id>/relationships/event')
478481
api.route(DiscountCodeRelationshipOptional, 'discount_code_events',
@@ -539,7 +542,9 @@
539542
api.route(AccessCodeList, 'access_code_list', '/events/<int:event_id>/access-codes',
540543
'/events/<event_identifier>/access-codes', '/users/<int:user_id>/access-codes',
541544
'/tickets/<int:ticket_id>/access-codes')
542-
api.route(AccessCodeDetail, 'access_code_detail', '/access-codes/<int:id>', '/access-codes/<code>')
545+
api.route(AccessCodeDetail, 'access_code_detail', '/access-codes/<int:id>',
546+
'/events/<int:access_event_id>/access-codes/<code>',
547+
'/events/<int:access_event_identifier>/access-codes/<code>',)
543548
api.route(AccessCodeRelationshipRequired, 'access_code_event',
544549
'/access-codes/<int:id>/relationships/event')
545550
api.route(AccessCodeRelationshipOptional, 'access_code_user',
@@ -600,6 +605,7 @@
600605
api.route(OrderRelationship, 'order_event', '/orders/<order_identifier>/relationships/event')
601606
api.route(OrderRelationship, 'order_marketer', '/orders/<order_identifier>/relationships/marketer')
602607
api.route(OrderRelationship, 'order_discount', '/orders/<order_identifier>/relationships/discount-code')
608+
api.route(OrderRelationship, 'order_event_invoice', '/orders/<order_identifier>/relationships/event-invoice/')
603609

604610
# Event Statistics API
605611
api.route(EventStatisticsGeneralDetail, 'event_statistics_general_detail', '/events/<int:id>/general-statistics',

app/api/access_codes.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from app.models.access_code import AccessCode
1616
from app.models.ticket import Ticket
1717
from app.models.user import User
18+
from app.models.event import Event
1819

1920

2021
class AccessCodeListPost(ResourceList):
@@ -110,9 +111,16 @@ def before_get(self, args, kwargs):
110111
:param kwargs:
111112
:return:
112113
"""
113-
# Any registered user can fetch access code details using the code.
114-
if kwargs.get('code'):
115-
access = db.session.query(AccessCode).filter_by(code=kwargs.get('code')).first()
114+
# Any user can fetch access code details using the code.
115+
116+
if kwargs.get('access_event_identifier'):
117+
event = safe_query(
118+
db, Event, 'identifier', kwargs['discount_event_identifier'],
119+
'event_identifier')
120+
kwargs['access_event_id'] = event.id
121+
if kwargs.get('code') and kwargs.get('access_event_id'):
122+
access = db.session.query(AccessCode).filter_by(code=kwargs.get('code'),
123+
event_id=kwargs.get('access_event_id')).first()
116124
if access:
117125
kwargs['id'] = access.id
118126
else:

app/api/admin_statistics_api/events.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from flask_rest_jsonapi import ResourceDetail
22
from flask import jsonify, Blueprint
3-
from flask_jwt import jwt_required
3+
from flask_jwt_extended import jwt_required
44
from sqlalchemy.sql import text
55

66
from app.api.bootstrap import api
@@ -12,7 +12,7 @@
1212

1313

1414
@event_statistics.route('/event-topics', methods=['GET'])
15-
@jwt_required()
15+
@jwt_required
1616
def event_topic_count():
1717
result_set = db.engine.execute(text(
1818
"SELECT event_topics.name AS name, event_topics.id AS id, " +
@@ -25,7 +25,7 @@ def event_topic_count():
2525

2626

2727
@event_statistics.route('/event-types', methods=['GET'])
28-
@jwt_required()
28+
@jwt_required
2929
def event_types_count():
3030
result_set = db.engine.execute(text(
3131
"SELECT event_types.name AS name, event_types.id AS id, " +

app/api/attendees.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from datetime import datetime
22

33
from flask import Blueprint, request, jsonify, abort, make_response
4-
from flask_jwt import current_identity, jwt_required
4+
from flask_jwt_extended import current_user
55
from flask_rest_jsonapi import ResourceDetail, ResourceList, ResourceRelationship
66
from flask_rest_jsonapi.exceptions import ObjectNotFound
77
from sqlalchemy.orm.exc import NoResultFound
@@ -146,7 +146,7 @@ def before_get_object(self, view_kwargs):
146146
:return:
147147
"""
148148
attendee = safe_query(self, TicketHolder, 'id', view_kwargs['id'], 'attendee_id')
149-
if not has_access('is_registrar_or_user_itself', user_id=current_identity.id, event_id=attendee.event_id):
149+
if not has_access('is_registrar_or_user_itself', user_id=current_user.id, event_id=attendee.event_id):
150150
raise ForbiddenException({'source': 'User'}, 'You are not authorized to access this.')
151151

152152
def before_delete_object(self, obj, kwargs):
@@ -171,10 +171,10 @@ def before_update_object(self, obj, data, kwargs):
171171
# raise ForbiddenException({'source': 'User'}, 'You are not authorized to access this.')
172172

173173
if 'ticket' in data:
174-
user = safe_query(self, User, 'id', current_identity.id, 'user_id')
174+
user = safe_query(self, User, 'id', current_user.id, 'user_id')
175175
ticket = db.session.query(Ticket).filter_by(
176176
id=int(data['ticket']), deleted_at=None
177-
).first()
177+
).first()
178178
if ticket is None:
179179
raise UnprocessableEntity(
180180
{'pointer': '/data/relationships/ticket'}, "Invalid Ticket"
@@ -278,7 +278,7 @@ def send_receipt():
278278
except NoResultFound:
279279
raise ObjectNotFound({'parameter': '{identifier}'}, "Order not found")
280280

281-
if (order.user_id != current_identity.id) and (not has_access('is_registrar', event_id=order.event_id)):
281+
if (order.user_id != current_user.id) and (not has_access('is_registrar', event_id=order.event_id)):
282282
abort(
283283
make_response(jsonify(error="You need to be the event organizer or order buyer to send receipts."), 403)
284284
)
@@ -287,7 +287,7 @@ def send_receipt():
287287
make_response(jsonify(error="Cannot send receipt for an incomplete order"), 409)
288288
)
289289
else:
290-
send_email_to_attendees(order, current_identity.id)
290+
send_email_to_attendees(order, current_user.id)
291291
return jsonify(message="receipt sent to attendees")
292292
else:
293293
abort(

0 commit comments

Comments
 (0)