Skip to content

Commit 9d8a848

Browse files
prateekj117iamareebjamal
authored andcommitted
fix: Check user permission before exporting (#6581)
1 parent e9b879a commit 9d8a848

File tree

2 files changed

+91
-116
lines changed

2 files changed

+91
-116
lines changed

app/api/exports.py

Lines changed: 62 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22

33
from flask import send_file, make_response, jsonify, url_for, \
44
current_app, request, Blueprint
5-
from flask_jwt_extended import jwt_required, current_user
5+
from flask_jwt_extended import current_user
66

77
from app.api.helpers.export_helpers import export_event_json, create_export_job
8+
from app.api.helpers.permissions import is_coorganizer, to_event_id
89
from app.api.helpers.utilities import TASK_RESULTS
9-
from app.models import db
10-
from app.models.event import Event
1110

1211
export_routes = Blueprint('exports', __name__, url_prefix='/v1')
1312

@@ -19,9 +18,10 @@
1918
}
2019

2120

22-
@export_routes.route('/events/<string:event_identifier>/export/json', methods=['POST'])
23-
@jwt_required
24-
def export_event(event_identifier):
21+
@export_routes.route('/events/<string:event_identifier>/export/json', methods=['POST'], endpoint='export_event')
22+
@to_event_id
23+
@is_coorganizer
24+
def export_event(event_id):
2525
from .helpers.tasks import export_event_task
2626

2727
settings = EXPORT_SETTING
@@ -30,11 +30,6 @@ def export_event(event_identifier):
3030
settings['document'] = request.json.get('document', False)
3131
settings['audio'] = request.json.get('audio', False)
3232

33-
if not event_identifier.isdigit():
34-
event = db.session.query(Event).filter_by(identifier=event_identifier).first()
35-
event_id = event.id
36-
else:
37-
event_id = event_identifier
3833
# queue task
3934
task = export_event_task.delay(
4035
current_user.email, event_id, settings)
@@ -53,8 +48,9 @@ def export_event(event_identifier):
5348
)
5449

5550

56-
@export_routes.route('/events/<string:event_id>/exports/<path:path>')
57-
@jwt_required
51+
@export_routes.route('/events/<string:event_id>/exports/<path:path>', endpoint='export_download')
52+
@to_event_id
53+
@is_coorganizer
5854
def export_download(event_id, path):
5955
if not path.startswith('/'):
6056
path = '/' + path
@@ -65,15 +61,10 @@ def export_download(event_id, path):
6561
return response
6662

6763

68-
@export_routes.route('/events/<string:event_identifier>/export/xcal', methods=['GET'])
69-
@jwt_required
70-
def export_event_xcal(event_identifier):
71-
72-
if not event_identifier.isdigit():
73-
event = db.session.query(Event).filter_by(identifier=event_identifier).first()
74-
event_id = str(event.id)
75-
else:
76-
event_id = event_identifier
64+
@export_routes.route('/events/<string:event_identifier>/export/xcal', methods=['GET'], endpoint='export_event_xcal')
65+
@to_event_id
66+
@is_coorganizer
67+
def export_event_xcal(event_id):
7768

7869
from .helpers.tasks import export_xcal_task
7970

@@ -94,15 +85,10 @@ def event_export_task_base(event_id, settings):
9485
return path
9586

9687

97-
@export_routes.route('/events/<string:event_identifier>/export/ical', methods=['GET'])
98-
@jwt_required
99-
def export_event_ical(event_identifier):
100-
if not event_identifier.isdigit():
101-
event = db.session.query(Event).filter_by(identifier=event_identifier).first()
102-
event_id = str(event.id)
103-
else:
104-
event_id = event_identifier
105-
88+
@export_routes.route('/events/<string:event_identifier>/export/ical', methods=['GET'], endpoint='export_event_ical')
89+
@to_event_id
90+
@is_coorganizer
91+
def export_event_ical(event_id):
10692
from .helpers.tasks import export_ical_task
10793

10894
task = export_ical_task.delay(event_id)
@@ -114,15 +100,11 @@ def export_event_ical(event_identifier):
114100
)
115101

116102

117-
@export_routes.route('/events/<string:event_identifier>/export/pentabarf', methods=['GET'])
118-
@jwt_required
119-
def export_event_pentabarf(event_identifier):
120-
if not event_identifier.isdigit():
121-
event = db.session.query(Event).filter_by(identifier=event_identifier).first()
122-
event_id = str(event.id)
123-
else:
124-
event_id = event_identifier
125-
103+
@export_routes.route('/events/<string:event_identifier>/export/pentabarf', methods=['GET'],
104+
endpoint='export_event_pentabarf')
105+
@to_event_id
106+
@is_coorganizer
107+
def export_event_pentabarf(event_id):
126108
from .helpers.tasks import export_pentabarf_task
127109

