Repository: google/personfinder

Issue:
Should use /add_note instead of /view to handle POST request to add a note
Currently when you submit a note in /add_note page, it posts against /view URL:
https://github.com/google/personfinder/blob/master/app/resources/add_note.html.template#L53
There is the same logic in both add_note.Handler.post and view.Handler.post, but actually add_note.Handler.post is never used.

We should let the form in /add_note to post against /add_note instead of /view, and delete view.Handler.post.

Also see #157 .



Discussion:

Resolving patch:
diff --git a/app/add_note.py b/app/add_note.py
--- a/app/add_note.py
+++ b/app/add_note.py
@@ -60,8 +60,8 @@ def get(self):
                     standalone=standalone,
                     enable_notes_url=enable_notes_url)
 
-
     def post(self):
+        """Post a note in person's record view page"""
         if not self.params.text:
             return self.error(
                 200, _('Message is required. Please go back and try again.'))
@@ -176,5 +176,5 @@ def post(self):
                                  subscribe_email=self.params.author_email,
                                  context='add_note')
 
-        # Redirect to this page so the browser's back button works properly.
-        self.redirect('/add_note', id=self.params.id, query=self.params.query)
+        # Redirect to view page so the browser's back button works properly.
+        self.redirect('/view', id=self.params.id, query=self.params.query)
diff --git a/app/create.py b/app/create.py
--- a/app/create.py
+++ b/app/create.py
@@ -13,7 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from datetime import datetime
 from model import *
 from photo import create_photo, PhotoError
 from utils import *
@@ -79,10 +78,10 @@ def post(self):
         if self.params.add_note:
             if not self.params.text:
                 return self.error(400, _('Message is required. Please go back and try again.'))
-            if self.params.status == 'is_note_author' and \
-                not self.params.author_made_contact:
+            if (self.params.status == 'is_note_author' and
+                not self.params.author_made_contact):
                 return self.error(400, _('Please check that you have been in contact with the person after the earthquake, or change the "Status of this person" field.'))
-            if (self.params.status == 'believed_dead' and \
+            if (self.params.status == 'believed_dead' and
                 not self.config.allow_believed_dead_via_ui):
                 return self.error(400, _('Not authorized to post notes with the status "I have received information that this person is dead".'))
 
diff --git a/app/view.py b/app/view.py
--- a/app/view.py
+++ b/app/view.py
@@ -170,128 +170,6 @@ def get(self):
                     extension_days=extension_days,
                     expiration_days=expiration_days)
 
