def read_one(request): """ Read one Stakeholder based on ID and return all versions of this Stakeholder. Also return pending versions by currently logged in user and all pending versions of this Stakeholder if logged in as moderator. Default output format: JSON """ # Handle the parameters (locale, profile) bv = BaseView(request) bv._handle_parameters() try: output_format = request.matchdict['output'] except KeyError: output_format = 'json' uid = request.matchdict.get('uid', None) if check_valid_uuid(uid) is not True: raise HTTPNotFound() if output_format == 'json': stakeholders = stakeholder_protocol3.read_one(request, uid=uid, public=False) return render_to_response('json', stakeholders, request) elif output_format == 'html': # Show the details of a Stakeholder by rendering the form in readonly # mode. stakeholders = stakeholder_protocol3.read_one(request, uid=uid, public=False, translate=False) version = request.params.get('v', None) if (stakeholders and 'data' in stakeholders and len(stakeholders['data']) != 0): for sh in stakeholders['data']: if 'version' in sh: if version is None: # If there is no version provided, show the first # version visible to the user version = str(sh['version']) if str(sh['version']) == version: templateValues = renderReadonlyForm(request, 'stakeholders', sh) templateValues['profile'] = get_current_profile(request) templateValues['locale'] = get_current_locale(request) # Append the short uid and the uid to the templates values templateValues['uid'] = uid templateValues['shortuid'] = uid.split("-")[0] # Append also the site key from the commenting system templateValues['site_key'] = comments_sitekey(request)['site_key'] # and the url of the commenting system templateValues['comments_url'] = request.registry.settings['lmkp.comments_url'] return render_to_response( getTemplatePath(request, 'stakeholders/details.mak'), templateValues, request ) return HTTPNotFound() elif output_format == 'form': if request.user is None: # Make sure the user is logged in raise HTTPForbidden() # Query the Stakeholders with the given identifier stakeholders = stakeholder_protocol3.read_one(request, uid=uid, public=False, translate=False) version = request.params.get('v', None) if (stakeholders and 'data' in stakeholders and len(stakeholders['data']) != 0): for sh in stakeholders['data']: if 'version' in sh: if version is None: # If there is no version provided, show the first # version visible to the user version = str(sh['version']) if str(sh['version']) == version: templateValues = renderForm(request, 'stakeholders', itemJson=sh) if isinstance(templateValues, Response): return templateValues templateValues['profile'] = get_current_profile(request) templateValues['locale'] = get_current_locale(request) return render_to_response( getTemplatePath(request, 'stakeholders/form.mak'), templateValues, request ) return HTTPNotFound() elif output_format in ['review', 'compare']: if output_format == 'review': # Only moderators can see the review page. isLoggedIn, isModerator = checkUserPrivileges(request) if isLoggedIn is False or isModerator is False: raise HTTPForbidden() camefrom = request.params.get('camefrom', '') review = StakeholderReview(request) availableVersions = None recalculated = False defaultRefVersion, defaultNewVersion = review._get_valid_versions( Stakeholder, uid) refVersion = request.params.get('ref', None) if refVersion is not None: try: refVersion = int(refVersion) except: refVersion = None if refVersion is None or output_format == 'review': # No reference version indicated, use the default one # Also use the default one for review because it cannot be changed. refVersion = defaultRefVersion else: availableVersions = review._get_available_versions(Stakeholder, uid, review=output_format=='review') # Check if the indicated reference version is valid if refVersion not in [v.get('version') for v in availableVersions]: refVersion = defaultRefVersion newVersion = request.params.get('new', None) if newVersion is not None: try: newVersion = int(newVersion) except: newVersion = None if newVersion is None: # No new version indicated, use the default one newVersion = defaultNewVersion else: if availableVersions is None: availableVersions = review._get_available_versions(Stakeholder, uid, review=output_format=='review') # Check if the indicated new version is valid if newVersion not in [v.get('version') for v in availableVersions]: newVersion = defaultNewVersion if output_format == 'review': # If the Stakeholders are to be reviewed, only the changes which # were applied to the newVersion are of interest stakeholders, recalculated = review.get_comparison(Stakeholder, uid, refVersion, newVersion) else: # If the Stakeholders are compared, the versions as they are stored # in the database are of interest, without any recalculation stakeholders = [ stakeholder_protocol3.read_one_by_version(request, uid, refVersion, translate=False ), stakeholder_protocol3.read_one_by_version(request, uid, newVersion, translate=False ) ] templateValues = renderReadonlyCompareForm(request, 'stakeholders', stakeholders[0], stakeholders[1], review=output_format=='review') # Collect metadata for the reference version refMetadata = {} if stakeholders[0] is not None: refMetadata = stakeholders[0].get_metadata(request) # Collect metadata and missing keys for the new version newMetadata = {} missingKeys = [] reviewable = False if stakeholders[1] is not None: stakeholders[1].mark_complete(get_mandatory_keys(request, 'sh', False)) missingKeys = stakeholders[1]._missing_keys localizer = get_localizer(request) if localizer.locale_name != 'en': db_lang = Session.query(Language).filter(Language.locale == localizer.locale_name).first() missingKeys = get_translated_db_keys(SH_Key, missingKeys, db_lang) missingKeys = [m[1] for m in missingKeys] newMetadata = stakeholders[1].get_metadata(request) reviewable = (len(missingKeys) == 0 and 'reviewableMessage' in templateValues and templateValues['reviewableMessage'] is None) if output_format == 'review': pendingVersions = [] if availableVersions is None: availableVersions = review._get_available_versions(Stakeholder, uid, review=output_format=='review') for v in sorted(availableVersions, key=lambda v:v.get('version')): if v.get('status') == 1: pendingVersions.append(v.get('version')) templateValues['pendingVersions'] = pendingVersions templateValues.update({ 'identifier': uid, 'refVersion': refVersion, 'refMetadata': refMetadata, 'newVersion': newVersion, 'newMetadata': newMetadata, 'missingKeys': missingKeys, 'reviewable': reviewable, 'recalculated': recalculated, 'camefrom': camefrom, 'profile': get_current_profile(request), 'locale': get_current_locale(request) }) if output_format == 'review': return render_to_response( getTemplatePath(request, 'stakeholders/review.mak'), templateValues, request ) else: return render_to_response( getTemplatePath(request, 'stakeholders/compare.mak'), templateValues, request ) elif output_format == 'formtest': # Test if a Stakeholder is valid according to the form configuration stakeholders = stakeholder_protocol3.read_one(request, uid=uid, public=False, translate=False) version = request.params.get('v', None) if (stakeholders and 'data' in stakeholders and len(stakeholders['data']) != 0): for sh in stakeholders['data']: if 'version' in sh: if version is None: version = str(sh['version']) if str(sh['version']) == version: categorylist = getCategoryList(request, 'stakeholders') return render_to_response('json', checkValidItemjson(categorylist, sh), request) return HTTPNotFound() else: # If the output format was not found, raise 404 error raise HTTPNotFound()
def review(request): """ Insert a review decision for a pending Stakeholder Required POST attributes: - identifier (string, uid) - version (int) - review_decision (string): approve / reject - review_comment (string): nullable - camefrom: uid of the Activity """ _ = request.translate # Check if the user is logged in and he/she has sufficient user rights userid = authenticated_userid(request) if userid is None: raise HTTPUnauthorized(_('User is not logged in.')) if not isinstance(has_permission('moderate', request.context, request), ACLAllowed): raise HTTPUnauthorized(_('User has no permissions to add a review.')) user = Session.query(User).\ filter(User.username == authenticated_userid(request)).first() # Query new version of Stakeholder stakeholder = Session.query(Stakeholder).\ filter(Stakeholder.stakeholder_identifier == request.POST['identifier']).\ filter(Stakeholder.version == request.POST['version']).\ first() if stakeholder is None: raise HTTPUnauthorized(_('The Item was not found')) # If review decision is 'approved', make sure that all mandatory fields are # there, except if it is to be deleted review_decision = request.POST['review_decision'] if review_decision == 'approve': review_decision = 1 elif review_decision == 'reject': review_decision = 2 else: raise HTTPBadRequest(_('No valid review decision')) review_comment = request.POST.get('review_comment', '') camefrom = request.POST.get('camefrom', '') if review_decision == 1: # Approved # Only check for mandatory keys if new version is not to be deleted # (has no tag groups) if len(stakeholder.tag_groups) > 0: mandatory_keys = get_mandatory_keys(request, 'sh') # Query keys stakeholder_keys = Session.query(SH_Key.key).\ join(SH_Tag).\ join(SH_Tag_Group, SH_Tag.fk_tag_group == SH_Tag_Group.id).\ filter(SH_Tag_Group.stakeholder == stakeholder) keys = [] for k in stakeholder_keys.all(): keys.append(k.key) for mk in mandatory_keys: if mk not in keys: raise HTTPBadRequest(_('Not all mandatory keys are provided')) # The user can add a review ret = stakeholder_protocol3._add_review(request, stakeholder, Stakeholder, user, review_decision, review_comment) if 'success' not in ret or ret['success'] is False and 'msg' not in ret: raise HTTPBadRequest(_('Unknown error')) if ret['success'] is True: request.session.flash(ret['msg'], 'success') else: request.session.flash(ret['msg'], 'error') if camefrom != '': camefromMsg = render( getTemplatePath(request, 'parts/messages/stakeholder_reviewed_through_involvement.mak'), {'url': request.route_url('activities_read_one', output='review', uid=camefrom)}, request ) request.session.flash(camefromMsg) return HTTPFound(location=request.route_url('stakeholders_read_one_history', output='html', uid=stakeholder.identifier))
def review(self): """ Review a pending :term:`Activity` version. A review can only be done by moderators and if the :term:`Activity` is situated within one of the profiles of the moderator. POST parameters: ``identifier`` (str): An :term:`Activity` :term:`UID`. ``version`` (int): The version of the :term:`Activity` to be reviewed ``review_decision`` (str): One of ``approve`` or ``reject``. ``review_comment`` (str): An optional comment to be stored with the review. Returns: ``HTTPResponse``. If the review was successful, the history page of the :term:`Activity` is returned. """ is_logged_in, is_moderator = get_user_privileges(self.request) if not is_logged_in: raise HTTPUnauthorized("User is not logged in.") if not is_moderator: raise HTTPUnauthorized("User has no permissions to add a review.") profile_filters = activity_protocol._get_spatial_moderator_filter(self.request) if profile_filters is None: raise HTTPBadRequest("User has no profile attached") activity = ( Session.query(Activity) .filter(Activity.activity_identifier == self.request.POST["identifier"]) .filter(Activity.version == self.request.POST["version"]) .filter(profile_filters) .first() ) if activity is None: raise HTTPUnauthorized("The Item was not found or is not situated within the user's " "profiles") review_decision = self.request.POST["review_decision"] if review_decision == "approve": review_decision = 1 elif review_decision == "reject": review_decision = 2 else: raise HTTPBadRequest("No valid review decision") # Only check for mandatory keys if the new version is to be approved # and if it is not to be deleted (in which case it has no tag groups) if review_decision == 1 and len(activity.tag_groups) > 0: mandatory_keys = get_mandatory_keys(self.request, "a") activity_keys = ( Session.query(A_Key.key) .join(A_Tag) .join(A_Tag_Group, A_Tag.fk_tag_group == A_Tag_Group.id) .filter(A_Tag_Group.activity == activity) ) keys = [] for k in activity_keys.all(): keys.append(k.key) for mk in mandatory_keys: if mk not in keys: raise HTTPBadRequest("Not all mandatory keys are provided") review = activity_protocol._add_review( self.request, activity, Activity, self.request.user, review_decision, self.request.POST.get("review_comment", ""), ) review_success = review.get("success", False) if review_success: self.request.session.flash(review.get("msg"), "success") else: if review.get("msg") is None: raise HTTPBadRequest("Unknown error") self.request.session.flash(review.get("msg"), "error") return HTTPFound( location=self.request.route_url("activities_read_one_history", output="html", uid=activity.identifier) )
def _check_mandatory_keys(): mandatory_keys = get_mandatory_keys(self.request, 'a') log.debug(mandatory_keys)
def read_one(self, public=False): """ Return one :term:`Activity`. .. seealso:: :ref:`read-one` Read one :term:`Activity` or one version of an :term:`Activity`. By default, this is the latest visible version to the current user. This means that logged in users can see their own pending version and moderators of the current profile can see a pending version as well. If you don't want to see a version pending, consider using :class:`lmkp.views.activities.ActivityView.read_one_public` instead. Args: ``public`` (bool): A boolean indicating to return only a version visible to the public (eg. pending) or not. Matchdict parameters: ``/activities/{output}/{uid}`` ``output`` (str): If the output format is not valid, a 404 Response is returned. The following output formats are supported: ``json``: Return the :term:`Activity` as JSON. All versions visible to the current user are returned. ``geojson``: Return the :term:`Activity` as GeoJSON. A version parameter is required. ``html``: Return the :term:`Activity` as HTML (eg. the `Detail View`). ``form``: Returns the form to edit an existing :term:`Activity`. ``compare``: Return the page to compare two versions of the :term:`Activity`. ``review``: Return the page to review a pending version of an :term:`Activity`. ``statistics``: Return a page with the areal statistics of an :term:`Activity`. ``uid`` (str): An :term:`Activity` :term:`UID`. Request parameters: ``translate`` (bool): Return translated values or not. This is only valid for the output formats ``json`` or ``geojson``. ``v`` (int): Indicate a specific version to return. This is only valid for the output formats ``geojson``, ``html`` and ``form``. ``inv`` (str): Only valid for output format ``form``. Indicate an involvement of the form to return to after creating a new :term:`Stakeholder`. ``ref`` (int) and ``new`` (int): Indicate specific versions. This is only valid for the output formats ``compare`` and ``review``. Returns: ``HTTPResponse``. Either a HTML or a JSON response. """ output_format = get_output_format(self.request) uid = self.request.matchdict.get("uid", None) if validate_uuid(uid) is not True: raise HTTPNotFound() if output_format == "json": translate = self.request.params.get("translate", "true").lower() == "true" item = activity_protocol.read_one(self.request, uid=uid, public=public, translate=translate) return render_to_response("json", item, self.request) elif output_format == "geojson": # A version is required version = self.request.params.get("v", None) if version is None: raise HTTPBadRequest("You must specify a version as parameter ?v=X") translate = self.request.params.get("translate", "true").lower() == "true" item = activity_protocol.read_one_geojson_by_version(self.request, uid, version, translate=translate) return render_to_response("json", item, self.request) elif output_format == "html": version = self.request.params.get("v", None) item = activity_protocol.read_one(self.request, uid=uid, public=public, translate=False) for i in item.get("data", []): item_version = i.get("version") if version is None: # If there was no version provided, show the first # version visible to the user version = str(item_version) if str(item_version) == version: template_values = self.get_base_template_values() template_values.update(renderReadonlyForm(self.request, "activities", i)) template_values.update( { "uid": uid, "shortuid": shorten_uuid(uid), "version": version, "site_key": comments_sitekey(self.request)["site_key"], "comments_url": self.request.registry.settings["lmkp.comments_url"], } ) return render_to_response( get_customized_template_path(self.request, "activities/details.mak"), template_values, self.request, ) return HTTPNotFound() elif output_format == "form": is_logged_in, __ = get_user_privileges(self.request) if not is_logged_in: raise HTTPForbidden() version = self.request.params.get("v", None) item = activity_protocol.read_one(self.request, uid=uid, public=False, translate=False) for i in item.get("data", []): item_version = i.get("version") if version is None: # If there was no version provided, show the first # version visible to the user version = str(item_version) if str(item_version) == version: new_involvement = self.request.params.get("inv") template_values = renderForm(self.request, "activities", itemJson=i, inv=new_involvement) if isinstance(template_values, Response): return template_values template_values.update(self.get_base_template_values()) template_values.update({"uid": uid, "version": version}) return render_to_response( get_customized_template_path(self.request, "activities/form.mak"), template_values, self.request ) return HTTPNotFound() elif output_format in ["review", "compare"]: if output_format == "review": # Only moderators can see the review page. is_logged_in, is_moderator = get_user_privileges(self.request) if not is_logged_in or not is_moderator: raise HTTPForbidden() review = ActivityReview(self.request) is_review = output_format == "review" available_versions = review._get_available_versions(Activity, uid, review=is_review) recalculated = False default_ref_version, default_new_version = review._get_valid_versions(Activity, uid) try: ref_version = int(self.request.params.get("ref")) except: ref_version = None # For review or if no valid reference version is provided, use the # default reference version. if ( output_format == "review" or ref_version is None or ref_version not in [v.get("version") for v in available_versions] ): ref_version = default_ref_version try: new_version = int(self.request.params.get("new")) except: new_version = None # If no valid new version is provided, use the default new version. if new_version is None or new_version not in [v.get("version") for v in available_versions]: new_version = default_new_version if output_format == "review": # If the Items are to be reviewed, only the changes which were # applied to the new_version are of interest items, recalculated = review.get_comparison(Activity, uid, ref_version, new_version) else: # If the Items are to be compared, the versions as they are # stored in the database are of interest, without any # recalculation items = [ activity_protocol.read_one_by_version( self.request, uid, ref_version, geometry="full", translate=False ), activity_protocol.read_one_by_version( self.request, uid, new_version, geometry="full", translate=False ), ] template_values = renderReadonlyCompareForm( self.request, "activities", items[0], items[1], review=is_review ) # Collect the metadata ref_metadata = {} new_metadata = {} missing_keys = [] reviewable = False if items[0] is not None: ref_metadata = items[0].get_metadata(self.request) if items[1] is not None: new_metadata = items[1].get_metadata(self.request) items[1].mark_complete(get_mandatory_keys(self.request, "a", False)) missing_keys = items[1]._missing_keys localizer = get_localizer(self.request) if localizer.locale_name != "en": db_lang = Session.query(Language).filter(Language.locale == localizer.locale_name).first() missing_keys = get_translated_db_keys(A_Key, missing_keys, db_lang) missing_keys = [m[1] for m in missing_keys] reviewable = ( len(missing_keys) == 0 and "reviewableMessage" in template_values and template_values["reviewableMessage"] is None ) if output_format == "review": pending_versions = [] for v in sorted(available_versions, key=lambda v: v.get("version")): if v.get("status") == 1: pending_versions.append(v.get("version")) template_values.update({"pendingVersions": pending_versions}) template_values.update(self.get_base_template_values()) template_values.update( { "identifier": uid, "refVersion": ref_version, "refMetadata": ref_metadata, "newVersion": new_version, "newMetadata": new_metadata, "missingKeys": missing_keys, "reviewable": reviewable, "recalculated": recalculated, } ) if output_format == "review": template = get_customized_template_path(self.request, "activities/review.mak") else: template = get_customized_template_path(self.request, "activities/compare.mak") return render_to_response(template, template_values, self.request) elif output_format == "formtest": version = self.request.params.get("v", None) # Test if an Item is valid according to the form configuration items = activity_protocol.read_one(self.request, uid=uid, public=False, translate=False) for i in item.get("data", []): item_version = i.get("version") if version is None: # If there was no version provided, show the first # version visible to the user version = str(item_version) if str(item_version) == version: categorylist = getCategoryList(self.request, "activities") return render_to_response("json", checkValidItemjson(categorylist, i), self.request) return HTTPNotFound() elif output_format == "statistics": # Try to get the base URL to the web processing service which # provides the areal statistics. # If no web processing service is configured, it is assumed that # the platform does not provide the areal statistics try: wps_host = self.request.registry.settings["lmkp.base_wps"] except KeyError: raise HTTPNotFound() # Check if the spatial accuracy map is configured in the # application .yml file spatial_accuracy_map = get_spatial_accuracy_map(self.request) if spatial_accuracy_map is None: raise HTTPNotFound() # Show the details of an Activity by rendering the form in readonly # mode. activities = activity_protocol.read_one(self.request, uid=uid, public=False, translate=False) activity = activities["data"][0] coords = activity["geometry"]["coordinates"] for taggroup in activity["taggroups"]: if taggroup["main_tag"]["key"] == "Spatial Accuracy": spatial_accuracy = taggroup["main_tag"]["value"] buffer = spatial_accuracy_map[spatial_accuracy] wps_parameters = { "ServiceProvider": "", "metapath": "", "Service": "WPS", "Request": "Execute", "Version": "1.0.0", "Identifier": "BufferStatistics", "DataInputs": "lon=%s;lat=%s;epsg=4326;buffer=%s" % (coords[0], coords[1], buffer), "RawDataOutput": "bufferstatistics@mimeType=application/json", } if not wps_host.endswith("?"): wps_host = "%s?" % wps_host for k, v in wps_parameters.items(): wps_host = "%s%s=%s&" % (wps_host, k, v) log.debug("Accessing: %s" % wps_host) try: handle = urllib.urlopen(wps_host) except IOError: return HTTPInternalServerError("Remote server not accessible.") templateValues = json.loads(handle.read()) templateValues["uid"] = uid templateValues["shortuid"] = uid.split("-")[0] return render_to_response( get_customized_template_path(self.request, "activities/statistics.mak"), templateValues, self.request ) else: raise HTTPNotFound()
def review(request): """ Insert a review decision for a pending Activity Required POST attributes: - identifier (string, uid) - version (int) - review_decision (string): approve / reject - review_comment (string): nullable """ _ = request.translate # Check if the user is logged in and he/she has sufficient user rights userid = authenticated_userid(request) if userid is None: raise HTTPUnauthorized(_('User is not logged in.')) if not isinstance(has_permission('moderate', request.context, request), ACLAllowed): raise HTTPUnauthorized(_('User has no permissions to add a review.')) #user = Session.query(User).filter(User.username == authenticated_userid(request)).first() user = request.user # Check for profile profile_filters = activity_protocol3._get_spatial_moderator_filter(request) if profile_filters is None: raise HTTPBadRequest(_('User has no profile attached')) activity = Session.query(Activity).\ filter(Activity.activity_identifier == request.POST['identifier']).\ filter(Activity.version == request.POST['version']).\ filter(profile_filters).\ first() if activity is None: raise HTTPUnauthorized(_("The Item was not found or is not situated within the user's profiles")) # If review decision is 'approved', make sure that all mandatory fields are # there, except if it is to be deleted review_decision = request.POST['review_decision'] if review_decision == 'approve': review_decision = 1 elif review_decision == 'reject': review_decision = 2 else: raise HTTPBadRequest(_('No valid review decision')) review_comment = request.POST['review_comment'] if review_decision == 1: # Approved # Only check for mandatory keys if new version is not to be deleted # (has no tag groups) if len(activity.tag_groups) > 0: mandatory_keys = get_mandatory_keys(request, 'a') # Query keys activity_keys = Session.query(A_Key.key).\ join(A_Tag).\ join(A_Tag_Group, A_Tag.fk_tag_group == A_Tag_Group.id).\ filter(A_Tag_Group.activity == activity) keys = [] for k in activity_keys.all(): keys.append(k.key) for mk in mandatory_keys: if mk not in keys: raise HTTPBadRequest(_('Not all mandatory keys are provided')) # The user can add a review ret = activity_protocol3._add_review(request, activity, Activity, user, review_decision, review_comment) if 'success' not in ret or ret['success'] is False and 'msg' not in ret: raise HTTPBadRequest(_('Unknown error')) if ret['success'] is True: request.session.flash(ret['msg'], 'success') else: request.session.flash(ret['msg'], 'error') return HTTPFound(location=request.route_url('activities_read_one_history', output='html', uid=activity.identifier))
def read_one(request): """ Read one Activity based on ID and return all versions of this Activity. Also return pending versions by currently logged in user and all pending versions of this Activity if logged in as moderator. Default output format: JSON """ # Handle the parameters (locale, profile) bv = BaseView(request) bv._handle_parameters() try: output_format = request.matchdict['output'] except KeyError: output_format = 'json' uid = request.matchdict.get('uid', None) if check_valid_uuid(uid) is not True: raise HTTPNotFound() if output_format == 'json': activities = activity_protocol3.read_one(request, uid=uid, public=False) return render_to_response('json', activities, request) elif output_format == 'html': # Show the details of an Activity by rendering the form in readonly # mode. activities = activity_protocol3.read_one(request, uid=uid, public=False, translate=False) version = request.params.get('v', None) if activities and 'data' in activities and len(activities['data']) != 0: for a in activities['data']: if 'version' in a: if version is None: # If there was no version provided, show the first # version visible to the user version = str(a['version']) if str(a['version']) == version: templateValues = renderReadonlyForm(request, 'activities', a) templateValues['profile'] = get_current_profile(request) templateValues['locale'] = get_current_locale(request) # Append the short uid and the uid to the templates values templateValues['uid'] = uid templateValues['version'] = version templateValues['shortuid'] = uid.split("-")[0] # Append also the site key from the commenting system templateValues['site_key'] = comments_sitekey(request)['site_key'] # and the url of the commenting system templateValues['comments_url'] = request.registry.settings['lmkp.comments_url'] return render_to_response( getTemplatePath(request, 'activities/details.mak'), templateValues, request ) return HTTPNotFound() elif output_format == 'form': if request.user is None: # Make sure the user is logged in raise HTTPForbidden() # Query the Activities wih the given identifier activities = activity_protocol3.read_one(request, uid=uid, public=False, translate=False) version = request.params.get('v', None) if activities and 'data' in activities and len(activities['data']) != 0: for a in activities['data']: if 'version' in a: if version is None: # If there was no version provided, show the first # version visible to the user version = str(a['version']) if str(a['version']) == version: templateValues = renderForm(request, 'activities', itemJson=a) if isinstance(templateValues, Response): return templateValues templateValues['profile'] = get_current_profile(request) templateValues['locale'] = get_current_locale(request) templateValues['uid'] = uid templateValues['version'] = version return render_to_response( getTemplatePath(request, 'activities/form.mak'), templateValues, request ) return HTTPNotFound() elif output_format in ['review', 'compare']: if output_format == 'review': # Only moderators can see the review page. isLoggedIn, isModerator = checkUserPrivileges(request) if isLoggedIn is False or isModerator is False: raise HTTPForbidden() review = ActivityReview(request) availableVersions = None recalculated = False defaultRefVersion, defaultNewVersion = review._get_valid_versions( Activity, uid) refVersion = request.params.get('ref', None) if refVersion is not None: try: refVersion = int(refVersion) except: refVersion = None if refVersion is None or output_format == 'review': # No reference version indicated, use the default one # Also use the default one for review because it cannot be changed. refVersion = defaultRefVersion else: availableVersions = review._get_available_versions(Activity, uid, review=output_format == 'review') # Check if the indicated reference version is valid if refVersion not in [v.get('version') for v in availableVersions]: refVersion = defaultRefVersion newVersion = request.params.get('new', None) if newVersion is not None: try: newVersion = int(newVersion) except: newVersion = None if newVersion is None: # No new version indicated, use the default one newVersion = defaultNewVersion else: if availableVersions is None: availableVersions = review._get_available_versions(Activity, uid, review=output_format == 'review') # Check if the indicated new version is valid if newVersion not in [v.get('version') for v in availableVersions]: newVersion = defaultNewVersion if output_format == 'review': # If the Activities are to be reviewed, only the changes which were # applied to the newVersion are of interest activities, recalculated = review.get_comparison(Activity, uid, refVersion, newVersion) else: # If the Activities are compared, the versions as they are stored # in the database are of interest, without any recalculation activities = [ activity_protocol3.read_one_by_version(request, uid, refVersion, geometry='full', translate=False ), activity_protocol3.read_one_by_version(request, uid, newVersion, geometry='full', translate=False ) ] templateValues = renderReadonlyCompareForm(request, 'activities', activities[0], activities[1], review=output_format == 'review') # Collect metadata for the reference version refMetadata = {} if activities[0] is not None: refMetadata = activities[0].get_metadata(request) # Collect metadata and missing keys for the new version newMetadata = {} missingKeys = [] reviewable = False if activities[1] is not None: activities[1].mark_complete(get_mandatory_keys(request, 'a', False)) missingKeys = activities[1]._missing_keys localizer = get_localizer(request) if localizer.locale_name != 'en': db_lang = Session.query(Language).filter(Language.locale == localizer.locale_name).first() missingKeys = get_translated_db_keys(A_Key, missingKeys, db_lang) missingKeys = [m[1] for m in missingKeys] newMetadata = activities[1].get_metadata(request) reviewable = (len(missingKeys) == 0 and 'reviewableMessage' in templateValues and templateValues['reviewableMessage'] is None) if output_format == 'review': pendingVersions = [] if availableVersions is None: availableVersions = review._get_available_versions(Activity, uid, review=output_format == 'review') for v in sorted(availableVersions, key=lambda v:v.get('version')): if v.get('status') == 1: pendingVersions.append(v.get('version')) templateValues['pendingVersions'] = pendingVersions templateValues.update({ 'identifier': uid, 'refVersion': refVersion, 'refMetadata': refMetadata, 'newVersion': newVersion, 'newMetadata': newMetadata, 'missingKeys': missingKeys, 'reviewable': reviewable, 'recalculated': recalculated, 'profile': get_current_profile(request), 'locale': get_current_locale(request) }) if output_format == 'review': return render_to_response( getTemplatePath(request, 'activities/review.mak'), templateValues, request ) else: return render_to_response( getTemplatePath(request, 'activities/compare.mak'), templateValues, request ) elif output_format == 'geojson': # A version is required version = request.params.get('v', None) if version is None: raise HTTPBadRequest('You must specify a version as parameter ?v=X') translate = request.params.get('translate', 'true').lower() == 'true' activities = activity_protocol3.read_one_geojson_by_version(request, uid, version, translate=translate) return render_to_response('json', activities, request) elif output_format == 'formtest': # Test if an Activity is valid according to the form configuration activities = activity_protocol3.read_one(request, uid=uid, public=False, translate=False) version = request.params.get('v', None) if activities and 'data' in activities and len(activities['data']) != 0: for a in activities['data']: if 'version' in a: if version is None: version = str(a['version']) if str(a['version']) == version: categorylist = getCategoryList(request, 'activities') return render_to_response('json', checkValidItemjson(categorylist, a), request) return HTTPNotFound() # Output the areal statistics for the requested activity based on the # Web Processing Service elif output_format == 'statistics': # Try to get the base URL to the web processing service which provides # the areal statistics. # If no web processing service is configured, it is assumed that the # platform does not provide the areal statistics try: wps_host = request.registry.settings['lmkp.base_wps'] except KeyError: raise HTTPNotFound() spatial_accuracy_map = get_spatial_accuracy_map(request) # Check if the spatial accuracy map is configured in the application.yml # file if spatial_accuracy_map is None: raise HTTPNotFound() # Show the details of an Activity by rendering the form in readonly # mode. activities = activity_protocol3.read_one(request, uid=uid, public=False, translate=False) activity = activities['data'][0] coords = activity['geometry']['coordinates'] for taggroup in activity['taggroups']: if taggroup['main_tag']['key'] == _(u"Spatial Accuracy"): spatial_accuracy = taggroup['main_tag']['value'] buffer = spatial_accuracy_map[spatial_accuracy] wps_parameters = { "ServiceProvider": "", "metapath": "", "Service": "WPS", "Request": "Execute", "Version": "1.0.0", "Identifier": "BufferStatistics", "DataInputs": "lon=%s;lat=%s;epsg=4326;buffer=%s" % (coords[0], coords[1], buffer), "RawDataOutput": 'bufferstatistics@mimeType=application/json' } if not wps_host.endswith("?"): wps_host = "%s?" % wps_host for k, v in wps_parameters.items(): wps_host = "%s%s=%s&" % (wps_host, k, v) log.debug("Accessing: %s" % wps_host) try: handle = urllib.urlopen(wps_host) except IOError: return HTTPInternalServerError("Remote server not accessible.") templateValues = json.loads(handle.read()) templateValues['uid'] = uid templateValues['shortuid'] = uid.split("-")[0] return render_to_response( getTemplatePath(request, 'activities/statistics.mak'), templateValues, request ) else: # If the output format was not found, raise 404 error raise HTTPNotFound()
def review(self): """ Review a pending :term:`Stakeholder` version. A review can only be done by moderators. POST parameters: ``identifier`` (str): An :term:`Stakeholder` :term:`UID`. ``version`` (int): The version of the :term:`Stakeholder` to be reviewed ``review_decision`` (str): One of ``approve`` or ``reject``. ``review_comment`` (str): An optional comment to be stored with the review. ``camefrom`` (uid): An optional :term:`Activity` :term:`UID` to return back to after review. Returns: ``HTTPResponse``. If the review was successful, the history page of the :term:`Stakeholder` is returned. """ is_logged_in, is_moderator = get_user_privileges(self.request) if not is_logged_in: raise HTTPUnauthorized('User is not logged in.') if not is_moderator: raise HTTPUnauthorized( 'User has no permissions to add a review.') # Query new version of Stakeholder stakeholder = Session.query(Stakeholder).\ filter( Stakeholder.stakeholder_identifier == self.request.POST[ 'identifier']).\ filter(Stakeholder.version == self.request.POST['version']).\ first() if stakeholder is None: raise HTTPUnauthorized('The Item was not found') review_decision = self.request.POST['review_decision'] if review_decision == 'approve': review_decision = 1 elif review_decision == 'reject': review_decision = 2 else: raise HTTPBadRequest('No valid review decision') # Only check for mandatory keys if the new version is to be approved # and if it is not to be deleted (in which case it has no tag groups) if review_decision == 1 and len(stakeholder.tag_groups) > 0: mandatory_keys = get_mandatory_keys(self.request, 'sh') stakeholder_keys = Session.query(SH_Key.key).\ join(SH_Tag).\ join(SH_Tag_Group, SH_Tag.fk_tag_group == SH_Tag_Group.id).\ filter(SH_Tag_Group.stakeholder == stakeholder) keys = [] for k in stakeholder_keys.all(): keys.append(k.key) for mk in mandatory_keys: if mk not in keys: raise HTTPBadRequest( 'Not all mandatory keys are provided') review = stakeholder_protocol._add_review( self.request, stakeholder, Stakeholder, self.request.user, review_decision, self.request.POST.get('review_comment', '')) review_success = review.get('success', False) if review_success: self.request.session.flash(review.get('msg'), 'success') else: if review.get('msg') is None: raise HTTPBadRequest('Unknown error') self.request.session.flash(review.get('msg'), 'error') # Redirect to moderation view of Activity if camefrom parameter is # available camefrom = self.request.POST.get('camefrom', '') if camefrom != '': return HTTPFound(self.request.route_url( 'activities_read_one', output='review', uid=camefrom)) return HTTPFound(location=self.request.route_url( 'stakeholders_read_one_history', output='html', uid=stakeholder.identifier))
def read_one(self, public=False): """ Return one :term:`Stakeholder`. .. seealso:: :ref:`read-one` Read one :term:`Stakeholder` or one version of a :term:`Stakeholder`. By default, this is the latest visible version to the current user. This means that logged in users can see their own pending version and moderators of the current profile can see a pending version as well. If you don't want to see a version pending, consider using :class:`lmkp.views.stakeholders.StakeholderView.read_one_public` instead. Args: ``public`` (bool): A boolean indicating to return only a version visible to the public (eg. pending) or not. Matchdict parameters: ``/stakeholders/{output}/{uid}`` ``output`` (str): If the output format is not valid, a 404 Response is returned. The following output formats are supported: ``json``: Return the :term:`Stakeholder` as JSON. All versions visible to the current user are returned. ``html``: Return the :term:`Stakeholder` as HTML (eg. the `Detail View`). ``form``: Returns the form to edit an existing :term:`Stakeholder`. ``compare``: Return the page to compare two versions of the :term:`Stakeholder`. ``review``: Return the page to review a pending version of a :term:`Stakeholder`. ``uid`` (str): An :term:`Stakeholder` :term:`UID`. Request parameters: ``translate`` (bool): Return translated values or not. This is only valid for the output format ``json``. ``v`` (int): Indicate a specific version to return. This is only valid for the output formats ``html`` and ``form``. ``camefrom`` (uid): Only valid for output format ``review``. Indicate a :term:`Activity` to return to after reviewing the :term:`Stakeholder`. ``ref`` (int) and ``new`` (int): Indicate specific versions. This is only valid for the output formats ``compare`` and ``review``. Returns: ``HTTPResponse``. Either a HTML or a JSON response. """ output_format = get_output_format(self.request) uid = self.request.matchdict.get('uid', None) if validate_uuid(uid) is not True: raise HTTPNotFound() if output_format == 'json': translate = self.request.params.get( 'translate', 'true').lower() == 'true' item = stakeholder_protocol.read_one( self.request, uid=uid, public=public, translate=translate) return render_to_response('json', item, self.request) elif output_format == 'html': version = self.request.params.get('v', None) item = stakeholder_protocol.read_one( self.request, uid=uid, public=public, translate=False) for i in item.get('data', []): item_version = i.get('version') if version is None: # If there was no version provided, show the first # version visible to the user version = str(item_version) if str(item_version) == version: template_values = self.get_base_template_values() template_values.update(renderReadonlyForm( self.request, 'stakeholders', i)) template_values.update({ 'uid': uid, 'shortuid': shorten_uuid(uid), 'version': version, 'site_key': comments_sitekey(self.request)['site_key'], 'comments_url': self.request.registry.settings[ 'lmkp.comments_url'] }) return render_to_response( get_customized_template_path( self.request, 'stakeholders/details.mak'), template_values, self.request) return HTTPNotFound() elif output_format == 'form': is_logged_in, __ = get_user_privileges(self.request) if not is_logged_in: raise HTTPForbidden() version = self.request.params.get('v', None) item = stakeholder_protocol.read_one( self.request, uid=uid, public=False, translate=False) for i in item.get('data', []): item_version = i.get('version') if version is None: # If there was no version provided, show the first # version visible to the user version = str(item_version) if str(item_version) == version: template_values = renderForm( self.request, 'stakeholders', itemJson=i) if isinstance(template_values, Response): return template_values template_values.update(self.get_base_template_values()) return render_to_response( get_customized_template_path( self.request, 'stakeholders/form.mak'), template_values, self.request) return HTTPNotFound() elif output_format in ['review', 'compare']: if output_format == 'review': # Only moderators can see the review page. is_logged_in, is_moderator = get_user_privileges(self.request) if not is_logged_in or not is_moderator: raise HTTPForbidden() review = StakeholderReview(self.request) is_review = output_format == 'review' available_versions = review._get_available_versions( Stakeholder, uid, review=is_review) recalculated = False default_ref_version, default_new_version = review.\ _get_valid_versions(Stakeholder, uid) try: ref_version = int(self.request.params.get('ref')) except: ref_version = None # For review or if no valid reference version is provided, use the # default reference version. if (output_format == 'review' or ref_version is None or ref_version not in [ v.get('version') for v in available_versions]): ref_version = default_ref_version try: new_version = int(self.request.params.get('new')) except: new_version = None if new_version is None or new_version not in [ v.get('version') for v in available_versions]: new_version = default_new_version if output_format == 'review': # If the Items are to be reviewed, only the changes which were # applied to the new_version are of interest items, recalculated = review.get_comparison( Stakeholder, uid, ref_version, new_version) else: # If the Items are to be compared, the versions as they are # stored in the database are of interest, without any # recalculation items = [ stakeholder_protocol.read_one_by_version( self.request, uid, ref_version, translate=False ), stakeholder_protocol.read_one_by_version( self.request, uid, new_version, translate=False ) ] template_values = renderReadonlyCompareForm( self.request, 'stakeholders', items[0], items[1], review=is_review) # Collect the metadata ref_metadata = {} new_metadata = {} missing_keys = [] reviewable = False if items[0] is not None: ref_metadata = items[0].get_metadata(self.request) # Collect metadata and missing keys for the new version if items[1] is not None: new_metadata = items[1].get_metadata(self.request) items[1].mark_complete(get_mandatory_keys( self.request, 'sh', False)) missing_keys = items[1]._missing_keys localizer = get_localizer(self.request) if localizer.locale_name != 'en': db_lang = Session.query(Language).filter( Language.locale == localizer.locale_name).first() missing_keys = get_translated_db_keys( SH_Key, missing_keys, db_lang) missing_keys = [m[1] for m in missing_keys] reviewable = (len(missing_keys) == 0 and 'reviewableMessage' in template_values and template_values['reviewableMessage'] is None) if output_format == 'review': pending_versions = [] for v in sorted( available_versions, key=lambda v: v.get('version')): if v.get('status') == 1: pending_versions.append(v.get('version')) template_values['pendingVersions'] = pending_versions template_values.update(self.get_base_template_values()) template_values.update({ 'identifier': uid, 'refVersion': ref_version, 'refMetadata': ref_metadata, 'newVersion': new_version, 'newMetadata': new_metadata, 'missingKeys': missing_keys, 'reviewable': reviewable, 'recalculated': recalculated, 'camefrom': self.request.params.get('camefrom', ''), }) if output_format == 'review': template = get_customized_template_path( self.request, 'stakeholders/review.mak') else: template = get_customized_template_path( self.request, 'stakeholders/compare.mak') return render_to_response(template, template_values, self.request) elif output_format == 'formtest': version = self.request.params.get('v', None) # Test if an Item is valid according to the form configuration items = stakeholder_protocol.read_one( self.request, uid=uid, public=False, translate=False) for i in item.get('data', []): item_version = i.get('version') if version is None: # If there was no version provided, show the first # version visible to the user version = str(item_version) if str(item_version) == version: categorylist = getCategoryList( self.request, 'stakeholders') return render_to_response( 'json', checkValidItemjson(categorylist, i), self.request) return HTTPNotFound() else: raise HTTPNotFound()