def build_installers(self, vessel_list, user_data=None): """ <Purpose> Allows XML-RPC clients to build installers. <Arguments> vessels: A list of vessels, each represented by a dictonary. The dictionary should contain 'percentage', 'owner', and (optionally) 'users' entries. platforms: A list of platforms for which to build the installers, such as 'linux', 'mac', or 'windows'. user_data: An optional dictionary with user names as keys, and sub-dictionaries as values. The sub-dictionaries may contain a 'public_key' entry. <Exceptions> ValidationError if malformed data was passed. <Side Effects> Creates the desired installers and writes them to disk. <Returns> A dictionary which contains the build ID, URLs pointing to the newly built installers, and a dictionary of user cryptographic keys. """ manager = BuildManager(vessel_list, user_data) return manager.prepare()
def build_installers(request): """ <Purpose> Uses the build data from the user's session to build the installers and cryptogrpahic key packages. Designed for AJAX use. <Arguments> request: A Django request. <Exceptions> None. <Side Effects> The created packages will be written to the appropriate location on disk. <Returns> A Django response with text indicating success or error. """ if 'build_string' not in request.session: return ErrorReponse('No build data provided.') build_data = json.loads(request.session['build_string']) user_data = {} for user in build_data['users']: user_data[user['name']] = {'public_key': user['public_key']} try: manager = BuildManager(vessel_list=build_data['vessels'], user_data=user_data) build_results = manager.prepare() except validations.ValidationError, e: return ErrorResponse(e.message)
def get_urls(self, build_id): """ <Purpose> Allows XML-RPC clients request the URLs for builds other than their own. <Arguments> build_id: The build ID of a previously generated custom installer. <Exceptions> ValidationError if improper build_id is passed. <Side Effects> None. <Returns> A dictionary which contains URLs pointing to the installers, and a dictionary of user cryptographic keys. """ validations.validate_build_id(build_id) manager = BuildManager(build_id=build_id) if not os.path.isdir(manager.get_build_directory()): raise validations.ValidationError('Given build ID does not exist.') return manager.get_urls()
def download_installers_page(request, build_id): """ <Purpose> Renders the installer package download page. <Arguments> request: A Django request. build_id: The build ID of the results to display. <Exceptions> None. <Side Effects> None. <Returns> A Django response. """ manager = BuildManager(build_id=build_id) # Invalid build IDs should results in an error. if not os.path.isdir(manager.get_build_directory()): raise Http404 # Compile the list of links of where to find the installers and cryptographic # key archives. installer_links = manager.get_urls() # If there is a query string appended to the current URL, we don't want that # in the share-this-URL box. share_url = request.build_absolute_uri().split('?')[0] # Only show the progress bar if the user has built this installer himself. # Otherwise, we assume the user has shared this link with a friend. step = None user_built = False if 'build_results' in request.session: if build_id in request.session['build_results']: step = 'installers' user_built = True # If we serve a fast_lane_build we don't show the breadcrumbs if 'fast_lane_build' in request.session['build_results'][build_id]: step = False return render(request, 'download_installers.html', { 'build_id': build_id, 'installers': installer_links, 'share_url': share_url, 'step': step, 'user_built': user_built, })
def build_installers(request): """ <Purpose> Uses the build data from the user's session to build the installers and cryptogrpahic key packages. Designed for AJAX use. <Arguments> request: A Django request. <Exceptions> None. <Side Effects> The created packages will be written to the appropriate location on disk. <Returns> A Django response with text indicating success or error. """ if 'build_string' not in request.session: return ErrorReponse('No build data provided.') build_data = json.loads(request.session['build_string']) user_data = {} for user in build_data['users']: user_data[user['name']] = {'public_key': user['public_key']} try: manager = BuildManager(vessel_list=build_data['vessels'], user_data=user_data) build_results = manager.prepare() except validations.ValidationError as e: return ErrorResponse(e) except: log_exception(request) return ErrorResponse( 'Unknown error occured while trying to build the installers.') else: # Save the build results so that the download pages can access the information. build_id = build_results['build_id'] if 'build_results' in request.session: request.session['build_results'][build_id] = build_results request.session.save() else: request.session['build_results'] = {build_id: build_results} return TextResponse( reverse('download-keys-page', kwargs={'build_id': manager.build_id}))
def download_installers_page(request, build_id): """ <Purpose> Renders the installer package download page. <Arguments> request: A Django request. build_id: The build ID of the results to display. <Exceptions> None. <Side Effects> None. <Returns> A Django response. """ manager = BuildManager(build_id=build_id) # Invalid build IDs should results in an error. if not os.path.isdir(manager.get_build_directory()): raise Http404 # Compile the list of links of where to find the installers and cryptographic # key archives. installer_links = manager.get_urls() # If there is a query string appended to the current URL, we don't want that # in the share-this-URL box. share_url = request.build_absolute_uri().split('?')[0] # Only show the progress bar if the user has built this installer himself. # Otherwise, we assume the user has shared this link with a friend. step = None user_built = False if 'build_results' in request.session: if build_id in request.session['build_results']: step = 'installers' user_built = True # If we serve a fast_lane_build we don't show the breadcrumbs if 'fast_lane_build' in request.session['build_results'][build_id]: step = False return render( request, 'download_installers.html', { 'build_id': build_id, 'installers': installer_links, 'share_url': share_url, 'step': step, 'user_built': user_built, })
def build_installers(request): """ <Purpose> Uses the build data from the user's session to build the installers and cryptogrpahic key packages. Designed for AJAX use. <Arguments> request: A Django request. <Exceptions> None. <Side Effects> The created packages will be written to the appropriate location on disk. <Returns> A Django response with text indicating success or error. """ if 'build_string' not in request.session: return ErrorReponse('No build data provided.') build_data = json.loads(request.session['build_string']) user_data = {} for user in build_data['users']: user_data[user['name']] = {'public_key': user['public_key']} try: manager = BuildManager(vessel_list=build_data['vessels'], user_data=user_data) build_results = manager.prepare() except validations.ValidationError as e: return ErrorResponse(e) except: log_exception(request) return ErrorResponse('Unknown error occured while trying to build the installers.') else: # Save the build results so that the download pages can access the information. build_id = build_results['build_id'] if 'build_results' in request.session: request.session['build_results'][build_id] = build_results request.session.save() else: request.session['build_results'] = {build_id: build_results} return TextResponse(reverse('download-keys-page', kwargs={'build_id': manager.build_id}))
def download_keys(request, build_id, key_type): """ <Purpose> Initiates a download of a key bundle. <Arguments> request: A Django request. build_id: The build ID of the file to download. key_type: The type of key bundle to return ('public' or 'private'). <Exceptions> None. <Side Effects> None. <Returns> A Django response which initiates a download through a redirect. """ manager = BuildManager(build_id=build_id) # Invalid build IDs should results in an error. if not os.path.isdir(manager.get_build_directory()): raise Http404 key_filenames = packager.package_keys( request.session['build_results'][build_id]['users']) # Generally, it is undesirable to serve files directly through django, but # the key bundles should be very small and still download quickly. bundle_filename = key_filenames[key_type] # FileResponse is a subclass of StreamingHttpResponse optimized # for binary files requires Django >1.8 response = FileResponse(open(bundle_filename), content_type='application/zip') response['Content-Disposition'] = 'attachment; filename=' + os.path.split( bundle_filename)[1] response['Content-Length'] = os.path.getsize(bundle_filename) # The HTML form will not give access to the installers until the user has # downloaded the private keys. keys_downloaded = request.session['build_results'][build_id].get( 'keys_downloaded', dict()) keys_downloaded[key_type] = True request.session['build_results'][build_id][ 'keys_downloaded'] = keys_downloaded request.session.save() return response
def download_installer(request, build_id, platform): """ <Purpose> Initiates a download of an installer. <Arguments> request: A Django request. build_id: The build ID of the file to download. platform: The platform for which to build the installer. <Exceptions> None. <Side Effects> None. <Returns> A Django response which initiates a download through a redirect. """ manager = BuildManager(build_id=build_id) # Invalid build IDs should results in an error. if not os.path.isdir(manager.get_build_directory()): raise Http404 if not manager.installer_exists(platform): manager.package(platform) installer_url = manager.get_static_urls()[platform] return HttpResponseRedirect(installer_url)
def download_keys(request, build_id, key_type): """ <Purpose> Initiates a download of a key bundle. <Arguments> request: A Django request. build_id: The build ID of the file to download. key_type: The type of key bundle to return ('public' or 'private'). <Exceptions> None. <Side Effects> None. <Returns> A Django response which initiates a download through a redirect. """ manager = BuildManager(build_id=build_id) # Invalid build IDs should results in an error. if not os.path.isdir(manager.get_build_directory()): raise Http404 key_filenames = packager.package_keys(request.session['build_results'][build_id]['users']) # Generally, it is undesirable to serve files directly through django, but # the key bundles should be very small and still download quickly. bundle_filename = key_filenames[key_type] # FileResponse is a subclass of StreamingHttpResponse optimized # for binary files requires Django >1.8 response = FileResponse(open(bundle_filename), content_type='application/zip') response['Content-Disposition'] = 'attachment; filename=' + os.path.split(bundle_filename)[1] response['Content-Length'] = os.path.getsize(bundle_filename) # The HTML form will not give access to the installers until the user has # downloaded the private keys. keys_downloaded = request.session['build_results'][build_id].get('keys_downloaded', dict()) keys_downloaded[key_type] = True request.session['build_results'][build_id]['keys_downloaded'] = keys_downloaded request.session.save() return response
def fastlane_page(request): """ <Purpose> Renders a key and installer download page for a default user-built seattle build, i.e.: One 80 per-cent vessel, one owner/user Note: owner/user-name can be set in settings.FASTLANE_USER_NAME <Arguments> request: A Django request. <Exceptions> None. <Side Effects> If new session - Creates and stores vesselinfo to appropriate location on disk - Stores generated key pair to session (memory) <Returns> A Django response. """ try: existing_build_result = False # We have to check if the user already has a build result in his session # and make sure it's a fastlane build, i.e. # it does not collide with a build from the interactive CIB if 'build_results' in request.session.keys(): for val in request.session['build_results'].values(): if isinstance(val, dict) and val.get("fast_lane_build"): existing_build_result = val break else: # This dict will only be saved if the build succeeds request.session['build_results'] = {} if existing_build_result: # There is no need to build again, let's serve what's already there build_id = existing_build_result.get('build_id') keys_downloaded = existing_build_result.get('keys_downloaded', dict()) # The manager helps us to find the files stored to disk manager = BuildManager(build_id=build_id) installer_links = manager.get_urls() else: # The user is here for the first time # Create basic installation setup (1 owner, 1 vessel, no users) users = { settings.FASTLANE_USER_NAME: {u'public_key': None} } vessels = [ { u'owner': settings.FASTLANE_USER_NAME, u'percentage': 80, u'users': [] } ] # Use build manager to create and store vesselinfo # and create cryptographic key pair (only stored in memory) manager = BuildManager(vessel_list=vessels, user_data=users) new_fastlane_build_results = manager.prepare() # These are needed in the HTML template to render the proper links # to the keys and installer build_id = manager.build_id installer_links = manager.get_urls() # Used in template to display check marks next to buttons # The keys are new so they cannot have been downloaded keys_downloaded = False # This prevents collision when using interactive CIB and fastlane CIB # in the same session # also hides breadcrumbs when serving shared (w/o key links) fastlane # download page new_fastlane_build_results["fast_lane_build"] = True # download_installer and download_keys views get the build_results # from the session to serve the correct files request.session['build_results'][build_id] = new_fastlane_build_results request.session.save() except: log_exception(request) return ErrorResponse('Unknown error occured while' + \ ' trying to build the installers.') # Builds share_url by using view URLreversing and the request object share_url = request.build_absolute_uri(reverse('download-installers-page', args=[build_id])) return render(request, 'download_installers.html', { 'fast_lane': True, 'build_id': build_id, 'installers': installer_links, 'share_url': share_url, 'keys_downloaded': keys_downloaded, })
def fastlane_page(request): """ <Purpose> Renders a key and installer download page for a default user-built seattle build, i.e.: One 80 per-cent vessel, one owner/user Note: owner/user-name can be set in settings.FASTLANE_USER_NAME <Arguments> request: A Django request. <Exceptions> None. <Side Effects> If new session - Creates and stores vesselinfo to appropriate location on disk - Stores generated key pair to session (memory) <Returns> A Django response. """ try: existing_build_result = False # We have to check if the user already has a build result in his session # and make sure it's a fastlane build, i.e. # it does not collide with a build from the interactive CIB if 'build_results' in request.session.keys(): for val in request.session['build_results'].values(): if isinstance(val, dict) and val.get("fast_lane_build"): existing_build_result = val break else: # This dict will only be saved if the build succeeds request.session['build_results'] = {} if existing_build_result: # There is no need to build again, let's serve what's already there build_id = existing_build_result.get('build_id') keys_downloaded = existing_build_result.get( 'keys_downloaded', dict()) # The manager helps us to find the files stored to disk manager = BuildManager(build_id=build_id) installer_links = manager.get_urls() else: # The user is here for the first time # Create basic installation setup (1 owner, 1 vessel, no users) users = {settings.FASTLANE_USER_NAME: {u'public_key': None}} vessels = [{ u'owner': settings.FASTLANE_USER_NAME, u'percentage': 80, u'users': [] }] # Use build manager to create and store vesselinfo # and create cryptographic key pair (only stored in memory) manager = BuildManager(vessel_list=vessels, user_data=users) new_fastlane_build_results = manager.prepare() # These are needed in the HTML template to render the proper links # to the keys and installer build_id = manager.build_id installer_links = manager.get_urls() # Used in template to display check marks next to buttons # The keys are new so they cannot have been downloaded keys_downloaded = False # This prevents collision when using interactive CIB and fastlane CIB # in the same session # also hides breadcrumbs when serving shared (w/o key links) fastlane # download page new_fastlane_build_results["fast_lane_build"] = True # download_installer and download_keys views get the build_results # from the session to serve the correct files request.session['build_results'][ build_id] = new_fastlane_build_results request.session.save() except: log_exception(request) return ErrorResponse('Unknown error occured while' + \ ' trying to build the installers.') # Builds share_url by using view URLreversing and the request object share_url = request.build_absolute_uri( reverse('download-installers-page', args=[build_id])) return render( request, 'download_installers.html', { 'fast_lane': True, 'build_id': build_id, 'installers': installer_links, 'share_url': share_url, 'keys_downloaded': keys_downloaded, })