-    # Posts a note.
-    def post(self):
-        if not self.params.text:
-            return self.error(
-                200, _('Message is required. Please go back and try again.'))
-
-        if not self.params.author_name:
-            return self.error(
-                200, _('Your name is required in the "About you" section.  '
-                       'Please go back and try again.'))
-
-        if (self.params.status == 'is_note_author' and
-            not self.params.author_made_contact):
-            return self.error(
-                200, _('Please check that you have been in contact with '
-                       'the person after the earthquake, or change the '
-                       '"Status of this person" field.'))
-
-        if (self.params.status == 'believed_dead' and
-            not self.config.allow_believed_dead_via_ui):
-            return self.error(
-                200, _('Not authorized to post notes with the status '
-                       '"believed_dead".'))
-
-        person = Person.get(self.repo, self.params.id)
-        if not person:
-            return self.error(404,
-                _("This person's entry does not exist or has been deleted."))
-        if person.notes_disabled:
-            return self.error(
-                200, _('The author has disabled status updates '
-                       'on this record.'))
-
-        # If a photo was uploaded, create and store a new Photo entry and get
-        # the URL where it's served; otherwise, use the note_photo_url provided.
-        photo, photo_url = (None, self.params.note_photo_url)
-        if self.params.note_photo is not None:
-            try:
-                photo, photo_url = create_photo(self.params.note_photo, self)
-            except PhotoError, e:
-                return self.error(400, e.message)
-            photo.put()
-
-        spam_detector = SpamDetector(self.config.bad_words)
-        spam_score = spam_detector.estimate_spam_score(self.params.text)
-
-        if (spam_score > 0):
-            note = NoteWithBadWords.create_original(
-                self.repo,
-                entry_date=get_utcnow(),
-                person_record_id=self.params.id,
-                author_name=self.params.author_name,
-                author_email=self.params.author_email,
-                author_phone=self.params.author_phone,
-                source_date=get_utcnow(),
-                author_made_contact=bool(self.params.author_made_contact),
-                status=self.params.status,
-                email_of_found_person=self.params.email_of_found_person,
-                phone_of_found_person=self.params.phone_of_found_person,
-                last_known_location=self.params.last_known_location,
-                text=self.params.text,
-                photo=photo,
-                photo_url=photo_url,
-                spam_score=spam_score,
-                confirmed=False)
-            # Write the new NoteWithBadWords to the datastore
-            note.put_new()
-            # When the note is detected as spam, we do not update person record
-            # or log action. We ask the note author for confirmation first.
-            return self.redirect('/post_flagged_note', id=note.get_record_id(),
-                                 author_email=note.author_email,
-                                 repo=self.repo)
-        else:
-            note = Note.create_original(
-                self.repo,
-                entry_date=get_utcnow(),
-                person_record_id=self.params.id,
-                author_name=self.params.author_name,
-                author_email=self.params.author_email,
-                author_phone=self.params.author_phone,
-                source_date=get_utcnow(),
-                author_made_contact=bool(self.params.author_made_contact),
-                status=self.params.status,
-                email_of_found_person=self.params.email_of_found_person,
-                phone_of_found_person=self.params.phone_of_found_person,
-                last_known_location=self.params.last_known_location,
-                text=self.params.text,
-                photo=photo,
-                photo_url=photo_url)
-            # Write the new regular Note to the datastore
-            note.put_new()
-
-        # Specially log 'believed_dead'.
-        if note.status == 'believed_dead':
-            UserActionLog.put_new(
-                'mark_dead', note, person.primary_full_name,
-                self.request.remote_addr)
-
-        # Specially log a switch to an alive status.
-        if (note.status in ['believed_alive', 'is_note_author'] and
-            person.latest_status not in ['believed_alive', 'is_note_author']):
-            UserActionLog.put_new('mark_alive', note, person.primary_full_name)
-
-        # Update the Person based on the Note.
-        if person:
-            person.update_from_note(note)
-            # Send notification to all people
-            # who subscribed to updates on this person
-            subscribe.send_notifications(self, person, [note])
-            # write the updated person record to datastore
-            db.put(person)
-
-        # If user wants to subscribe to updates, redirect to the subscribe page
-        if self.params.subscribe:
-            return self.redirect('/subscribe',
-                                 id=person.record_id,
-                                 subscribe_email=self.params.author_email,
-                                 context='add_note')
-
-        # Redirect to this page so the browser's back button works properly.
-        self.redirect('/view', id=self.params.id, query=self.params.query)
-
     def __add_fields_to_note(self, note):
         """Adds some fields used in the template to a note."""
         note.status_text = get_note_status_text(note)


Test patch:
diff --git a/tests/server_test_cases/config_tests.py b/tests/server_test_cases/config_tests.py
--- a/tests/server_test_cases/config_tests.py
+++ b/tests/server_test_cases/config_tests.py
@@ -16,36 +16,9 @@
 
 """Test cases for end-to-end testing.  Run with the server_tests script."""
 
-import calendar
-import datetime
-import email
-import email.header
-import optparse
-import os
-import pytest
-import re
 import simplejson
-import sys
-import tempfile
-import time
-import unittest
-import urlparse
-
-from google.appengine.api import images
-
-import config
-from const import ROOT_URL, PERSON_STATUS_TEXT, NOTE_STATUS_TEXT
-import download_feed
 from model import *
