def _single_cell_land_cover(self, model_run, values, errors): land_cover_controller_helper = LandCoverControllerHelper() if not request.POST: self._user_service.set_current_model_run_creation_action(self.current_user, "land_cover") land_cover_controller_helper.add_fractional_land_cover_to_context(c, errors, model_run, self.current_user) return render('model_run/fractional_land_cover.html') else: land_cover_controller_helper.save_fractional_land_cover(values, errors, model_run, self.current_user) if len(errors) > 0: if 'land_cover_frac' in errors: helpers.error_flash(errors['land_cover_frac']) land_cover_controller_helper.add_fractional_land_cover_to_context( c, errors, model_run, self.current_user) c.land_cover_values = values del values['submit'] html = render('model_run/fractional_land_cover.html') return htmlfill.render( html, defaults=values, errors=errors, auto_error_formatter=BaseController.error_formatter ) else: self._model_run_controller_helper.check_user_quota(self.current_user) try: action = values['submit'] except KeyError: action = None if action == u'Next': redirect(url(controller='model_run', action='output')) else: redirect(url(controller='model_run', action='extents'))
def _land_cover(self, model_run, values, errors): land_cover_controller_helper = LandCoverControllerHelper() if not request.POST: self._user_service.set_current_model_run_creation_action(self.current_user, "land_cover") land_cover_controller_helper.add_land_covers_to_context(c, errors, model_run) if len(errors) > 0: helpers.error_flash(errors['land_cover_actions']) return render('model_run/land_cover.html') else: land_cover_controller_helper.save_land_cover_actions(values, errors, model_run) if len(errors) > 0: helpers.error_flash(errors['land_cover_actions']) return render('model_run/land_cover.html') else: # Get the action to perform self._model_run_controller_helper.check_user_quota(self.current_user) try: action = values['submit'] except KeyError: action = None if action == u'Next': redirect(url(controller='model_run', action='output')) else: redirect(url(controller='model_run', action='extents'))
def _external_user_password(self, id): """ Code for password resets for an external user :param id: user id :return:html to render """ c.password_one = "" c.password_two = "" can_reset_password = self._valid_user_and_uuid(id) if can_reset_password == 'OK': if request.method == 'POST': try: self._user_service.reset_password( c.user.id, request.params.getone('password_one'), request.params.getone('password_two')) helpers.success_flash("Password Reset Successful") redirect(url(controller='account', action='login')) except ServiceException as ex: helpers.error_flash("Password not reset because %s" % ex.message) return render("user/forgotten_password_external.html") else: return render("user/forgotten_password_external.html") elif can_reset_password == 'EXPIRED': self._user_service.set_forgot_password(c.user.id, send_email=True) return render("user/expired_forgotten_password_external.html") else: return render("user/invalid_forgotten_password_external.html")
def about(self): """Action for when the user selects the about tab""" # We want to present slightly different about pages depending on whether the user # is logged in or not. The text is the same however. if self.current_user: return render("about/about-internal.html") else: return render("about/about-external.html")
def index(self): """Default action, shows the home page""" user = self.current_user if user: c.name = self.current_user.first_name return render("home.html") else: return render("landing.html")
def requests(self, id): """ List the account requests for approval :param id: id to accept or reject or None on get :return: nothing """ if self.current_user is None or not self.current_user.is_admin(): return render('not_found.html') if not request.method == 'POST': c.account_requests = self._account_request_service.get_account_requests() return render('user/requests.html') else: if id is None: helpers.error_flash("Request not accepted or rejected. No id included with reject or accept") try: action = request.params.getone('action') if action == u'accept': self._account_request_service.accept_account_request(id) helpers.success_flash("User account created and user emailed.") elif action == u'reject': reason_for_rejection = request.params.getone('reason') if len(reason_for_rejection.strip()) == 0: helpers.error_flash( "Request not rejected: A reason must be given to the user for why they are being rejected") else: self._account_request_service.reject_account_request(id, reason_for_rejection) helpers.success_flash("User account request has been rejected and an email has been sent.") elif action == u'ignore': self._account_request_service.ignore_account_request(id) helpers.success_flash( "User account request ignored; no user account created and user has not been emailed.") else: raise KeyError() except KeyError: helpers.error_flash("Request not accepted or rejected. No action included with reject or accept") except NoResultFound: helpers.error_flash("Request could not be found, no action taken") except ClientException as ex: log.exception("Trouble accepting account request because of CROWD") helpers.error_flash( "User account could not be created, there is a problem with CROWD: %s" % ex.message) except ServiceException as ex: log.exception("Trouble accepting or rejecting account request because of a service error") helpers.error_flash("User account could not be created %s" % ex.message) return redirect(url(controller="user", action="requests"))
def create(self): """Create a new user """ if not self.current_user.access_level == constants.USER_ACCESS_LEVEL_ADMIN: return render('not_found.html') if not request.POST: return render('new_user.html') schema = CreateUserForm() c.form_errors = {} if request.POST: try: c.form_result = schema.to_python(request.params) except formencode.Invalid, error: c.form_result = error.value c.form_errors = error.error_dict or {} user_email = str(c.form_result.get('email')) # Username of the user will be set as the user's email address # Generate an error if the email address (and hence username) is already taken if self._user_service.get_user_by_email_address(user_email): c.form_errors = dict(c.form_errors.items() + { 'email': 'Email address is already taken - please choose another.' }.items()) if c.form_errors: html = render('new_user.html') return htmlfill.render(html, defaults=c.form_result, errors=c.form_errors, prefix_error=False, auto_error_formatter=BaseController.error_formatter) else: # By default a user will be an external user self._user_service.create(c.form_result.get('user_name'), c.form_result.get('first_name'), c.form_result.get('last_name'), user_email, constants.USER_ACCESS_LEVEL_ADMIN if c.form_result.get('is_admin') else constants.USER_ACCESS_LEVEL_CEH) return redirect(url(controller="user"))
def faq(self): """ Frequently asked questions page :return: """ c.admin_email = config["email.admin_address"] return render("about/faq.html")
def parameters(self): """ Define parameters for the current new run being created """ try: c.parameters = self._model_run_service.get_parameters_for_model_being_created(self.current_user) except NoResultFound: helpers.error_flash(u"You must create a model run before any parameters can be set") redirect(url(controller='model_run', action='create')) if not request.POST: html = render('model_run/parameters.html') parameter_values = {} for parameter in c.parameters: if parameter.parameter_values: parameter_values[PARAMETER_NAME_PREFIX + str(parameter.id)] = parameter.parameter_values[0].value return htmlfill.render( html, defaults=parameter_values, errors={}, auto_error_formatter=BaseController.error_formatter ) else: # get the action to perform and remove it from the dictionary action = request.params.getone('submit') if action == u'Next': redirect(url(controller='model_run', action='submit')) else: redirect(url(controller='model_run', action='output'))
def license(self): """ Show the Majic license :return: rendered license page """ return render("request_account/license.html")
def submit(self): """ Page to submit the model un """ model_run = None try: model_run = \ self._model_run_service.get_model_being_created_with_non_default_parameter_values(self.current_user) except NoResultFound: helpers.error_flash(u"You must create a model run before submitting the model run") redirect(url(controller='model_run', action='create')) if not request.POST: self._user_service.set_current_model_run_creation_action(self.current_user, "submit") summmary_helper = SummaryControllerHelper(model_run_service=self._model_run_service) summmary_helper.add_summary_fields_to_context(model_run, c, self.current_user) else: self._model_run_controller_helper.check_user_quota(self.current_user) if request.params.getone('submit') == u'Submit': status, message = self._model_run_service.submit_model_run(self.current_user) if status.name == constants.MODEL_RUN_STATUS_SUBMITTED: helpers.success_flash(message) else: helpers.error_flash(message) redirect(url(controller='model_run', action='index')) else: redirect(url(controller='model_run', action='output')) return render('model_run/submit.html')
def index(self): """ Default controller providing access to the catalogue of user model runs :return: Rendered catalogue page """ # all non-created runs for the user c.user = self.current_user c.model_runs = [model for model in self._model_run_service.get_models_for_user(self.current_user) if model.status.name != constants.MODEL_RUN_STATUS_CREATED] total_user_storage = 0 for model in c.model_runs: if model.status.name != constants.MODEL_RUN_STATUS_PUBLISHED and \ model.status.name != constants.MODEL_RUN_STATUS_PUBLIC: if model.storage_in_mb is not None: total_user_storage += model.storage_in_mb c.storage_total_used_in_gb = utils.convert_mb_to_gb_and_round(total_user_storage) c.storage_percent_used = round(c.storage_total_used_in_gb / c.user.storage_quota_in_gb * 100.0, 0) c.bar_class = helpers.get_progress_bar_class_name(c.storage_percent_used) c.showing = "mine" c.user_has_model_run_being_created = \ self._model_run_service.get_user_has_model_run_being_created(self.current_user) return render("model_run/catalogue.html")
def profile(self): """ Deal with a logged in users profile :return: page to render """ c.user_to_edit = self.current_user if request.POST: self._user_service.update( self.current_user.id, self.form_result['first_name'], self.form_result['last_name'], self.form_result['email'], self.form_result['workbench_username'] ) return redirect(url(controller='home', action='index')) else: values = c.user_to_edit.__dict__ errors = {} # render the form if there are errors on Post or if this is a get return htmlfill.render( render('account/profile.html'), defaults=values, errors=errors, auto_error_formatter=BaseController.error_formatter)
def index(self): """ Allow admins to list the driving data sets :return: html to render """ c.driving_data_sets = self._dataset_service.get_driving_datasets(self.current_user) return render('driving_data/list.html')
def error_window(self): """Renders a page containing an error window with a specified message. """ log.debug("running viewdata.error_window") if 'message' in request.params: c.message = request.params['message'] else: c.message = 'Unknown error' return render('viewdata_error.html')
def request(self): """ Process a request for a new account :return: rendered form or success page """ if not request.POST: return render("request_account/request.html") account_request = AccountRequest() account_request.first_name = self.form_result["first_name"] account_request.last_name = self.form_result["last_name"] account_request.email = self.form_result["email"] account_request.institution = self.form_result["institution"] account_request.usage = self.form_result["usage"] self._account_request_service.add_account_request_with_email(account_request) c.account_request = account_request return render("request_account/request_made.html")
def published(self): """ Controller providing access to the catalogue of published model runs :return: Rendered catalogue page """ c.user = self.current_user c.model_runs = self._model_run_service.get_published_models() c.showing = "published" return render("model_run/catalogue.html")
def index(self): """Allow admin-user to see all users of the system. If user is non-admin, redirect to page not found. """ if self.current_user is not None and self.current_user.is_admin(): c.all_users = self._user_service.get_all_users() user_map = {} for user in c.all_users: user_map[user.id] = user user.storage_in_mb = 0 user.published_storage_in_mb = 0 c.storage_total_used_in_gb = 0 for user_id, status, storage_mb in self._model_run_service.get_storage_used(): c.storage_total_used_in_gb += int(storage_mb) if status == constants.MODEL_RUN_STATUS_PUBLISHED or status == constants.MODEL_RUN_STATUS_PUBLIC: user_map[user_id].published_storage_in_mb += int(storage_mb) else: user_map[user_id].storage_in_mb += int(storage_mb) c.storage_total_used_in_gb = utils.convert_mb_to_gb_and_round(c.storage_total_used_in_gb) c.core_user = None for user in c.all_users: if user.username == constants.CORE_USERNAME: c.core_user = user user.quota_status = '' percentage = round(utils.convert_mb_to_gb_and_round(user.storage_in_mb) / user.storage_quota_in_gb * 100.0, 1) if percentage >= constants.QUOTA_ABSOLUTE_LIMIT_PERCENT: user.quota_status = 'error' elif percentage >= constants.QUOTA_WARNING_LIMIT_PERCENT: user.quota_status = 'warning' c.core_user.quota_status = 'info' c.total_storage_percent_used = c.storage_total_used_in_gb / c.core_user.storage_quota_in_gb * 100.0 c.bar_class = helpers.get_progress_bar_class_name(c.total_storage_percent_used) return render('user/list_of_users.html') else: return render('not_found.html')
def login(self): """Action for the 'log in' view""" identity = request.environ.get('REMOTE_USER') came_from = request.params.get('came_from', None) message = request.params.get('message', None) if identity is not None: if came_from: redirect(url(str(came_from))) return render('login.html', extra_vars={'came_from': came_from, 'message': message})
def password(self, id=None): """ Action for when the user selects password :param id: users id :return: html """ # If the user is logged in then request the users password otherwise use the uuid in he query string if self.current_user: return render("not_found.html") else: return self._external_user_password(id)
def output(self): """ Select output parameters """ # First we need to check that we are allowed to be on this page model_run = self.get_model_run_being_created_or_redirect(self._model_run_service) if not request.POST: self._user_service.set_current_model_run_creation_action(self.current_user, "output") # We need to not show the output variables which are dependent on JULES_MODEL_LEVELS::nsmax if nsmax is 0 jules_param_nsmax = model_run.get_python_parameter_value(constants.JULES_PARAM_NSMAX) c.output_variables = self._model_run_service.get_output_variables( include_depends_on_nsmax=jules_param_nsmax > 0) # We want to pass the renderer a list of which output variables are already selected and for which time # periods so that we can render these onto the page as selected output_controller_helper.add_selected_outputs_to_template_context(c, model_run) # Finally we need to know if we must disable yearly or monthly outputs c.yearly_allowed = output_controller_helper.yearly_output_allowed(model_run) c.monthly_allowed = output_controller_helper.monthly_output_allowed(model_run) return render("model_run/output.html") else: values = dict(request.params) # Identify the requested output variables and save the appropriate parameters output_variable_groups = output_controller_helper.create_output_variable_groups(values, self._model_run_service, model_run) self._model_run_service.set_output_variables_for_model_being_created(output_variable_groups, self.current_user) # Put a limit on the number of output profiles (tick-boxes) that can be submitted. if len(output_variable_groups) > constants.JULES_PARAM_OUTPUT_NPROFILES_MAX: helpers.error_flash("Cannot submit with more than " + str(constants.JULES_PARAM_OUTPUT_NPROFILES_MAX) + " output profiles. Please select fewer than " + str(constants.JULES_PARAM_OUTPUT_NPROFILES_MAX) + " tick-boxes on this page.") redirect(url(controller='model_run', action='output')) # Get the action to perform self._model_run_controller_helper.check_user_quota(self.current_user) try: action = values['submit'] except KeyError: action = None if action == u'Next': redirect(url(controller='model_run', action='submit')) else: redirect(url(controller='model_run', action='land_cover'))
def show_error_if_thredds_down(func, self, *args, **kwargs): """ Renders an error page if the THREDDS server cannot be contacted :param func: Function that is decorated :param args: Arguments for the function :param kwargs: Named key word arguments :return: Rendered HTML """ if is_thredds_up(config): return func(self, *args, **kwargs) else: c.admin_email = config["email.admin_address"] page = render("map_down.html") return page
def timeselection(self, id): """ Gets the possible time points for a temporal dataset @param id: ID of the dataset to get time points for """ ds = self._dataset_service.get_dataset_by_id(id, user_id=self.current_user.id) c.time_points = self._netcdf_service.get_time_points(ds.netcdf_url) c.dataset_name = ds.name c.column_name = request.params.get('col', '') c.identifier = "%s_%s" % (ds.id, c.column_name) if c.time_points: # Render the points back return render("dataset_time_values.html")
def must_be_admin(func, self, *args, **kwargs): """ Decorator to add to an action in a controller which means that if the user is not an admin the not found page is rendered :param func: function that is decorated :param args: arguments for the function :param kwargs: dictionary for the functions :return: rendered html """ access_is_ok = False try: access_is_ok = self.current_user is not None and self.current_user.is_admin() except Exception: log.exception("Exception when accessing a admin only page") # call to render page must be outside exception block otherwise redirects do not work if access_is_ok: return func(self, *args, **kwargs) return render('not_found.html')
def summary(self, id): """ Controller providing a detailed summary of a single model run :param id: the id of the model run to display :return: Rendered summary page of requested model run """ c.user = self.current_user model_run = self._model_run_service.get_model_by_id(self.current_user, id) summary_helper = SummaryControllerHelper(model_run_service=self._model_run_service) summary_helper.add_summary_fields_to_context(model_run, c, self.current_user) c.user_has_model_run_being_created = \ self._model_run_service.get_user_has_model_run_being_created(self.current_user) # does the model belong to this user. Not to be used for security but for display purposes c.is_users_model = (c.user.id == model_run.user.id) # path to workbench c.workbench_path = config["workbench_path_template"].format(model_run_id=model_run.id) return render("model_run/summary.html")
def view(self, id): """ Controller to load specific model_runs onto the map viewer :param id: Database ID of model_run to view data for :return: Rendered map page """ models = self._model_run_service.get_models_for_user(self.current_user) models_to_view = [m for m in models if m.status.allow_visualise()] counter = 0 for model in models_to_view: for dataset in model.datasets: dataset.layer_id = counter counter += 1 published_models_to_view = self._model_run_service.get_published_models() for model in published_models_to_view: for dataset in model.datasets: dataset.layer_id = counter counter += 1 c.model_run_sorts = \ [ { 'name': "Mine", 'model_runs': models_to_view }, { 'name': "Published", 'model_runs': published_models_to_view } ] c.id = id c.DATASET_TYPE_COVERAGE = constants.DATASET_TYPE_COVERAGE c.DATASET_TYPE_SINGLE_CELL = constants.DATASET_TYPE_SINGLE_CELL c.DATASET_TYPE_TRANSECT = constants.DATASET_TYPE_TRANSECT c.DATASET_TYPE_LAND_COVER_FRAC = constants.DATASET_TYPE_LAND_COVER_FRAC c.DATASET_TYPE_SOIL_PROP = constants.DATASET_TYPE_SOIL_PROP c.GRAPH_NPOINTS = constants.GRAPH_NPOINTS return render('map.html')
def layers(self, id): """ Returns a view on a dataset's map layers :param id: The ID of the dataset to get the layer data for, and the ID :return: rendered layer """ dataset_id = request.params.get('dsid') c.layer_id = request.params.get('layerid') dataset = self._dataset_service.get_dataset_by_id(dataset_id, user_id=self.current_user.id) c.model_run = model_run = self._model_run_service.get_model_by_id(self.current_user, dataset.model_run_id) c.dataset = dataset c.dimensions = [] dataset_type = dataset.dataset_type.type if dataset_type == constants.DATASET_TYPE_COVERAGE: c.layers = self.get_layers_for_dataset(dataset) # Check for dimensionality if c.layers and c.layers[0]['dimensions']: c.dimensions = c.layers[0]['dimensions'] c.dimensions[0]['dimensionNames'] = c.dimensions[0]['dimensionValues'] elif dataset_type == constants.DATASET_TYPE_SINGLE_CELL: c.dimensions = self.get_time_dimensions_for_single_cell(dataset) elif dataset_type == constants.DATASET_TYPE_LAND_COVER_FRAC or dataset_type == constants.DATASET_TYPE_SOIL_PROP: layer = self.get_layers_for_dataset(dataset)[0] layer['title'] = dataset.name c.layers = [layer] c.dimensions = self.get_variable_dimensions_for_ancils(dataset, model_run) for period in ['Daily', 'Monthly', 'Hourly', 'Yearly']: if period in dataset.name: for layer in c.layers: layer['title'] += ' (%s)' % period return render('layers.html')
def create(self): """ Controller for creating a new run """ scientific_configurations = self._model_run_service.get_scientific_configurations() values = dict(request.params) errors = None if request.POST: try: self._model_run_service.update_model_run( self.current_user, self.form_result['name'], self.form_result['science_configuration'], self.form_result['description']) self._model_run_controller_helper.check_user_quota(self.current_user) redirect(url(controller='model_run', action='driving_data')) except NoResultFound: errors = {'science_configuration': 'Configuration is not recognised'} except DuplicateName: errors = {'name': 'Name can not be the same as another model run'} else: self._user_service.set_current_model_run_creation_action(self.current_user, "create") model = self._model_run_service.get_model_run_being_created_or_default(self.current_user) values['name'] = model.name values['science_configuration'] = model.science_configuration_id values['description'] = model.description c.scientific_configurations = scientific_configurations html = render('model_run/create.html') return htmlfill.render( html, defaults=values, errors=errors, auto_error_formatter=BaseController.error_formatter)
else: driving_dataset = self._dataset_service.get_driving_dataset_by_id(id) c.regions = self._landcover_service.get_land_cover_regions(id) jules_params = DrivingDatasetJulesParams() jules_params.set_from(driving_dataset, c.regions) values = jules_params.create_values_dict(c.namelist) c.masks = int(values['mask_count']) c.mask_can_be_deleted = [] for mask_index in range(c.masks): mask_id = values['region-{}.id'.format(mask_index)] c.mask_can_be_deleted.append(mask_id is None or mask_id == "") try: c.nvar = int(values['drive_nvars']) except (ValueError, KeyError): c.nvar = 0 c.param_names = values["param_names"] html = render('driving_data/edit.html') return htmlfill.render( html, defaults=values, errors=variabledecode.variable_encode(errors, add_repetitions=False), auto_error_formatter=BaseController.error_formatter, prefix_error=False)
except AuthenticationFailedException: message = 'Login failed: check your username and/or password.' except ClientException: message = 'Login failed: The authentication server is not responding correctly. ' \ 'Please try again later. If the problem persists please report it to {}.'\ .format(config['email.admin_address']) else: # Forcefully forget any existing credentials. _, headers = who_api.login({}) request.response_headerlist = headers if 'REMOTE_USER' in request.environ: del request.environ['REMOTE_USER'] return htmlfill.render( render('login.html', extra_vars={'came_from': came_from, 'message': message}), defaults=c.form_result, errors=c.form_errors, auto_error_formatter=_custom_formatter ) def logout(self): """Action to log the user out - removing their session""" who_api = get_api(request.environ) who_api.logout() self.current_user = None redirect(url(controller='home', action='index')) @validate(schema=AccountProfileEdit(), form='profile', post_only=False, on_get=False, prefix_error=False, auto_error_formatter=BaseController.error_formatter)