11import json
22import traceback
33import datetime
4+ import secrets
45
56from algoliasearch import algoliasearch
67from flask import Blueprint , jsonify , abort , request
@@ -152,8 +153,10 @@ def submit_new_app():
152153 ), 400
153154
154155 app_is_timeline_enabled = False
156+ timeline_token = None
155157 if 'timeline_enabled' in params and params ['timeline_enabled' ] == 'true' :
156158 app_is_timeline_enabled = True
159+ timeline_token = secrets .token_urlsafe (32 )
157160
158161 # Remove any platforms with no screenshots
159162 screenshots = {k : v for k , v in screenshots .items () if v }
@@ -179,6 +182,7 @@ def submit_new_app():
179182 title = params ['title' ],
180183 type = params ['type' ],
181184 timeline_enabled = app_is_timeline_enabled ,
185+ timeline_token = timeline_token ,
182186 website = params ['website' ] if 'website' in params else "" ,
183187 )
184188 db .session .add (app_obj )
@@ -218,12 +222,14 @@ def update_app_fields(app_id):
218222 "category" : str ,
219223 "website" : str ,
220224 "source" : str ,
221- "visible" : bool
225+ "visible" : bool ,
226+ "timeline_enabled" : bool ,
227+ "timeline_token" : None
222228 }
223229
224230 # Check all valid passed fields are correct type
225231 for x in req :
226- if (x in allowed_fields_type_map ) and (not type (x ) == allowed_fields_type_map [x ]):
232+ if (x in allowed_fields_type_map ) and (not type (req [ x ] ) == allowed_fields_type_map [x ]):
227233 return jsonify (error = f"Invalid value for field '{ x } '" , e = f"invalid.field.{ x } " ), 400
228234
229235
@@ -240,8 +246,6 @@ def update_app_fields(app_id):
240246 # Check any enum fields
241247 if "category" in req and not is_valid_category (req ["category" ]):
242248 return jsonify (error = "Invalid value for field: category" , e = "invalid.field.category" ), 400
243- if "visible" in req and not (req ["visible" ].lower () == "true" or req ["visible" ].lower () == "false" ):
244- return jsonify (error = "Invalid value for field: visible" , e = "invalid.field.visible" ), 400
245249
246250 # Disallow change face category
247251 if "category" in req and app .category == "Faces" :
@@ -250,7 +254,14 @@ def update_app_fields(app_id):
250254 # Check title length
251255 if "title" in req and len (req ["title" ]) > 45 :
252256 return jsonify (error = "Title must be less than 45 characters" , e = "invalid.field.title" ), 400
253-
257+
258+ # Create a timeline token when enabling the timeline
259+ if "timeline_enabled" in req :
260+ if not req ["timeline_enabled" ]:
261+ req ["timeline_token" ] = None
262+ elif app .timeline_token == None :
263+ req ["timeline_token" ] = secrets .token_urlsafe (32 )
264+
254265 # Update the app
255266 for x in req :
256267 setattr (app , x , req [x ])
@@ -332,7 +343,25 @@ def submit_new_release(app_id):
332343 print ("Discord is being weird" )
333344
334345 return jsonify (success = True )
335-
346+
347+ @devportal_api .route ('/app/<app_id>/timeline_token' )
348+ def apps_timeline_token (app_id ):
349+ try :
350+ app = App .query .filter (App .id == app_id ).one ()
351+ except NoResultFound :
352+ abort (404 )
353+ return
354+
355+ # Check we own the app
356+ if not is_users_developer_id (app .developer_id ):
357+ return jsonify (error = "You do not have permission to access the token" , e = "permission.denied" ), 403
358+
359+ result = {
360+ "timeline_token" : app .timeline_token
361+ }
362+
363+ return jsonify (result )
364+
336365# Screenshots
337366@devportal_api .route ('/app/<app_id>/screenshots' )
338367def missing_platform (app_id ):
0 commit comments