-from photo import MAX_IMAGE_DIMENSION
-import remote_api
-from resources import Resource, ResourceBundle
-import reveal
-import scrape
 import setup_pf as setup
-from test_pfif import text_diff
-from text_query import TextQuery
-import utils
 from server_tests_base import ServerTestsBase
 
 
diff --git a/tests/server_test_cases/download_feed_tests.py b/tests/server_test_cases/download_feed_tests.py
--- a/tests/server_test_cases/download_feed_tests.py
+++ b/tests/server_test_cases/download_feed_tests.py
@@ -16,36 +16,9 @@
 
 """Test cases for end-to-end testing.  Run with the server_tests script."""
 
-import calendar
-import datetime
-import email
-import email.header
-import optparse
 import os
-import pytest
-import re
-import simplejson
-import sys
 import tempfile
-import time
-import unittest
-import urlparse
-
-from google.appengine.api import images
-
-import config
-from const import ROOT_URL, PERSON_STATUS_TEXT, NOTE_STATUS_TEXT
 import download_feed
-from model import *
-from photo import MAX_IMAGE_DIMENSION
-import remote_api
-from resources import Resource, ResourceBundle
-import reveal
-import scrape
-import setup_pf as setup
-from test_pfif import text_diff
-from text_query import TextQuery
-import utils
 from server_tests_base import ServerTestsBase
 
 
diff --git a/tests/server_test_cases/feed_tests.py b/tests/server_test_cases/feed_tests.py
--- a/tests/server_test_cases/feed_tests.py
+++ b/tests/server_test_cases/feed_tests.py
@@ -16,35 +16,10 @@
 
 """Test cases for end-to-end testing.  Run with the server_tests script."""
 
-import calendar
 import datetime
-import email
-import email.header
-import optparse
-import os
-import pytest
-import re
-import simplejson
-import sys
-import tempfile
-import time
-import unittest
-import urlparse
-
-from google.appengine.api import images
-
-import config
-from const import ROOT_URL, PERSON_STATUS_TEXT, NOTE_STATUS_TEXT
-import download_feed
+from const import ROOT_URL
 from model import *
-from photo import MAX_IMAGE_DIMENSION
-import remote_api
-from resources import Resource, ResourceBundle
-import reveal
-import scrape
-import setup_pf as setup
 from test_pfif import text_diff
-from text_query import TextQuery
 import utils
 from server_tests_base import ServerTestsBase
 
diff --git a/tests/server_test_cases/import_tests.py b/tests/server_test_cases/import_tests.py
--- a/tests/server_test_cases/import_tests.py
+++ b/tests/server_test_cases/import_tests.py
@@ -16,36 +16,11 @@
 
 """Test cases for end-to-end testing.  Run with the server_tests script."""
 
-import calendar
 import datetime
-import email
-import email.header
-import optparse
 import os
-import pytest
 import re
-import simplejson
-import sys
 import tempfile
-import time
-import unittest
-import urlparse
-
-from google.appengine.api import images
-
-import config
-from const import ROOT_URL, PERSON_STATUS_TEXT, NOTE_STATUS_TEXT
-import download_feed
 from model import *
-from photo import MAX_IMAGE_DIMENSION
-import remote_api
-from resources import Resource, ResourceBundle
-import reveal
-import scrape
-import setup_pf as setup
-from test_pfif import text_diff
-from text_query import TextQuery
-import utils
 from server_tests_base import ServerTestsBase
 
 