128110
task = export_pentabarf_task.delay(event_id)
@@ -134,15 +116,11 @@ def export_event_pentabarf(event_identifier):
134116
)
135117

136118

137-
@export_routes.route('/events/<string:event_identifier>/export/orders/csv', methods=['GET'])
138-
@jwt_required
139-
def export_orders_csv(event_identifier):
140-
if not event_identifier.isdigit():
141-
event = db.session.query(Event).filter_by(identifier=event_identifier).first()
142-
event_id = str(event.id)
143-
else:
144-
event_id = event_identifier
145-
119+
@export_routes.route('/events/<string:event_identifier>/export/orders/csv', methods=['GET'],
120+
endpoint='export_orders_csv')
121+
@to_event_id
122+
@is_coorganizer
123+
def export_orders_csv(event_id):
146124
from .helpers.tasks import export_order_csv_task
147125

148126
task = export_order_csv_task.delay(event_id)
@@ -154,15 +132,11 @@ def export_orders_csv(event_identifier):
154132
)
155133

156134

157-
@export_routes.route('/events/<string:event_identifier>/export/orders/pdf', methods=['GET'])
158-
@jwt_required
159-
def export_orders_pdf(event_identifier):
160-
if not event_identifier.isdigit():
161-
event = db.session.query(Event).filter_by(identifier=event_identifier).first()
162-
event_id = str(event.id)
163-
else:
164-
event_id = event_identifier
165-
135+
@export_routes.route('/events/<string:event_identifier>/export/orders/pdf', methods=['GET'],
136+
endpoint='export_orders_pdf')
137+
@to_event_id
138+
@is_coorganizer
139+
def export_orders_pdf(event_id):
166140
from .helpers.tasks import export_order_pdf_task
167141

168142
task = export_order_pdf_task.delay(event_id)
@@ -174,15 +148,11 @@ def export_orders_pdf(event_identifier):
174148
)
175149

176150

177-
@export_routes.route('/events/<string:event_identifier>/export/attendees/csv', methods=['GET'])
178-
@jwt_required
179-
def export_attendees_csv(event_identifier):
180-
if not event_identifier.isdigit():
181-
event = db.session.query(Event).filter_by(identifier=event_identifier).first()
182-
event_id = str(event.id)
183-
else:
184-
event_id = event_identifier
185-
151+
@export_routes.route('/events/<string:event_identifier>/export/attendees/csv', methods=['GET'],
152+
endpoint='export_attendees_csv')
153+
@to_event_id
154+
@is_coorganizer
155+
def export_attendees_csv(event_id):
186156
from .helpers.tasks import export_attendees_csv_task
187157

188158
task = export_attendees_csv_task.delay(event_id)
@@ -194,15 +164,11 @@ def export_attendees_csv(event_identifier):
194164
)
195165

196166

197-
@export_routes.route('/events/<string:event_identifier>/export/attendees/pdf', methods=['GET'])
198-
@jwt_required
199-
def export_attendees_pdf(event_identifier):
200-
if not event_identifier.isdigit():
201-
event = db.session.query(Event).filter_by(identifier=event_identifier).first()
202-
event_id = str(event.id)
203-
else:
204-
event_id = event_identifier
205-
167+
@export_routes.route('/events/<string:event_identifier>/export/attendees/pdf', methods=['GET'],
168+
endpoint='export_attendees_pdf')
169+
@to_event_id
170+
@is_coorganizer
171+
def export_attendees_pdf(event_id):
206172
from .helpers.tasks import export_attendees_pdf_task
207173

208174
task = export_attendees_pdf_task.delay(event_id)
@@ -214,15 +180,11 @@ def export_attendees_pdf(event_identifier):
214180
)
215181

216182

217-
@export_routes.route('/events/<string:event_identifier>/export/sessions/csv', methods=['GET'])
218-
@jwt_required
219-
def export_sessions_csv(event_identifier):
220-
if not event_identifier.isdigit():
221-
event = db.session.query(Event).filter_by(identifier=event_identifier).first()
222-
event_id = str(event.id)
223-
else:
224-
event_id = event_identifier
225-
183+
@export_routes.route('/events/<string:event_identifier>/export/sessions/csv', methods=['GET'],
184+
endpoint='export_sessions_csv')
185+
@to_event_id
186+
@is_coorganizer
187+
def export_sessions_csv(event_id):
226188
from .helpers.tasks import export_sessions_csv_task
227189

228190
task = export_sessions_csv_task.delay(event_id)
@@ -234,15 +196,11 @@ def export_sessions_csv(event_identifier):
234196
)
235197

