From ce374b0b350e8ec7b0b3e37582658bfe578d12ed Mon Sep 17 00:00:00 2001 From: Edwin Henneken Date: Fri, 4 Sep 2020 07:51:29 -0400 Subject: [PATCH 1/6] feedback forms machinery --- adsws/feedback/config.py | 17 +- .../templates/associated_articles.txt | 16 ++ .../feedback/templates/missing_references.txt | 7 + adsws/feedback/templates/new_record.txt | 13 ++ adsws/feedback/templates/updated_record.txt | 6 + adsws/feedback/utils.py | 16 +- adsws/feedback/views.py | 152 ++++++++++++++---- adsws/tests/stubdata/__init__.py | 0 adsws/tests/stubdata/associated_errata.py | 13 ++ adsws/tests/stubdata/associated_other.py | 16 ++ adsws/tests/stubdata/corrected_abstract.py | 61 +++++++ adsws/tests/stubdata/missing_references.py | 26 +++ adsws/tests/stubdata/new_abstract.py | 79 +++++++++ adsws/tests/test_feedback.py | 145 ++++++++++++++++- 14 files changed, 526 insertions(+), 41 deletions(-) create mode 100644 adsws/feedback/templates/associated_articles.txt create mode 100644 adsws/feedback/templates/missing_references.txt create mode 100644 adsws/feedback/templates/new_record.txt create mode 100644 adsws/feedback/templates/updated_record.txt create mode 100644 adsws/tests/stubdata/__init__.py create mode 100644 adsws/tests/stubdata/associated_errata.py create mode 100644 adsws/tests/stubdata/associated_other.py create mode 100644 adsws/tests/stubdata/corrected_abstract.py create mode 100644 adsws/tests/stubdata/missing_references.py create mode 100644 adsws/tests/stubdata/new_abstract.py diff --git a/adsws/feedback/config.py b/adsws/feedback/config.py index 3d18912..5564480 100644 --- a/adsws/feedback/config.py +++ b/adsws/feedback/config.py @@ -12,7 +12,22 @@ FEEDBACK_SLACK_END_POINT = 'https://hooks.slack.com/services/TOKEN/TOKEN' FEEDBACK_SLACK_EMOJI = ':interrobang:' -FEEDBACK_EMAIL = 'adshelp@cfa.harvard.edu' +DEFAULT_EMAIL = 'adshelp@cfa.harvard.edu' +# Feedback processing depends on 'origin' attribute supplied in POST data +FEEDBACK_FORMS_ORIGIN = 'user_submission' +BBB_FEEDBACK_ORIGIN = 'bbb_feedback' +# Email template to be applied based on email subject +FEEDBACK_TEMPLATES = { + 'Missing References': 'missing_references.txt', + 'Associated Articles': 'associated_articles.txt', + 'Updated Record': 'updated_record.txt', + 'New Record': 'new_record.txt' +} +# Override defaul recipient based on email subject (key) +FEEDBACK_EMAILS = { + 'Missing References': 'ads@cfa.harvard.edu' +} + GOOGLE_RECAPTCHA_ENDPOINT = 'https://www.google.com/recaptcha/api/siteverify' GOOGLE_RECAPTCHA_PRIVATE_KEY = 'MY_PRIVATE_KEY' CORS_DOMAINS = ['https://ui.adsabs.harvard.edu'] diff --git a/adsws/feedback/templates/associated_articles.txt b/adsws/feedback/templates/associated_articles.txt new file mode 100644 index 0000000..1e33d6f --- /dev/null +++ b/adsws/feedback/templates/associated_articles.txt @@ -0,0 +1,16 @@ +From: {{data.name}} +Address: {{data.email}} + +Correlated articles: +{% if 'other' == data.relationship -%} + {{data.custom_name}}: {{data.source}} {{data.target[0]}} +{% else -%} + {{data.relationship}}: {{data.source}} {{data.target[0]}} + {% if data.target|length > 1 -%} + {% for bibcode in data.target[1:] -%} + {% set indent_count = data.relationship | length -%} + {{bibcode | indent(indent_count + 17, true)}} + {% endfor %} + {% endif %} +{% endif %} + diff --git a/adsws/feedback/templates/missing_references.txt b/adsws/feedback/templates/missing_references.txt new file mode 100644 index 0000000..2b47dd0 --- /dev/null +++ b/adsws/feedback/templates/missing_references.txt @@ -0,0 +1,7 @@ +From: {{data.name}} +Address: {{data.email}} + +Missing references: +{% for reference in data.references -%} +{{reference.citing}}[tab]{{reference.cited}}[tab]{{reference.refstring}} +{% endfor %} diff --git a/adsws/feedback/templates/new_record.txt b/adsws/feedback/templates/new_record.txt new file mode 100644 index 0000000..1fcbc63 --- /dev/null +++ b/adsws/feedback/templates/new_record.txt @@ -0,0 +1,13 @@ +From: {{data.name}} +Address: {{data.email}} + +Abstract data for new record. Summary: + +Collection: {{data.new.collection[0]}} + +%R {{data.new.bibcode}} +%T {{data.new.title}} +%A {{data.new.author_list}} +%D {{data.new.publicationDate}} +%J {{data.new.publication}} +%B {{data.new.abstract}} \ No newline at end of file diff --git a/adsws/feedback/templates/updated_record.txt b/adsws/feedback/templates/updated_record.txt new file mode 100644 index 0000000..9adec08 --- /dev/null +++ b/adsws/feedback/templates/updated_record.txt @@ -0,0 +1,6 @@ +From: {{data.name}} +Address: {{data.email}} + +Correction for {{data.original.bibcode}}: + +{{data.diff}} \ No newline at end of file diff --git a/adsws/feedback/utils.py b/adsws/feedback/utils.py index 89192f2..fe5cd2d 100644 --- a/adsws/feedback/utils.py +++ b/adsws/feedback/utils.py @@ -5,14 +5,20 @@ """ from flask import current_app from flask.ext.mail import Message +import json -def send_feedback_email(name, sender, feedback): - help_email = current_app.config['FEEDBACK_EMAIL'] - msg = Message(subject="Bumblebee Feedback from %s (%s)" % (name, sender), +def send_feedback_email(name, sender, subject, data, attachments=None): + # Allow the default recipient to be overriden depending on email subject + help_email = current_app.config['FEEDBACK_EMAILS'].get(subject, current_app.config['DEFAULT_EMAIL']) + msg = Message(subject="%s from %s (%s)" % (subject, name, sender), recipients=[help_email], - sender=("adshelp", help_email), + sender=("ADS", help_email), reply_to=(name, sender), - body=feedback) + body=data) + if attachments: + for attachment in attachments: + # Each entry is a tuple of file name and JSON data + msg.attach(attachment[0], "application/json", json.dumps(attachment[1])) current_app.extensions['mail'].send(msg) return msg diff --git a/adsws/feedback/views.py b/adsws/feedback/views.py index 743e495..e9e9aeb 100644 --- a/adsws/feedback/views.py +++ b/adsws/feedback/views.py @@ -5,13 +5,14 @@ import json import requests -from flask import current_app, request +from flask import current_app, request, render_template from flask.ext.restful import Resource from adsws.ext.ratelimiter import ratelimit, scope_func from adsws.feedback.utils import err from adsws.accounts.utils import verify_recaptcha, get_post_data from werkzeug.exceptions import BadRequestKeyError from utils import send_feedback_email +from urllib import unquote API_DOCS = 'https://github.com/adsabs/adsabs-dev-api' ERROR_UNVERIFIED_CAPTCHA = dict( @@ -23,6 +24,18 @@ .format(API_DOCS), number=404 ) +ERROR_FEEDBACKFORM_PROBLEM = dict( + body='Error while processing feedback form data', + number=404 +) +ERROR_EMAILBODY_PROBLEM = dict( + body='Unable to generate email body', + number=404 +) +ERROR_UNKNOWN_ORIGIN = dict( + body='No origin provided in feedback data', + number=404 +) ERROR_WRONG_ENDPOINT = dict( body='Re-directed due to malformed request or incorrect end point', number=302 @@ -69,7 +82,7 @@ def prettify_post(post_data): feedback_email = 'no email sent' if post_data.has_key('_replyto') and post_data.has_key('name'): try: - res = send_feedback_email(name, reply_to, text) + res = send_feedback_email(name, reply_to, "Bumblebee Feedback", text) feedback_email = 'success' except Exception as e: current_app.logger.info('Sending feedback mail failed: %s' % str(e)) @@ -86,6 +99,63 @@ def prettify_post(post_data): } return prettified_data + @staticmethod + def create_email_body(post_data): + """ + Takes the data from the feedback forms and fills out the appropriate template + :param post_data: the post data to fill out email template, dictionary expected + :return: email body, string + """ + # Retrieve the appropriate template + template = current_app.config['FEEDBACK_TEMPLATES'].get(post_data.get('_subject')) + # For abstract corrections, the POST payload has a "diff" attribute that contains + # the updated fields in Github "diff" format, URL encoded. For display purposes, + # this needs to be decoded. + if post_data.has_key('diff'): + post_data['diff'] = unquote(post_data['diff']) + # In the case of a new record the mail body will show a summary + # In this summary it's easier to show a author list in the form of a string + # We also attach the JSON data of the new record as a file + if post_data.get('_subject') == 'New Record': + try: + post_data['new']['author_list'] = ";".join([a['name'] for a in post_data['new']['authors']]) + except: + post_data['new']['author_list'] = "" + # Construct the email body + body = render_template(template, data=post_data) + # If there is a way to insert tabs in the template, it should happen there + # (currently, this only happens in the missing_references.txt template) + body = body.replace('[tab]','\t') + + return body + + @staticmethod + def process_feedbackform_submission(post_data, body): + """ + Takes the data from the feedback forms and fills out the appropriate template + :param post_data: the post data to fill out email template, dictionary expected + :param body: email body + :return: success message, string + """ + # List to hold attachments to be sent along + attachments=[] + if post_data.get('_subject') == 'New Record': + attachments.append(('new_record.json', post_data['new'])) + if post_data.get('_subject') == 'Updated Record': + attachments.append(('updated_record.json', post_data['new'])) + attachments.append(('original_record.json', post_data['original'])) + + feedback_email = 'no email sent' + if post_data.has_key('email') and post_data.has_key('name'): + try: + res = send_feedback_email(post_data['name'], post_data['name'], post_data['_subject'], body, attachments=attachments) + feedback_email = 'success' + except Exception as e: + current_app.logger.info('Sending feedback mail failed: %s' % str(e)) + feedback_email = 'failed' + + return feedback_email + def post(self): """ HTTP POST request @@ -93,43 +163,61 @@ def post(self): """ post_data = get_post_data(request) + current_app.logger.info('Received feedback: {0}'.format(post_data)) + if not post_data.get('g-recaptcha-response', False) or \ not verify_recaptcha(request): current_app.logger.info('The captcha was not verified!') return err(ERROR_UNVERIFIED_CAPTCHA) else: current_app.logger.info('Skipped captcha!') + origin = post_data.get('origin', 'NA') + if origin == current_app.config['FEEDBACK_FORMS_ORIGIN']: + current_app.logger.info('Received data from feedback form "{0}" from {1} ({2})'.format(post_data.get('_subject'), post_data.get('name'), post_data.get('email'))) + try: + email_body = self.create_email_body(post_data) + except Exception as error: + current_app.logger.error('Fatal error creating email body: {0}'.format(error)) + return err(ERROR_EMAILBODY_PROBLEM) + try: + email_sent = self.process_feedbackform_submission(post_data, email_body) + except Exception as error: + current_app.logger.error('Fatal error while processing feedback form data: {0}'.format(error)) + return err(ERROR_FEEDBACKFORM_PROBLEM) + elif origin == current_app.config['BBB_FEEDBACK_ORIGIN']: + try: + current_app.logger.info('Prettifiying post data: {0}' + .format(post_data)) + formatted_post_data = json.dumps(self.prettify_post(post_data)) + current_app.logger.info('Data prettified: {0}' + .format(formatted_post_data)) + except BadRequestKeyError as error: + current_app.logger.error('Missing keywords: {0}, {1}' + .format(error, post_data)) + return err(ERROR_MISSING_KEYWORDS) - try: - current_app.logger.info('Prettifiying post data: {0}' - .format(post_data)) - formatted_post_data = json.dumps(self.prettify_post(post_data)) - current_app.logger.info('Data prettified: {0}' - .format(formatted_post_data)) - except BadRequestKeyError as error: - current_app.logger.error('Missing keywords: {0}, {1}' - .format(error, post_data)) - return err(ERROR_MISSING_KEYWORDS) - - try: - slack_response = requests.post( - url=current_app.config['FEEDBACK_SLACK_END_POINT'], - data=formatted_post_data, - timeout=60 - ) - except (requests.exceptions.ConnectionError, requests.exceptions.Timeout): - return b'504 Gateway Timeout', 504 - current_app.logger.info('slack response: {0}' - .format(slack_response.status_code)) - - # Slack annoyingly redirects if you have the wrong end point - current_app.logger.info('Slack API' in slack_response.text) - - if 'Slack API' in slack_response.text: - return err(ERROR_WRONG_ENDPOINT) - elif slack_response.status_code == 200: - return {}, 200 + try: + slack_response = requests.post( + url=current_app.config['FEEDBACK_SLACK_END_POINT'], + data=formatted_post_data, + timeout=60 + ) + except (requests.exceptions.ConnectionError, requests.exceptions.Timeout): + return b'504 Gateway Timeout', 504 + current_app.logger.info('slack response: {0}' + .format(slack_response.status_code)) + + # Slack annoyingly redirects if you have the wrong end point + current_app.logger.info('Slack API' in slack_response.text) + + if 'Slack API' in slack_response.text: + return err(ERROR_WRONG_ENDPOINT) + elif slack_response.status_code == 200: + return {}, 200 + else: + return {'msg': 'Unknown error'}, slack_response.status_code else: - return {'msg': 'Unknown error'}, slack_response.status_code + return err(ERROR_UNKNOWN_ORIGIN) + return {}, 200 diff --git a/adsws/tests/stubdata/__init__.py b/adsws/tests/stubdata/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/adsws/tests/stubdata/associated_errata.py b/adsws/tests/stubdata/associated_errata.py new file mode 100644 index 0000000..0c415c7 --- /dev/null +++ b/adsws/tests/stubdata/associated_errata.py @@ -0,0 +1,13 @@ +data = { + "origin": "user_submission", + "g-recaptcha-response": "correct_response", + "_subject": "Associated Articles", + "name": "Tim Hostetler", + "email": "twhostetler0@gmail.com", + "source": "2014AJ....147..124M", + "target": [ + "2020PDU....3000620S", + "1999ApJ...511L..65Y" + ], + "relationship": "errata" +} \ No newline at end of file diff --git a/adsws/tests/stubdata/associated_other.py b/adsws/tests/stubdata/associated_other.py new file mode 100644 index 0000000..e7ef1ae --- /dev/null +++ b/adsws/tests/stubdata/associated_other.py @@ -0,0 +1,16 @@ +data = { + "origin": "user_submission", + "g-recaptcha-response": "correct_response", + "_subject": "Associated Articles", + "name": "Tim Hostetler", + "email": "twhostetler0@gmail.com", + "source": "2014AJ....147..124M", + "target": [ + "2020PDU....3000620S", + "1999ApJ...511L..65Y" + ], + "relationship": "other", + "custom_name": "TEST TEST TEST" +} + +response = 'From: Tim Hostetler\nAddress: twhostetler0@gmail.com\n\nCorrelated articles:\nTEST TEST TEST: 2014AJ....147..124M 2020PDU....3000620S\n\n' \ No newline at end of file diff --git a/adsws/tests/stubdata/corrected_abstract.py b/adsws/tests/stubdata/corrected_abstract.py new file mode 100644 index 0000000..1f1afa6 --- /dev/null +++ b/adsws/tests/stubdata/corrected_abstract.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +data = { + "origin": "user_submission", + "g-recaptcha-response": "correct_response", + "_subject": "Updated Record", + "original": { + "comments": "test", + "recaptcha": "03AGdBq27Ni592wVKdm1Fk-nj_7pygAegrToYNuEGR3rUb8kMBx9lvwRmBpEc9qDVoqFlXpN9nDtNiIS4QwaUOPOmzPPg6_q74U9XDazRXDhGFMBYMh_a18EtMBaIXMGKU4YUAWSViQ5QEK8ExCZDaB_tSDRFzAgRlUddDUQSouwhtw7QYiR7NC0vWV8Yx2i43fBBEomI4UlJCyuSh7ZobS5MGC9JvgXW9O5uwjB6HLZ9znd0v_fAKXKJNmc-Kog7ZIIvEFXPJFPgdNbevm3vu1IxRx5SYAsztmYwK8sQ6K612IWXH7nRebF-2a5-yukXmpIh_S_AUigm8TqIjcX19lI_ZBNAlsjagH-wg2nSmPks6vva4AcPHaLllQURKsL-TNScnqWLJ0GpZ", + "name": "Tim Hostetler", + "email": "twhostetler0@gmail.com", + "entryType": "edit", + "bibcode": "2021NewA...8301464S", + "title": "Dynamical analysis with thermodynamic aspects of anisotropic dark energy bounce cosmological model in f(R, G) gravity", + "publication": "New Astronomy, Volume 83, article id. 101464.", + "publicationDate": "2021-02-00", + "abstract": "Present analysis dedicated to the dynamical investigation of anisotropic dark energy LRS Bianchi type-I cosmological model in the context of modified gravity in which Langrangian be the arbitrary function of Ricci scalar and Gouss-Bonnet invariant say f(R, G) gravity in the way of anisotropic fluid. The classification of the field equations towards f(R , G) =f0RmG 1 - m make available that the model is purely accelerating corresponds to 0 ≤ q ≤ - 1 . We govern the features of the derived cosmological model in view of the hybrid law inflation in bounce form (which involve power and de-Sitter cosmology) for the average scale factor. Also discussed the singularity of the model with the help of curvature of the model. It is observed that the model is fully engaged with both matter which exist initially for short expansion and dark energy dominated era and rests existing in quintessence dominated era and for sufficiently large time derived model forecasts that the anisotropy of the model will damp out and the Universe will turn out to be isotropic one and also observed that for quintessence dominated era the temperature and entropy density of anticipated model are positive definite along with some physical and kinematical parameters of the bounce model is also discussed in details.", + "authors": [ + { + "id": "Shekh, S. H._0", + "position": 0, + "name": "Shekh, S. H.", + "aff": "Department of Mathematics, S. P. M. Science and Gilani Arts Commerece College Ghatanji, Maharashtra 445301, India", + "orcid": "" + } + ], + "keywords": ["95.36.+x", "04.50.kd", "98.80.Jk"], + "urls": [ + + ] + }, + "new": { + "comments": "test", + "bibcode": "2021NewA...8301464S", + "title": "Dynamical analysis with thermodynamic aspects of anisotropic dark energy bounce cosmological model in f(R, G) gravity", + "publication": "New Astronomy, Volume 83, article id. 101464.", + "publicationDate": "2021-02-00", + "abstract": "Present analysis dedicated to the dynamical investigation of anisotropic dark energy LRS Bianchi type-I cosmological model in the context of modified gravity in which Langrangian be the arbitrary function of Ricci scalar and Gouss-Bonnet invariant say f(R, G) gravity in the way of anisotropic fluid. The classification of the field equations towards f(R , G) =f0RmG 1 - m make available that the model is purely accelerating corresponds to 0 ≤ q ≤ - 1 . We govern the features of the derived cosmological model in view of the hybrid law inflation in bounce form (which involve power and de-Sitter cosmology) for the average scale factor. Also discussed the singularity of the model with the help of curvature of the model. It is observed that the model is fully engaged with both matter which exist initially for short expansion and dark energy dominated era and rests existing in quintessence dominated era and for sufficiently large time derived model forecasts that the anisotropy of the model will damp out and the Universe will turn out to be isotropic one and also observed that for quintessence dominated era the temperature and entropy density of anticipated model are positive definite along with some physical and kinematical parameters of the bounce model is also discussed in details.", + "authors": [ + { + "id": "Shekh, S. H._0", + "position": 0, + "name": "Shekh, S. H.", + "aff": "Department of Mathematics, S. P. M. Science and Gilani Arts Commerece College Ghatanji, Maharashtra 445301, India", + "orcid": "" + } + ], + "keywords": ["95.36.+x", "04.50.kd", "98.80.Jk"], + "urls": [ + + ], + "collection": [ + "astronomy", + "physics" + ] + }, + "name": "Tim Hostetler", + "email": "twhostetler0@gmail.com", + "diff": "%0A%20%20%3E%3E%3E%3E%20Title%0A%20%20test%0A%20%20%3C%3C%3C%3C%0A%0A%20%20%3E%3E%3E%3E%20Publication%0A%20%20test%0A%20%20%3C%3C%3C%3C%0A%0A%20%20%3E%3E%3E%3E%20PublicationDate%0A%20%202020-01%0A%20%20%3C%3C%3C%3C%0A%0A%20%20%3E%3E%3E%3E%20Comments%0A%20%20test%0A%20%20%3C%3C%3C%3C" +} + +response = 'From: Tim Hostetler\nAddress: twhostetler0@gmail.com\n\nCorrection for 2021NewA...8301464S:\n\n\n >>>> Title\n test\n <<<<\n\n >>>> Publication\n test\n <<<<\n\n >>>> PublicationDate\n 2020-01\n <<<<\n\n >>>> Comments\n test\n <<<<' \ No newline at end of file diff --git a/adsws/tests/stubdata/missing_references.py b/adsws/tests/stubdata/missing_references.py new file mode 100644 index 0000000..221f6ad --- /dev/null +++ b/adsws/tests/stubdata/missing_references.py @@ -0,0 +1,26 @@ +data = { + "origin": "user_submission", + "g-recaptcha-response": "correct_response", + "_subject": "Missing References", + "name": "Tim Hostetler", + "email": "twhostetler0@gmail.com", + "references": [ + { + "citing": "2020arXiv200310949S", + "cited": "2021NewA...8301464S", + "refstring": "Shekh, S. H. (2021), New Astronomy, Volume 83, article id. 101464." + }, + { + "citing": "2021NewA...8201452A", + "cited": "2020PDU....3000664A", + "refstring": "Arora, S., et al. (2020), Physics of the Dark Universe, Volume 30, article id. 100664." + }, + { + "citing": "2020arXiv200310949S", + "cited": "2020PDU....3000620S", + "refstring": "Singh, K. N., et al. (2020), Physics of the Dark Universe, Volume 30, article id. 100620." + } + ] +} + +response = 'From: Tim Hostetler\nAddress: twhostetler0@gmail.com\n\nMissing references:\n2020arXiv200310949S\t2021NewA...8301464S\tShekh, S. H. (2021), New Astronomy, Volume 83, article id. 101464.\n2021NewA...8201452A\t2020PDU....3000664A\tArora, S., et al. (2020), Physics of the Dark Universe, Volume 30, article id. 100664.\n2020arXiv200310949S\t2020PDU....3000620S\tSingh, K. N., et al. (2020), Physics of the Dark Universe, Volume 30, article id. 100620.\n' \ No newline at end of file diff --git a/adsws/tests/stubdata/new_abstract.py b/adsws/tests/stubdata/new_abstract.py new file mode 100644 index 0000000..7587fea --- /dev/null +++ b/adsws/tests/stubdata/new_abstract.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +data = { + "origin": "user_submission", + "g-recaptcha-response": "correct_response", + "_subject": "New Record", + "original": { + "entryType": "new", + "name": "", + "email": "", + "collection": [ + "astronomy" + ], + "bibcode": "", + "title": "", + "authors": [ + + ], + "publication": "", + "publicationDate": "", + "urls": [ + { + "value": "" + } + ], + "abstract": "", + "keywords": [ + { + "value": "" + } + ], + "references": [ + { + "value": "" + } + ], + "comments": "", + "recaptcha": "" + }, + "new": { + "collection": [ + "astronomy" + ], + "bibcode": "", + "title": "test", + "authors": [ + { + "id": "Shekh, S. H._0", + "position": 0, + "name": "Shekh, S. H.", + "aff": "Department of Mathematics, S. P. M. Science and Gilani Arts Commerece College Ghatanji, Maharashtra 445301, India", + "orcid": "" + }, + { + "id": "Shekh, S. H._0", + "position": 0, + "name": "Foo, Bar", + "aff": "Department of Mathematics, S. P. M. Science and Gilani Arts Commerece College Ghatanji, Maharashtra 445301, India", + "orcid": "" + }, + ], + "publication": "test", + "publicationDate": "2020-01", + "urls": [ + { + "type": "none", + "value": "" + } + ], + "abstract": "Present analysis dedicated to the dynamical investigation of anisotropic dark energy LRS Bianchi type-I cosmological model in the context of modified gravity in which Langrangian be the arbitrary function of Ricci scalar and Gouss-Bonnet invariant say f(R, G) gravity in the way of anisotropic fluid. The classification of the field equations towards f(R , G) =f0RmG 1 - m make available that the model is purely accelerating corresponds to 0 ~ q ~ - 1 . We govern the features of the derived cosmological model in view of the hybrid law inflation in bounce form (which involve power and de-Sitter cosmology) for the average scale factor. Also discussed the singularity of the model with the help of curvature of the model. It is observed that the model is fully engaged with both matter which exist initially for short expansion and dark energy dominated era and rests existing in quintessence dominated era and for sufficiently large time derived model forecasts that the anisotropy of the model will damp out and the Universe will turn out to be isotropic one and also observed that for quintessence dominated era the temperature and entropy density of anticipated model are positive definite along with some physical and kinematical parameters of the bounce model is also discussed in details.", + "keywords": [], + "references": [], + "comments": "test" + }, + "name": "Tim Hostetler", + "email": "twhostetler0@gmail.com", + "diff": "" +} + +response = 'From: Tim Hostetler\nAddress: twhostetler0@gmail.com\n\nAbstract data for new record. Summary:\n\nCollection: astronomy\n\n%R \n%T test\n%A Shekh, S. H.;Foo, Bar\n%D 2020-01\n%J test\n%B Present analysis dedicated to the dynamical investigation of anisotropic dark energy LRS Bianchi type-I cosmological model in the context of modified gravity in which Langrangian be the arbitrary function of Ricci scalar and Gouss-Bonnet invariant say f(R, G) gravity in the way of anisotropic fluid. The classification of the field equations towards f(R , G) =f0RmG 1 - m make available that the model is purely accelerating corresponds to 0 ~ q ~ - 1 . We govern the features of the derived cosmological model in view of the hybrid law inflation in bounce form (which involve power and de-Sitter cosmology) for the average scale factor. Also discussed the singularity of the model with the help of curvature of the model. It is observed that the model is fully engaged with both matter which exist initially for short expansion and dark energy dominated era and rests existing in quintessence dominated era and for sufficiently large time derived model forecasts that the anisotropy of the model will damp out and the Universe will turn out to be isotropic one and also observed that for quintessence dominated era the temperature and entropy density of anticipated model are positive definite along with some physical and kinematical parameters of the bounce model is also discussed in details.' \ No newline at end of file diff --git a/adsws/tests/test_feedback.py b/adsws/tests/test_feedback.py index 6351b56..411d8d9 100644 --- a/adsws/tests/test_feedback.py +++ b/adsws/tests/test_feedback.py @@ -12,6 +12,7 @@ from flask.ext.testing import TestCase from httpretty import HTTPretty from adsws.feedback.views import SlackFeedback, verify_recaptcha +from adsws.tests.stubdata import missing_references, associated_other, associated_errata, new_abstract, corrected_abstract class GoogleRecaptchaService(object): @@ -155,7 +156,8 @@ def test_submitting_feedback(self): 'name': 'Commenter', 'comments': 'Why are my citations missing?', '_replyto': 'commenter@email.com', - 'g-recaptcha-response': 'correct_response' + 'g-recaptcha-response': 'correct_response', + 'origin': 'bbb_feedback' } # User presses submit on the feedback form @@ -167,6 +169,81 @@ def test_submitting_feedback(self): ) self.assertEqual(response.status_code, 200) + def test_submitting_missing_references(self): + """ + A generic test of the entire work flow of the feedback submission + end point: submissions of missing references + """ + + # User presses submit on the feedback form + url = url_for('slackfeedback') + with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: + response = self.client.post( + url, + data=json.dumps(missing_references.data) + ) + self.assertEqual(response.status_code, 200) + + def test_submitting_associated(self): + """ + A generic test of the entire work flow of the feedback submission + end point: submissions of associated records + """ + + # User presses submit on the feedback form + url = url_for('slackfeedback') + with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: + response = self.client.post( + url, + data=json.dumps(associated_errata.data) + ) + self.assertEqual(response.status_code, 200) + + def test_submitting_associated_other(self): + """ + A generic test of the entire work flow of the feedback submission + end point: submissions of associated records of type 'other' + """ + + # User presses submit on the feedback form + url = url_for('slackfeedback') + with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: + response = self.client.post( + url, + data=json.dumps(associated_other.data) + ) + self.assertEqual(response.status_code, 200) + + def test_submitting_new_abstract(self): + """ + A generic test of the entire work flow of the feedback submission + end point: submissions of new abstract + """ + + # User presses submit on the feedback form + url = url_for('slackfeedback') + with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: + response = self.client.post( + url, + data=json.dumps(new_abstract.data) + ) + self.assertEqual(response.status_code, 200) + + def test_submitting_corrected_abstract(self): + """ + A generic test of the entire work flow of the feedback submission + end point: submissions of new abstract + """ + + # User presses submit on the feedback form + url = url_for('slackfeedback') + with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: + response = self.client.post( + url, + data=json.dumps(corrected_abstract.data) + ) + self.assertEqual(response.status_code, 200) + def test_submitting_feedback_with_minimal_information(self): """ Check they can send minimal information to the end point @@ -174,7 +251,8 @@ def test_submitting_feedback_with_minimal_information(self): # User fills the user feedback form form_data = { 'comments': 'Why are my citations missing?', - 'g-recaptcha-response': 'correct_response' + 'g-recaptcha-response': 'correct_response', + 'origin': 'bbb_feedback' } # User presses submit on the feedback form @@ -195,7 +273,8 @@ def test_404_if_not_right_data(self): form_data = { 'name': 'Commenter', '_replyto': 'commenter@email.com', - 'g-recaptcha-response': 'correct_response' + 'g-recaptcha-response': 'correct_response', + 'origin': 'bbb_feedback' } # User presses submit on the feedback form @@ -206,7 +285,50 @@ def test_404_if_not_right_data(self): data=form_data ) self.assertEqual(response.status_code, 404) + + def test_404_if_not_right_origin(self): + """ + Checks the passed data. The endpoint expects specific values for the 'origin' attribute + """ + # User fills the user feedback form + form_data = { + 'name': 'Commenter', + '_replyto': 'commenter@email.com', + 'g-recaptcha-response': 'correct_response', + 'origin': 'foobar' + } + # User presses submit on the feedback form + url = url_for('slackfeedback') + with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: + response = self.client.post( + url, + data=form_data + ) + self.assertEqual(response.status_code, 404) + + def test_404_if_not_right_subject(self): + """ + Checks the passed data. For user submission feedback, the value _subject field + determines the email template. Exception is thrown when this has an unexpected value. + """ + # User fills the user feedback form + form_data = { + 'name': 'Commenter', + '_replyto': 'commenter@email.com', + 'g-recaptcha-response': 'correct_response', + 'origin': 'user_submission', + '_subject': 'foo' + } + + # User presses submit on the feedback form + url = url_for('slackfeedback') + with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: + response = self.client.post( + url, + data=form_data + ) + self.assertEqual(response.status_code, 404) class TestUnits(TestBase): """ @@ -307,6 +429,23 @@ def test_can_send_abritrary_keyword_values(self): for key in post_data_sent.keys(): self.assertEqual(post_data_sent[key], prettified_post_data[key]) + def test_email_body(self): + """ + + """ + + email_body = SlackFeedback().create_email_body(corrected_abstract.data) + self.assertEqual(email_body, corrected_abstract.response) + + email_body = SlackFeedback().create_email_body(new_abstract.data) + self.assertEqual(email_body, new_abstract.response) + + email_body = SlackFeedback().create_email_body(associated_other.data) + self.assertEqual(email_body, associated_other.response) + + email_body = SlackFeedback().create_email_body(missing_references.data) + self.assertEqual(email_body, missing_references.response) + def test_verify_google_recaptcha(self): """ Test the function responsible for contacting the google recaptcha API From 28d7e6467914f90cd97c41e085d5c4f6732f3ff5 Mon Sep 17 00:00:00 2001 From: Edwin Henneken Date: Tue, 8 Sep 2020 08:33:59 -0400 Subject: [PATCH 2/6] small addition --- adsws/feedback/views.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/adsws/feedback/views.py b/adsws/feedback/views.py index e9e9aeb..3e33ff6 100644 --- a/adsws/feedback/views.py +++ b/adsws/feedback/views.py @@ -186,6 +186,9 @@ def post(self): except Exception as error: current_app.logger.error('Fatal error while processing feedback form data: {0}'.format(error)) return err(ERROR_FEEDBACKFORM_PROBLEM) + if not email_sent: + # If the email could not be sent, we can still log the data submitted + current_app.logger.error('Sending of email failed. Feedback data submitted by {0} ({1}): {2}'.format(post_data, post_data.get('name'), post_data.get('email'))) elif origin == current_app.config['BBB_FEEDBACK_ORIGIN']: try: current_app.logger.info('Prettifiying post data: {0}' From 07cece9147c7d690ee765d1ad2be259e4537daac Mon Sep 17 00:00:00 2001 From: Edwin Henneken Date: Fri, 25 Sep 2020 12:08:38 -0400 Subject: [PATCH 3/6] PR feedback changes --- adsws/feedback/app.py | 5 +- adsws/feedback/config.py | 17 +- .../feedback/templates/bumblebee_feedback.txt | 3 + adsws/feedback/utils.py | 6 +- adsws/feedback/views.py | 215 ++++++++---------- adsws/tests/stubdata/general_feedback.py | 3 + adsws/tests/test_feedback.py | 95 ++------ 7 files changed, 144 insertions(+), 200 deletions(-) create mode 100644 adsws/feedback/templates/bumblebee_feedback.txt create mode 100644 adsws/tests/stubdata/general_feedback.py diff --git a/adsws/feedback/app.py b/adsws/feedback/app.py index 407a7ba..30a136b 100644 --- a/adsws/feedback/app.py +++ b/adsws/feedback/app.py @@ -5,7 +5,7 @@ from .. import factory from flask.ext.restful import Api from flask.ext.cors import CORS -from adsws.feedback.views import SlackFeedback +from adsws.feedback.views import UserFeedback from flask.ext.mail import Mail @@ -35,6 +35,7 @@ def create_app(**kwargs_config): ) # Add end points - api.add_resource(SlackFeedback, '/slack') + api.add_resource(UserFeedback, '/userfeedback') + return app diff --git a/adsws/feedback/config.py b/adsws/feedback/config.py index 5564480..90e522d 100644 --- a/adsws/feedback/config.py +++ b/adsws/feedback/config.py @@ -12,7 +12,9 @@ FEEDBACK_SLACK_END_POINT = 'https://hooks.slack.com/services/TOKEN/TOKEN' FEEDBACK_SLACK_EMOJI = ':interrobang:' -DEFAULT_EMAIL = 'adshelp@cfa.harvard.edu' +FORM_SLACK_EMOJI = ':inbox_tray:' +DEFAULT_EMAIL_BACKUP = 'adshelp@cfa.harvard.edu' +DEFAULT_EMAIL = 'ehenneken@gmail.com' # Feedback processing depends on 'origin' attribute supplied in POST data FEEDBACK_FORMS_ORIGIN = 'user_submission' BBB_FEEDBACK_ORIGIN = 'bbb_feedback' @@ -21,11 +23,13 @@ 'Missing References': 'missing_references.txt', 'Associated Articles': 'associated_articles.txt', 'Updated Record': 'updated_record.txt', - 'New Record': 'new_record.txt' + 'New Record': 'new_record.txt', + 'Bumblebee Feedback':'bumblebee_feedback.txt' } # Override defaul recipient based on email subject (key) FEEDBACK_EMAILS = { - 'Missing References': 'ads@cfa.harvard.edu' + 'Missing References backup': 'ads@cfa.harvard.edu', + 'Missing References': 'ehenneken@gmail.com' } GOOGLE_RECAPTCHA_ENDPOINT = 'https://www.google.com/recaptcha/api/siteverify' @@ -33,3 +37,10 @@ CORS_DOMAINS = ['https://ui.adsabs.harvard.edu'] CORS_HEADERS = [] CORS_METHODS = ['POST', 'GET'] + +MAIL_SERVER = 'smtp.mail.yahoo.com' +MAIL_PORT = 587 +MAIL_USE_TLS = True +MAIL_USERNAME = 'edwinhenneken@yahoo.com' # enter your email here +MAIL_DEFAULT_SENDER = 'edwinhenneken@yahoo.com' # enter your email here +MAIL_PASSWORD = 'wmngndstdnxxczzn' # enter your password here \ No newline at end of file diff --git a/adsws/feedback/templates/bumblebee_feedback.txt b/adsws/feedback/templates/bumblebee_feedback.txt new file mode 100644 index 0000000..de94e5b --- /dev/null +++ b/adsws/feedback/templates/bumblebee_feedback.txt @@ -0,0 +1,3 @@ +{% for key, value in data.items() -%} + **{{ key }}** {{ value }} +{% endfor %} \ No newline at end of file diff --git a/adsws/feedback/utils.py b/adsws/feedback/utils.py index fe5cd2d..fba1cb3 100644 --- a/adsws/feedback/utils.py +++ b/adsws/feedback/utils.py @@ -9,10 +9,10 @@ def send_feedback_email(name, sender, subject, data, attachments=None): # Allow the default recipient to be overriden depending on email subject - help_email = current_app.config['FEEDBACK_EMAILS'].get(subject, current_app.config['DEFAULT_EMAIL']) + email = current_app.config['FEEDBACK_EMAILS'].get(subject, current_app.config['DEFAULT_EMAIL']) msg = Message(subject="%s from %s (%s)" % (subject, name, sender), - recipients=[help_email], - sender=("ADS", help_email), + recipients=[email], + sender=("ADS", email), reply_to=(name, sender), body=data) if attachments: diff --git a/adsws/feedback/views.py b/adsws/feedback/views.py index 3e33ff6..dedb0ea 100644 --- a/adsws/feedback/views.py +++ b/adsws/feedback/views.py @@ -5,6 +5,7 @@ import json import requests +import copy from flask import current_app, request, render_template from flask.ext.restful import Resource from adsws.ext.ratelimiter import ratelimit, scope_func @@ -40,132 +41,71 @@ body='Re-directed due to malformed request or incorrect end point', number=302 ) +ERROR_EMAIL_NOT_SENT = dict( + body='Delivery of feedback email to ADS failed!', + number=404 +) -class SlackFeedback(Resource): +class UserFeedback(Resource): """ - Forwards a user's feedback to slack chat using a web end + Forwards a user's feedback to Slack and/or email """ decorators = [ratelimit.shared_limit_and_check("500/600 second", scope=scope_func)] - @staticmethod - def prettify_post(post_data): - """ - Converts the given input into a prettified version - :param post_data: the post data to prettify, dictionary expected - :return: prettified_post data, dictionary - """ - channel = post_data.get('channel', '#feedback') - username = post_data.get('username', 'TownCrier') - - name = post_data.get('name', 'TownCrier') - reply_to = post_data.get('_replyto', 'TownCrier@lonelyvilla.ge') - - try: - comments = post_data['comments'] - except BadRequestKeyError: - raise - - text = [ - '*Commenter*: {}'.format(name), - '*e-mail*: {}'.format(reply_to), - '*Feedback*: {}'.format(comments.encode('utf-8')), - ] - - used = ['channel', 'username', 'name', '_replyto', 'comments', 'g-recaptcha-response'] - for key in post_data: - if key in used: - continue - text.append('*{}*: {}'.format(key, post_data[key])) - text = '\n'.join(text) - - feedback_email = 'no email sent' - if post_data.has_key('_replyto') and post_data.has_key('name'): - try: - res = send_feedback_email(name, reply_to, "Bumblebee Feedback", text) - feedback_email = 'success' - except Exception as e: - current_app.logger.info('Sending feedback mail failed: %s' % str(e)) - feedback_email = 'failed' - - text = '```Incoming Feedback```\n' + text + '\n*sent to adshelp*: {}\n'.format(feedback_email) - - icon_emoji = current_app.config['FEEDBACK_SLACK_EMOJI'] - prettified_data = { - 'text': text, - 'username': username, - 'channel': channel, - 'icon_emoji': icon_emoji - } - return prettified_data - @staticmethod def create_email_body(post_data): """ - Takes the data from the feedback forms and fills out the appropriate template + Takes the data from the feedback and fills out the appropriate template :param post_data: the post data to fill out email template, dictionary expected :return: email body, string """ + # We will be manipulating the dictionary with POST data, so make a copy + email_data = copy.copy(post_data) + # Determine the origin of the feedback. There are some origin-specific actions + origin = post_data.get('origin', 'NA') + if origin == current_app.config['BBB_FEEDBACK_ORIGIN']: + try: + comments = email_data['comments'] + except BadRequestKeyError: + raise + email_data['_subject'] = 'Bumblebee Feedback' + email_data['comments'] = post_data['comments'].encode('utf-8') + used = ['channel', 'username', 'name', '_replyto', 'g-recaptcha-response'] + for key in used: + email_data.pop(key, None) # Retrieve the appropriate template - template = current_app.config['FEEDBACK_TEMPLATES'].get(post_data.get('_subject')) + template = current_app.config['FEEDBACK_TEMPLATES'].get(email_data.get('_subject')) # For abstract corrections, the POST payload has a "diff" attribute that contains # the updated fields in Github "diff" format, URL encoded. For display purposes, # this needs to be decoded. if post_data.has_key('diff'): - post_data['diff'] = unquote(post_data['diff']) + email_data['diff'] = unquote(post_data['diff']) # In the case of a new record the mail body will show a summary # In this summary it's easier to show a author list in the form of a string # We also attach the JSON data of the new record as a file if post_data.get('_subject') == 'New Record': try: - post_data['new']['author_list'] = ";".join([a['name'] for a in post_data['new']['authors']]) + email_data['new']['author_list'] = ";".join([a['name'] for a in post_data['new']['authors']]) except: - post_data['new']['author_list'] = "" + email_data['new']['author_list'] = "" # Construct the email body - body = render_template(template, data=post_data) + body = render_template(template, data=email_data) # If there is a way to insert tabs in the template, it should happen there # (currently, this only happens in the missing_references.txt template) body = body.replace('[tab]','\t') - return body - - @staticmethod - def process_feedbackform_submission(post_data, body): - """ - Takes the data from the feedback forms and fills out the appropriate template - :param post_data: the post data to fill out email template, dictionary expected - :param body: email body - :return: success message, string - """ - # List to hold attachments to be sent along - attachments=[] - if post_data.get('_subject') == 'New Record': - attachments.append(('new_record.json', post_data['new'])) - if post_data.get('_subject') == 'Updated Record': - attachments.append(('updated_record.json', post_data['new'])) - attachments.append(('original_record.json', post_data['original'])) - - feedback_email = 'no email sent' - if post_data.has_key('email') and post_data.has_key('name'): - try: - res = send_feedback_email(post_data['name'], post_data['name'], post_data['_subject'], body, attachments=attachments) - feedback_email = 'success' - except Exception as e: - current_app.logger.info('Sending feedback mail failed: %s' % str(e)) - feedback_email = 'failed' - - return feedback_email + return body def post(self): """ HTTP POST request - :return: status code from the slack end point + :return: status code from the slack end point and for sending user feedback emails """ post_data = get_post_data(request) - current_app.logger.info('Received feedback: {0}'.format(post_data)) - + current_app.logger.info('Received feedback of type {0}: {1}'.format(post_data.get('_subject'), post_data)) if not post_data.get('g-recaptcha-response', False) or \ not verify_recaptcha(request): @@ -173,38 +113,82 @@ def post(self): return err(ERROR_UNVERIFIED_CAPTCHA) else: current_app.logger.info('Skipped captcha!') + # We only allow POST data from certain origins + allowed_origins = [v for k,v in current_app.config.items() if k.endswith('_ORIGIN')] origin = post_data.get('origin', 'NA') + if origin == 'NA' or origin not in allowed_origins: + return err(ERROR_UNKNOWN_ORIGIN) + # Some variable definitions + email_body = '' + slack_data = '' + attachments=[] + # Generate the email body based on the data in the POST payload + try: + email_body = self.create_email_body(post_data) + except BadRequestKeyError as error: + current_app.logger.error('Missing keywords: {0}, {1}' + .format(error, post_data)) + return err(ERROR_MISSING_KEYWORDS) + except Exception as error: + current_app.logger.error('Fatal error creating email body: {0}'.format(error)) + return err(ERROR_EMAILBODY_PROBLEM) + # Retrieve the name of the person submitting the feedback + name = post_data.get('name', 'TownCrier') + # There are some origin-specific actions if origin == current_app.config['FEEDBACK_FORMS_ORIGIN']: - current_app.logger.info('Received data from feedback form "{0}" from {1} ({2})'.format(post_data.get('_subject'), post_data.get('name'), post_data.get('email'))) - try: - email_body = self.create_email_body(post_data) - except Exception as error: - current_app.logger.error('Fatal error creating email body: {0}'.format(error)) - return err(ERROR_EMAILBODY_PROBLEM) + # The reply_to for feedback form data + reply_to = post_data.get('email') + # In the case of new or corrected records, attachments are sent along + if post_data.get('_subject') == 'New Record': + attachments.append(('new_record.json', post_data['new'])) + if post_data.get('_subject') == 'Updated Record': + attachments.append(('updated_record.json', post_data['new'])) + attachments.append(('original_record.json', post_data['original'])) + # Prepare a minimal Slack message + channel = post_data.get('channel', '#feedback') + username = post_data.get('username', 'TownCrier') + icon_emoji = current_app.config['FORM_SLACK_EMOJI'] + text = 'Received data from feedback form "{0}" from {1} ({2})'.format(post_data.get('_subject'), post_data.get('name'), post_data.get('email')) + slack_data = { + 'text': text, + 'username': username, + 'channel': channel, + 'icon_emoji': icon_emoji + } + elif origin == current_app.config['BBB_FEEDBACK_ORIGIN']: + # The reply_to for the general feedback data + reply_to = post_data.get('_replyto', 'TownCrier@lonelyvilla.ge') + # Prepare the Slack message with submitted data + text = '```Incoming Feedback```\n' + email_body + channel = post_data.get('channel', '#feedback') + username = post_data.get('username', 'TownCrier') + icon_emoji = current_app.config['FEEDBACK_SLACK_EMOJI'] + slack_data = { + 'text': text, + 'username': username, + 'channel': channel, + 'icon_emoji': icon_emoji + } + # If we have an email body (should always be the case), send out the email + if email_body: + email_sent = False try: - email_sent = self.process_feedbackform_submission(post_data, email_body) - except Exception as error: - current_app.logger.error('Fatal error while processing feedback form data: {0}'.format(error)) - return err(ERROR_FEEDBACKFORM_PROBLEM) + res = send_feedback_email(name, reply_to, post_data['_subject'], email_body, attachments=attachments) + email_sent = True + except Exception as e: + current_app.logger.error('Fatal error while processing feedback form data: {0}'.format(e)) + email_sent = False if not email_sent: # If the email could not be sent, we can still log the data submitted - current_app.logger.error('Sending of email failed. Feedback data submitted by {0} ({1}): {2}'.format(post_data, post_data.get('name'), post_data.get('email'))) - elif origin == current_app.config['BBB_FEEDBACK_ORIGIN']: - try: - current_app.logger.info('Prettifiying post data: {0}' - .format(post_data)) - formatted_post_data = json.dumps(self.prettify_post(post_data)) - current_app.logger.info('Data prettified: {0}' - .format(formatted_post_data)) - except BadRequestKeyError as error: - current_app.logger.error('Missing keywords: {0}, {1}' - .format(error, post_data)) - return err(ERROR_MISSING_KEYWORDS) - + current_app.logger.error('Sending of email failed. Feedback data submitted by {0} ({1}): {2}'.format(post_data, name, post_data.get('email'))) + return err(ERROR_EMAIL_NOT_SENT) + # If we have Slack data, post the message to Slack + if slack_data: + slack_data['text'] += '\n*sent to adshelp*: {0}'.format(email_sent) try: slack_response = requests.post( url=current_app.config['FEEDBACK_SLACK_END_POINT'], - data=formatted_post_data, + data=json.dumps(slack_data), timeout=60 ) except (requests.exceptions.ConnectionError, requests.exceptions.Timeout): @@ -221,6 +205,5 @@ def post(self): return {}, 200 else: return {'msg': 'Unknown error'}, slack_response.status_code - else: - return err(ERROR_UNKNOWN_ORIGIN) + return {}, 200 diff --git a/adsws/tests/stubdata/general_feedback.py b/adsws/tests/stubdata/general_feedback.py new file mode 100644 index 0000000..324d628 --- /dev/null +++ b/adsws/tests/stubdata/general_feedback.py @@ -0,0 +1,3 @@ +data = {'origin':'bbb_feedback','engine': u'Gecko', 'g-recaptcha-response': u'03AGdBq26IdCZUStucYY2tg4HR0X4PUoYutiiamENoDFrC9-kjBHV6CzuAxDSWWt8xn8p14WKtlvcQxHfhfNrmI-C_uoN8nUdbqJGy3T7ZxxkOaifTaD5CbQe-CeTKeUZYb4nHJYD4F3zIIVxNFyXK9wyzJT251ss-QNls3m9vt-ucHJwtPNlQ6EIkOfqLv5G3rOlZ0D-pZ17qybbWNo9PNFmEEWNiabdD01atIx8CIMjuhByPEbZYF7tH6lXGDscKfYTUqXEN9wLOadBv2yB-tA6UBCfBOQs8FD6szk1A7Q0GOd6juKL_O241z19ADNBsux21riOMw6UiPuDt8BI2yjEkjfoW3gdQkQp7j73FsIK5Gwb0C9SP7S34HJUuLt27QCmsp8NiXYu_k944U3KW_Rab9hcgUoix9ReXqqb2EJ6WT_W3mdeZh2fJumrRw5cdcaNmtESkONDH', 'feedback-type': u'feedback', '_gotcha': u'', 'user-agent-string': u'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0', '_subject': u'Bumblebee Feedback', 'current_query': u'filter_property_fq_property=AND&filter_property_fq_property=property%3A%22refereed%22&fq=%7B!type%3Daqp%20v%3D%24fq_property%7D&fq_property=(property%3A%22refereed%22)&p_=0&q=year%3A2020%20%20full%3A%22cfht%22%20NOT%20docs(library%2FEyD7bWIGRNmxqCofTjNw4Q)%20NOT%20docs(library%2F49PdHlcMRh2_KF672dbcZw)&sort=date%20asc%2C%20bibcode%20asc', 'browser.name': u'Firefox', 'name': u'Happy User', 'url': u'https://ui.adsabs.harvard.edu/search/filter_property_fq_property=AND&filter_property_fq_property=property%3A%22refereed%22&fq=%7B!type%3Daqp%20v%3D%24fq_property%7D&fq_property=(property%3A%22refereed%22)&p_=0&q=year%3A2020%20%20full%3A%22cfht%22%20NOT%20docs(library%2FEyD7bWIGRNmxqCofTjNw4Q)%20NOT%20docs(library%2F49PdHlcMRh2_KF672dbcZw)&sort=date%20asc%2C%20bibcode%20asc', 'current_page': u'search-page', 'comments': u'Hi,\r\n\r\n Thank you for maintaining this awesome service. Can you please give me more citations?\r\n\r\nThanks in advance,\r\nHappy User', 'platform': u'desktop', '_replyto': u'happyuser@happydomain.universe', 'os': u'Linux', 'currentuser': u'devost@cfht.hawaii.edu', 'browser.version': u'80.0'} + +response = '**origin** bbb_feedback\n**engine** Gecko\n**feedback-type** feedback\n**_gotcha** \n**user-agent-string** Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0\n**_subject** Bumblebee Feedback\n**current_query** filter_property_fq_property=AND&filter_property_fq_property=property%3A%22refereed%22&fq=%7B!type%3Daqp%20v%3D%24fq_property%7D&fq_property=(property%3A%22refereed%22)&p_=0&q=year%3A2020%20%20full%3A%22cfht%22%20NOT%20docs(library%2FEyD7bWIGRNmxqCofTjNw4Q)%20NOT%20docs(library%2F49PdHlcMRh2_KF672dbcZw)&sort=date%20asc%2C%20bibcode%20asc\n**url** https://ui.adsabs.harvard.edu/search/filter_property_fq_property=AND&filter_property_fq_property=property%3A%22refereed%22&fq=%7B!type%3Daqp%20v%3D%24fq_property%7D&fq_property=(property%3A%22refereed%22)&p_=0&q=year%3A2020%20%20full%3A%22cfht%22%20NOT%20docs(library%2FEyD7bWIGRNmxqCofTjNw4Q)%20NOT%20docs(library%2F49PdHlcMRh2_KF672dbcZw)&sort=date%20asc%2C%20bibcode%20asc\n**current_page** search-page\n**comments** Hi,\r\n\r\n Thank you for maintaining this awesome service. Can you please give me more citations?\r\n\r\nThanks in advance,\r\nHappy User\n**platform** desktop\n**browser.name** Firefox\n**os** Linux\n**currentuser** devost@cfht.hawaii.edu\n**browser.version** 80.0\n' \ No newline at end of file diff --git a/adsws/tests/test_feedback.py b/adsws/tests/test_feedback.py index 411d8d9..6b9c24d 100644 --- a/adsws/tests/test_feedback.py +++ b/adsws/tests/test_feedback.py @@ -11,8 +11,8 @@ from flask import url_for, current_app from flask.ext.testing import TestCase from httpretty import HTTPretty -from adsws.feedback.views import SlackFeedback, verify_recaptcha -from adsws.tests.stubdata import missing_references, associated_other, associated_errata, new_abstract, corrected_abstract +from adsws.feedback.views import UserFeedback, verify_recaptcha +from adsws.tests.stubdata import missing_references, associated_other, associated_errata, new_abstract, corrected_abstract, general_feedback class GoogleRecaptchaService(object): @@ -34,7 +34,6 @@ def request_callback(request, uri, headers): :return: httpretty response """ data = request.parsed_body - if data['response'][0] == 'correct_response': res = {'success': True} elif data['response'][0] == 'incorrect_response': @@ -161,7 +160,7 @@ def test_submitting_feedback(self): } # User presses submit on the feedback form - url = url_for('slackfeedback') + url = url_for('userfeedback') with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: response = self.client.post( url, @@ -176,7 +175,7 @@ def test_submitting_missing_references(self): """ # User presses submit on the feedback form - url = url_for('slackfeedback') + url = url_for('userfeedback') with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: response = self.client.post( url, @@ -191,7 +190,7 @@ def test_submitting_associated(self): """ # User presses submit on the feedback form - url = url_for('slackfeedback') + url = url_for('userfeedback') with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: response = self.client.post( url, @@ -206,7 +205,7 @@ def test_submitting_associated_other(self): """ # User presses submit on the feedback form - url = url_for('slackfeedback') + url = url_for('userfeedback') with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: response = self.client.post( url, @@ -221,7 +220,7 @@ def test_submitting_new_abstract(self): """ # User presses submit on the feedback form - url = url_for('slackfeedback') + url = url_for('userfeedback') with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: response = self.client.post( url, @@ -236,7 +235,7 @@ def test_submitting_corrected_abstract(self): """ # User presses submit on the feedback form - url = url_for('slackfeedback') + url = url_for('userfeedback') with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: response = self.client.post( url, @@ -256,7 +255,7 @@ def test_submitting_feedback_with_minimal_information(self): } # User presses submit on the feedback form - url = url_for('slackfeedback') + url = url_for('userfeedback') with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: response = self.client.post( url, @@ -278,7 +277,7 @@ def test_404_if_not_right_data(self): } # User presses submit on the feedback form - url = url_for('slackfeedback') + url = url_for('userfeedback') with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: response = self.client.post( url, @@ -299,7 +298,7 @@ def test_404_if_not_right_origin(self): } # User presses submit on the feedback form - url = url_for('slackfeedback') + url = url_for('userfeedback') with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: response = self.client.post( url, @@ -322,7 +321,7 @@ def test_404_if_not_right_subject(self): } # User presses submit on the feedback form - url = url_for('slackfeedback') + url = url_for('userfeedback') with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: response = self.client.post( url, @@ -370,81 +369,25 @@ def test_mock_of_slack_endpoint_fail(self): self.assertEqual(response.status_code, 400) self.assertEqual(response.json()['msg'], 'fail') - def test_parser_parses_content(self): - """ - Tests that the input given is parsed sensibly for slack - """ - emoji = current_app.config['FEEDBACK_SLACK_EMOJI'] - post_data_sent = { - 'text': '```Incoming Feedback```\n' - '*Commenter*: Commenter\n' - '*e-mail*: commenter@email.com\n' - '*Feedback*: Why are my citations missing?\n' - '*sent to adshelp*: failed\n', - 'username': 'TownCrier', - 'channel': '#feedback', - 'icon_emoji': emoji - } - - form_data = { - 'name': 'Commenter', - 'comments': 'Why are my citations missing?', - '_replyto': 'commenter@email.com' - } - - prettified_post_data = SlackFeedback().prettify_post(form_data) - - for key in post_data_sent.keys(): - self.assertEqual(post_data_sent[key], prettified_post_data[key]) - - def test_can_send_abritrary_keyword_values(self): - """ - Test the end point is not restrictive on the keyword values it can - create content for. - """ - emoji = current_app.config['FEEDBACK_SLACK_EMOJI'] - post_data_sent = { - 'text': '```Incoming Feedback```\n' - '*Commenter*: Commenter\n' - '*e-mail*: commenter@email.com\n' - '*Feedback*: Why are my citations missing?\n' - '*IP Address*: 127.0.0.1\n' - '*Browser*: Firefox v42\n' - '*sent to adshelp*: failed\n', - 'username': 'TownCrier', - 'channel': '#feedback', - 'icon_emoji': emoji - } - - form_data = { - 'name': 'Commenter', - 'comments': 'Why are my citations missing?', - 'Browser': 'Firefox v42', - 'IP Address': '127.0.0.1', - '_replyto': 'commenter@email.com' - } - - prettified_post_data = SlackFeedback().prettify_post(form_data) - - for key in post_data_sent.keys(): - self.assertEqual(post_data_sent[key], prettified_post_data[key]) - def test_email_body(self): """ """ - email_body = SlackFeedback().create_email_body(corrected_abstract.data) + email_body = UserFeedback().create_email_body(corrected_abstract.data) self.assertEqual(email_body, corrected_abstract.response) - email_body = SlackFeedback().create_email_body(new_abstract.data) + email_body = UserFeedback().create_email_body(new_abstract.data) self.assertEqual(email_body, new_abstract.response) - email_body = SlackFeedback().create_email_body(associated_other.data) + email_body = UserFeedback().create_email_body(associated_other.data) self.assertEqual(email_body, associated_other.response) - email_body = SlackFeedback().create_email_body(missing_references.data) + email_body = UserFeedback().create_email_body(missing_references.data) self.assertEqual(email_body, missing_references.response) + + email_body = UserFeedback().create_email_body(general_feedback.data) + self.assertEqual(email_body, general_feedback.response) def test_verify_google_recaptcha(self): """ From 5bc7d6d44b54ed596c49b505728f7449d337b40c Mon Sep 17 00:00:00 2001 From: Edwin Henneken Date: Fri, 25 Sep 2020 12:15:15 -0400 Subject: [PATCH 4/6] small update --- adsws/feedback/config.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/adsws/feedback/config.py b/adsws/feedback/config.py index 90e522d..ae01ddd 100644 --- a/adsws/feedback/config.py +++ b/adsws/feedback/config.py @@ -37,10 +37,3 @@ CORS_DOMAINS = ['https://ui.adsabs.harvard.edu'] CORS_HEADERS = [] CORS_METHODS = ['POST', 'GET'] - -MAIL_SERVER = 'smtp.mail.yahoo.com' -MAIL_PORT = 587 -MAIL_USE_TLS = True -MAIL_USERNAME = 'edwinhenneken@yahoo.com' # enter your email here -MAIL_DEFAULT_SENDER = 'edwinhenneken@yahoo.com' # enter your email here -MAIL_PASSWORD = 'wmngndstdnxxczzn' # enter your password here \ No newline at end of file From e3516d67795c76c0be7960a70b034619d5a91c84 Mon Sep 17 00:00:00 2001 From: Edwin Henneken Date: Fri, 25 Sep 2020 12:22:14 -0400 Subject: [PATCH 5/6] small additional update --- adsws/feedback/config.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/adsws/feedback/config.py b/adsws/feedback/config.py index ae01ddd..b76e7f2 100644 --- a/adsws/feedback/config.py +++ b/adsws/feedback/config.py @@ -13,8 +13,7 @@ FEEDBACK_SLACK_END_POINT = 'https://hooks.slack.com/services/TOKEN/TOKEN' FEEDBACK_SLACK_EMOJI = ':interrobang:' FORM_SLACK_EMOJI = ':inbox_tray:' -DEFAULT_EMAIL_BACKUP = 'adshelp@cfa.harvard.edu' -DEFAULT_EMAIL = 'ehenneken@gmail.com' +DEFAULT_EMAIL = 'adshelp@cfa.harvard.edu' # Feedback processing depends on 'origin' attribute supplied in POST data FEEDBACK_FORMS_ORIGIN = 'user_submission' BBB_FEEDBACK_ORIGIN = 'bbb_feedback' @@ -28,8 +27,7 @@ } # Override defaul recipient based on email subject (key) FEEDBACK_EMAILS = { - 'Missing References backup': 'ads@cfa.harvard.edu', - 'Missing References': 'ehenneken@gmail.com' + 'Missing References': 'ads@cfa.harvard.edu', } GOOGLE_RECAPTCHA_ENDPOINT = 'https://www.google.com/recaptcha/api/siteverify' @@ -37,3 +35,4 @@ CORS_DOMAINS = ['https://ui.adsabs.harvard.edu'] CORS_HEADERS = [] CORS_METHODS = ['POST', 'GET'] + From ea8856a015256d8a63f6f74fc06ce765a7d0884e Mon Sep 17 00:00:00 2001 From: Edwin Henneken Date: Fri, 25 Sep 2020 14:43:24 -0400 Subject: [PATCH 6/6] unittest fixes --- adsws/tests/stubdata/general_feedback.py | 4 +-- adsws/tests/test_feedback.py | 43 +++++++++++++----------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/adsws/tests/stubdata/general_feedback.py b/adsws/tests/stubdata/general_feedback.py index 324d628..44e105b 100644 --- a/adsws/tests/stubdata/general_feedback.py +++ b/adsws/tests/stubdata/general_feedback.py @@ -1,3 +1,3 @@ -data = {'origin':'bbb_feedback','engine': u'Gecko', 'g-recaptcha-response': u'03AGdBq26IdCZUStucYY2tg4HR0X4PUoYutiiamENoDFrC9-kjBHV6CzuAxDSWWt8xn8p14WKtlvcQxHfhfNrmI-C_uoN8nUdbqJGy3T7ZxxkOaifTaD5CbQe-CeTKeUZYb4nHJYD4F3zIIVxNFyXK9wyzJT251ss-QNls3m9vt-ucHJwtPNlQ6EIkOfqLv5G3rOlZ0D-pZ17qybbWNo9PNFmEEWNiabdD01atIx8CIMjuhByPEbZYF7tH6lXGDscKfYTUqXEN9wLOadBv2yB-tA6UBCfBOQs8FD6szk1A7Q0GOd6juKL_O241z19ADNBsux21riOMw6UiPuDt8BI2yjEkjfoW3gdQkQp7j73FsIK5Gwb0C9SP7S34HJUuLt27QCmsp8NiXYu_k944U3KW_Rab9hcgUoix9ReXqqb2EJ6WT_W3mdeZh2fJumrRw5cdcaNmtESkONDH', 'feedback-type': u'feedback', '_gotcha': u'', 'user-agent-string': u'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0', '_subject': u'Bumblebee Feedback', 'current_query': u'filter_property_fq_property=AND&filter_property_fq_property=property%3A%22refereed%22&fq=%7B!type%3Daqp%20v%3D%24fq_property%7D&fq_property=(property%3A%22refereed%22)&p_=0&q=year%3A2020%20%20full%3A%22cfht%22%20NOT%20docs(library%2FEyD7bWIGRNmxqCofTjNw4Q)%20NOT%20docs(library%2F49PdHlcMRh2_KF672dbcZw)&sort=date%20asc%2C%20bibcode%20asc', 'browser.name': u'Firefox', 'name': u'Happy User', 'url': u'https://ui.adsabs.harvard.edu/search/filter_property_fq_property=AND&filter_property_fq_property=property%3A%22refereed%22&fq=%7B!type%3Daqp%20v%3D%24fq_property%7D&fq_property=(property%3A%22refereed%22)&p_=0&q=year%3A2020%20%20full%3A%22cfht%22%20NOT%20docs(library%2FEyD7bWIGRNmxqCofTjNw4Q)%20NOT%20docs(library%2F49PdHlcMRh2_KF672dbcZw)&sort=date%20asc%2C%20bibcode%20asc', 'current_page': u'search-page', 'comments': u'Hi,\r\n\r\n Thank you for maintaining this awesome service. Can you please give me more citations?\r\n\r\nThanks in advance,\r\nHappy User', 'platform': u'desktop', '_replyto': u'happyuser@happydomain.universe', 'os': u'Linux', 'currentuser': u'devost@cfht.hawaii.edu', 'browser.version': u'80.0'} +data = {'origin':'bbb_feedback','engine': u'Gecko', 'g-recaptcha-response': u'correct_response', 'feedback-type': u'feedback', '_gotcha': u'', 'user-agent-string': u'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0', '_subject': u'Bumblebee Feedback', 'current_query': u'filter_property_fq_property=AND&filter_property_fq_property=property%3A%22refereed%22&fq=%7B!type%3Daqp%20v%3D%24fq_property%7D&fq_property=(property%3A%22refereed%22)&p_=0&q=year%3A2020%20%20full%3A%22cfht%22%20NOT%20docs(library%2FEyD7bWIGRNmxqCofTjNw4Q)%20NOT%20docs(library%2F49PdHlcMRh2_KF672dbcZw)&sort=date%20asc%2C%20bibcode%20asc', 'browser.name': u'Firefox', 'name': u'Happy User', 'url': u'https://ui.adsabs.harvard.edu/search/filter_property_fq_property=AND&filter_property_fq_property=property%3A%22refereed%22&fq=%7B!type%3Daqp%20v%3D%24fq_property%7D&fq_property=(property%3A%22refereed%22)&p_=0&q=year%3A2020%20%20full%3A%22cfht%22%20NOT%20docs(library%2FEyD7bWIGRNmxqCofTjNw4Q)%20NOT%20docs(library%2F49PdHlcMRh2_KF672dbcZw)&sort=date%20asc%2C%20bibcode%20asc', 'current_page': u'search-page', 'comments': u'Hi,\r\n\r\n Thank you for maintaining this awesome service. Can you please give me more citations?\r\n\r\nThanks in advance,\r\nHappy User', 'platform': u'desktop', '_replyto': u'happyuser@happydomain.universe', 'os': u'Linux', 'currentuser': u'devost@cfht.hawaii.edu', 'browser.version': u'80.0'} -response = '**origin** bbb_feedback\n**engine** Gecko\n**feedback-type** feedback\n**_gotcha** \n**user-agent-string** Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0\n**_subject** Bumblebee Feedback\n**current_query** filter_property_fq_property=AND&filter_property_fq_property=property%3A%22refereed%22&fq=%7B!type%3Daqp%20v%3D%24fq_property%7D&fq_property=(property%3A%22refereed%22)&p_=0&q=year%3A2020%20%20full%3A%22cfht%22%20NOT%20docs(library%2FEyD7bWIGRNmxqCofTjNw4Q)%20NOT%20docs(library%2F49PdHlcMRh2_KF672dbcZw)&sort=date%20asc%2C%20bibcode%20asc\n**url** https://ui.adsabs.harvard.edu/search/filter_property_fq_property=AND&filter_property_fq_property=property%3A%22refereed%22&fq=%7B!type%3Daqp%20v%3D%24fq_property%7D&fq_property=(property%3A%22refereed%22)&p_=0&q=year%3A2020%20%20full%3A%22cfht%22%20NOT%20docs(library%2FEyD7bWIGRNmxqCofTjNw4Q)%20NOT%20docs(library%2F49PdHlcMRh2_KF672dbcZw)&sort=date%20asc%2C%20bibcode%20asc\n**current_page** search-page\n**comments** Hi,\r\n\r\n Thank you for maintaining this awesome service. Can you please give me more citations?\r\n\r\nThanks in advance,\r\nHappy User\n**platform** desktop\n**browser.name** Firefox\n**os** Linux\n**currentuser** devost@cfht.hawaii.edu\n**browser.version** 80.0\n' \ No newline at end of file +response = '**origin** bbb_feedback\n**engine** Gecko\n**feedback-type** feedback\n**_gotcha** \n**user-agent-string** Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0\n**_subject** Bumblebee Feedback\n**current_query** filter_property_fq_property=AND&filter_property_fq_property=property%3A%22refereed%22&fq=%7B!type%3Daqp%20v%3D%24fq_property%7D&fq_property=(property%3A%22refereed%22)&p_=0&q=year%3A2020%20%20full%3A%22cfht%22%20NOT%20docs(library%2FEyD7bWIGRNmxqCofTjNw4Q)%20NOT%20docs(library%2F49PdHlcMRh2_KF672dbcZw)&sort=date%20asc%2C%20bibcode%20asc\n**url** https://ui.adsabs.harvard.edu/search/filter_property_fq_property=AND&filter_property_fq_property=property%3A%22refereed%22&fq=%7B!type%3Daqp%20v%3D%24fq_property%7D&fq_property=(property%3A%22refereed%22)&p_=0&q=year%3A2020%20%20full%3A%22cfht%22%20NOT%20docs(library%2FEyD7bWIGRNmxqCofTjNw4Q)%20NOT%20docs(library%2F49PdHlcMRh2_KF672dbcZw)&sort=date%20asc%2C%20bibcode%20asc\n**current_page** search-page\n**comments** Hi,\r\n\r\n Thank you for maintaining this awesome service. Can you please give me more citations?\r\n\r\nThanks in advance,\r\nHappy User\n**platform** desktop\n**browser.name** Firefox\n**os** Linux\n**currentuser** devost@cfht.hawaii.edu\n**browser.version** 80.0\n' diff --git a/adsws/tests/test_feedback.py b/adsws/tests/test_feedback.py index 6b9c24d..8801a01 100644 --- a/adsws/tests/test_feedback.py +++ b/adsws/tests/test_feedback.py @@ -136,7 +136,28 @@ def create_app(self): """ Create the wsgi application """ - app_ = feedback.create_app() + app_ = feedback.create_app( + FEEDBACK_SLACK_END_POINT = 'https://hooks.slack.com/services/TOKEN/TOKEN', + FEEDBACK_SLACK_EMOJI = ':interrobang:', + FORM_SLACK_EMOJI = ':inbox_tray:', + DEFAULT_EMAIL = 'adshelp@cfa.harvard.edu', + FEEDBACK_FORMS_ORIGIN = 'user_submission', + BBB_FEEDBACK_ORIGIN = 'bbb_feedback', + FEEDBACK_TEMPLATES = { + 'Missing References': 'missing_references.txt', + 'Associated Articles': 'associated_articles.txt', + 'Updated Record': 'updated_record.txt', + 'New Record': 'new_record.txt', + 'Bumblebee Feedback':'bumblebee_feedback.txt' + }, + FEEDBACK_EMAILS = { + 'Missing References': 'ads@cfa.harvard.edu', + }, + MAIL_SUPPRESS_SEND=True, + GOOGLE_RECAPTCHA_ENDPOINT = 'https://www.google.com/recaptcha/api/siteverify', + GOOGLE_RECAPTCHA_PRIVATE_KEY = 'MY_PRIVATE_KEY' + + ) return app_ @@ -150,21 +171,12 @@ def test_submitting_feedback(self): A generic test of the entire work flow of the feedback submission end point """ - # User fills the user feedback form - form_data = { - 'name': 'Commenter', - 'comments': 'Why are my citations missing?', - '_replyto': 'commenter@email.com', - 'g-recaptcha-response': 'correct_response', - 'origin': 'bbb_feedback' - } - # User presses submit on the feedback form url = url_for('userfeedback') with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: response = self.client.post( url, - data=form_data + data=json.dumps(general_feedback.data) ) self.assertEqual(response.status_code, 200) @@ -247,19 +259,12 @@ def test_submitting_feedback_with_minimal_information(self): """ Check they can send minimal information to the end point """ - # User fills the user feedback form - form_data = { - 'comments': 'Why are my citations missing?', - 'g-recaptcha-response': 'correct_response', - 'origin': 'bbb_feedback' - } - # User presses submit on the feedback form url = url_for('userfeedback') with SlackWebService() as SLW, GoogleRecaptchaService() as GRS: response = self.client.post( url, - data=form_data + data=json.dumps(general_feedback.data) ) self.assertEqual(response.status_code, 200)