diff --git a/tests/server_test_cases/person_note_tests.py b/tests/server_test_cases/person_note_tests.py
--- a/tests/server_test_cases/person_note_tests.py
+++ b/tests/server_test_cases/person_note_tests.py
@@ -19,36 +19,17 @@
 See scrape.py for methods available for the document object returned by self.s.go.
 """
 
-import calendar
 import datetime
-import email
-import email.header
-import optparse
-import os
-import pytest
 import re
-import simplejson
-import sys
-import tempfile
 import time
-import unittest
 import urlparse
 
-from google.appengine.api import images
-
-import config
 from const import ROOT_URL, PERSON_STATUS_TEXT, NOTE_STATUS_TEXT
-import download_feed
 from model import *
-from photo import MAX_IMAGE_DIMENSION
-import remote_api
-from resources import Resource, ResourceBundle
 import reveal
 import scrape
 from scrape import get_all_text, get_all_attrs, get_form_params
-import setup_pf as setup
 from test_pfif import text_diff
-from text_query import TextQuery
 import utils
 from server_tests_base import ServerTestsBase
 
diff --git a/tests/server_test_cases/photo_tests.py b/tests/server_test_cases/photo_tests.py
--- a/tests/server_test_cases/photo_tests.py
+++ b/tests/server_test_cases/photo_tests.py
@@ -16,36 +16,10 @@
 
 """Test cases for end-to-end testing.  Run with the server_tests script."""
 
-import calendar
-import datetime
-import email
-import email.header
-import optparse
-import os
-import pytest
-import re
-import simplejson
-import sys
-import tempfile
-import time
-import unittest
-import urlparse
 
-from google.appengine.api import images
 
-import config
-from const import ROOT_URL, PERSON_STATUS_TEXT, NOTE_STATUS_TEXT
-import download_feed
-from model import *
+from google.appengine.api import images
 from photo import MAX_IMAGE_DIMENSION
-import remote_api
-from resources import Resource, ResourceBundle
-import reveal
-import scrape
-import setup_pf as setup
-from test_pfif import text_diff
-from text_query import TextQuery
-import utils
 from server_tests_base import ServerTestsBase
 
 
diff --git a/tests/server_test_cases/read_only_tests.py b/tests/server_test_cases/read_only_tests.py
--- a/tests/server_test_cases/read_only_tests.py
+++ b/tests/server_test_cases/read_only_tests.py
@@ -16,36 +16,8 @@
 
 """Test cases for end-to-end testing.  Run with the server_tests script."""
 
-import calendar
-import datetime
-import email
-import email.header
-import optparse
-import os
-import pytest
-import re
-import simplejson
-import sys
-import tempfile
-import time
-import unittest
-import urlparse
-
-from google.appengine.api import images
-
-import config
-from const import ROOT_URL, PERSON_STATUS_TEXT, NOTE_STATUS_TEXT
-import download_feed
-from model import *
-from photo import MAX_IMAGE_DIMENSION
-import remote_api
-from resources import Resource, ResourceBundle
-import reveal
+
 import scrape
-import setup_pf as setup
-from test_pfif import text_diff
-from text_query import TextQuery
-import utils
 from server_tests_base import ServerTestsBase
 
 
diff --git a/tests/server_test_cases/resource_tests.py b/tests/server_test_cases/resource_tests.py
--- a/tests/server_test_cases/resource_tests.py
+++ b/tests/server_test_cases/resource_tests.py
@@ -16,36 +16,8 @@
 
 """Test cases for end-to-end testing.  Run with the server_tests script."""
 
-import calendar
-import datetime
-import email
-import email.header
-import optparse
-import os
-import pytest
-import re
-import simplejson
-import sys
-import tempfile
-import time
-import unittest
-import urlparse
-
-from google.appengine.api import images
-
-import config
-from const import ROOT_URL, PERSON_STATUS_TEXT, NOTE_STATUS_TEXT
-import download_feed
 from model import *
-from photo import MAX_IMAGE_DIMENSION
-import remote_api
 from resources import Resource, ResourceBundle
-import reveal
-import scrape
-import setup_pf as setup
-from test_pfif import text_diff
-from text_query import TextQuery
-import utils
 from server_tests_base import ServerTestsBase