236198

237-
@export_routes.route('/events/<string:event_identifier>/export/speakers/csv', methods=['GET'])
238-
@jwt_required
239-
def export_speakers_csv(event_identifier):
240-
if not event_identifier.isdigit():
241-
event = db.session.query(Event).filter_by(identifier=event_identifier).first()
242-
event_id = str(event.id)
243-
else:
244-
event_id = event_identifier
245-
199+
@export_routes.route('/events/<string:event_identifier>/export/speakers/csv', methods=['GET'],
200+
endpoint='export_speakers_csv')
201+
@to_event_id
202+
@is_coorganizer
203+
def export_speakers_csv(event_id):
246204
from .helpers.tasks import export_speakers_csv_task
247205

248206
task = export_speakers_csv_task.delay(event_id)
@@ -254,15 +212,11 @@ def export_speakers_csv(event_identifier):
254212
)
255213

256214

257-
@export_routes.route('/events/<string:event_identifier>/export/sessions/pdf', methods=['GET'])
258-
@jwt_required
259-
def export_sessions_pdf(event_identifier):
260-
if not event_identifier.isdigit():
261-
event = db.session.query(Event).filter_by(identifier=event_identifier).first()
262-
event_id = str(event.id)
263-
else:
264-
event_id = event_identifier
265-
215+
@export_routes.route('/events/<string:event_identifier>/export/sessions/pdf', methods=['GET'],
216+
endpoint='export_sessions_pdf')
217+
@to_event_id
218+
@is_coorganizer
219+
def export_sessions_pdf(event_id):
266220
from .helpers.tasks import export_sessions_pdf_task
267221

268222
task = export_sessions_pdf_task.delay(event_id)
@@ -274,15 +228,11 @@ def export_sessions_pdf(event_identifier):
274228
)
275229

276230

277-
@export_routes.route('/events/<string:event_identifier>/export/speakers/pdf', methods=['GET'])
278-
@jwt_required
279-
def export_speakers_pdf(event_identifier):
280-
if not event_identifier.isdigit():
281-
event = db.session.query(Event).filter_by(identifier=event_identifier).first()
282-
event_id = str(event.id)
283-
else:
284-
event_id = event_identifier
285-
231+
@export_routes.route('/events/<string:event_identifier>/export/speakers/pdf', methods=['GET'],
232+
endpoint='export_speakers_pdf')
233+
@to_event_id
234+
@is_coorganizer
235+
def export_speakers_pdf(event_id):
286236
from .helpers.tasks import export_speakers_pdf_task
287237

288238
task = export_speakers_pdf_task.delay(event_id)

app/api/helpers/permissions.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from functools import wraps
2-
from flask import current_app as app
32
from flask_jwt_extended import verify_jwt_in_request, current_user
43

54
from app.api.helpers.db import save_to_db
65
from app.api.helpers.errors import ForbiddenError
76
from flask import request
87
from datetime import datetime
8+
from app.models import db
9+
from app.models.event import Event
910

1011

1112
def second_order_decorator(inner_dec):
@@ -145,6 +146,30 @@ def decorated_function(*args, **kwargs):
145146
return decorated_function
146147

147148

149+
@second_order_decorator(jwt_required)
150+
def to_event_id(func):
151+
"""
152+
Change event_identifier to event_id in kwargs
153+
:param f:
154+
:return:
155+
"""
156+
157+
@wraps(func)
158+
def decorated_function(*args, **kwargs):
159+
160+
if 'event_identifier' in kwargs:
161+
if not kwargs['event_identifier'].isdigit():
162+
event = db.session.query(Event).filter_by(identifier=kwargs['event_identifier']).first()
163+
kwargs['event_id'] = event.id
164+
else:
165+
kwargs['event_id'] = kwargs['event_identifier']
166+
167+
return func(*args, **kwargs)
168+
169+
return decorated_function
170+
171+
172+
148173
@second_order_decorator(jwt_required)
149174
def is_coorganizer(f):
150175
"""
@@ -157,9 +182,9 @@ def is_coorganizer(f):
157182
def decorated_function(*args, **kwargs):
158183
user = current_user
159184

160-
if user.is_staff:
161-
return f(*args, **kwargs)
162-
if 'event_id' in kwargs and user.has_event_access(kwargs['event_id']):
185+
if user.is_staff or ('event_id' in kwargs and user.has_event_access(kwargs['event_id'])):
186+
if 'event_identifier' in kwargs:
187+
kwargs.pop('event_identifier', None)
163188
return f(*args, **kwargs)
164189
return ForbiddenError({'source': ''}, 'Co-organizer access is required.').respond()
165190

0 commit comments

Comments
 (0)