diff --git a/docs/git.rst b/docs/git.rst
index c3f7ccce..2836ecd8 100644
--- a/docs/git.rst
+++ b/docs/git.rst
@@ -108,8 +108,8 @@ Contributing changes
--------------------
Slartibartfast from the planet Magrathea far off in the universe has
-decided that he is bored with fjords and wants to fix issue 42 and
-send us the changes.
+decided that he is bored with fjords and wants to fix issue 42 (the
+meaning of life bug) and send us the changes.
Slartibartfast has cloned the MediaGoblin repository and his clone
lives on gitorious.
@@ -125,18 +125,18 @@ Slartibartfast does the following:
git fetch --all -p
2. Creates a branch from the tip of the MediaGoblin repository (the
- remote is named ``gmg``) master branch called ``issue_42``::
+ remote is named ``gmg``) master branch called ``bug42_meaning_of_life``::
- git checkout -b issue_42 gmg/master
+ git checkout -b bug42_meaning_of_life gmg/master
-3. Slartibartfast works hard on his changes in the ``issue_42``
+3. Slartibartfast works hard on his changes in the ``bug42_meaning_of_life``
branch. When done, he wants to notify us that he has made changes
he wants us to see.
4. Slartibartfast pushes his changes to his clone (the remote is named
``origin``)::
- git push origin issue_42 --set-upstream
+ git push origin bug42_meaning_of_life --set-upstream
5. Slartibartfast adds a comment to issue 42 with the url for his
repository and the name of the branch he put the code in. He also
@@ -155,19 +155,19 @@ He runs the unit tests and discovers there's a bug in the code!
Then he does this:
-1. He checks out the ``issue_42`` branch::
+1. He checks out the ``bug42_meaning_of_life`` branch::
- git checkout issue_42
+ git checkout bug42_meaning_of_life
-2. He fixes the bug and checks it into the ``issue_42`` branch.
+2. He fixes the bug and checks it into the ``bug42_meaning_of_life`` branch.
3. He pushes his changes to his clone (the remote is named ``origin``)::
- git push origin issue_42
+ git push origin bug42_meaning_of_life
4. He adds another comment to issue 42 explaining about the mistake
and how he fixed it and that he's pushed the new change to the
- ``issue_42`` branch of his publicly available clone.
+ ``bug42_meaning_of_life`` branch of his publicly available clone.
What happens next
@@ -180,7 +180,7 @@ request with his changes and explains what they are.
Later, someone checks out his code and finds a problem with it. He
adds a comment to the issue tracker specifying the problem and asks
Slartibartfast to fix it. Slartibartfst goes through the above steps
-again, fixes the issue, pushes it to his ``issue_42`` branch and adds
+again, fixes the issue, pushes it to his ``bug42_meaning_of_life`` branch and adds
another comment to the issue tracker about how he fixed it.
Later, someone checks out his code and is happy with it. Someone
@@ -192,8 +192,8 @@ Slartibartfast is notified of this. Slartibartfast does a::
git fetch --all
The changes show up in the ``master`` branch of the ``gmg`` remote.
-Slartibartfast now deletes his ``issue_42`` branch because he doesn't
-need it anymore.
+Slartibartfast now deletes his ``bug42_meaning_of_life`` branch
+because he doesn't need it anymore.
How to learn git
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index fcab5844..911f2340 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -136,7 +136,7 @@ This is fine in development, but if you want to actually run celery
separately for testing (or deployment purposes), you'll want to run
the server independently::
- ./bin/paster serve server.ini --reload
+ ./bin/paster serve paste.ini --reload
Running celeryd
@@ -158,7 +158,7 @@ Running the test suite
Run::
- ./bin/nosetests
+ ./runtests.sh
Running a shell
diff --git a/lazyserver.sh b/lazyserver.sh
index bd93b109..fdb03ba0 100755
--- a/lazyserver.sh
+++ b/lazyserver.sh
@@ -27,4 +27,4 @@ else
exit 1
fi
-CELERY_ALWAYS_EAGER=true $PASTER serve server.ini --reload
+CELERY_ALWAYS_EAGER=true $PASTER serve paste.ini --reload
diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py
index f1f625b7..b87988fe 100644
--- a/mediagoblin/db/migrations.py
+++ b/mediagoblin/db/migrations.py
@@ -14,6 +14,8 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see
-
{{ media.description }}
+ {% autoescape False %} +{{ media.description_html }}
+ {% endautoescape %}Uploaded on {{ "%4d-%02d-%02d"|format(media.created.year, media.created.month, media.created.day) }} diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py index b8389f8d..3a13cbb1 100644 --- a/mediagoblin/tests/test_auth.py +++ b/mediagoblin/tests/test_auth.py @@ -242,17 +242,69 @@ def test_authentication_views(test_app): test_user.save() # Get login + # --------- test_app.get('/auth/login/') - # Make sure it rendered with the appropriate template assert util.TEMPLATE_TEST_CONTEXT.has_key( 'mediagoblin/auth/login.html') - # Log in as that user + # Failed login - blank form + # ------------------------- + util.clear_test_template_context() + response = test_app.post('/auth/login/') + context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html'] + form = context['login_form'] + assert form.username.errors == [u'This field is required.'] + assert form.password.errors == [u'This field is required.'] + + # Failed login - blank user + # ------------------------- + util.clear_test_template_context() + response = test_app.post( + '/auth/login/', { + 'password': u'toast'}) + context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html'] + form = context['login_form'] + assert form.username.errors == [u'This field is required.'] + + # Failed login - blank password + # ----------------------------- + util.clear_test_template_context() + response = test_app.post( + '/auth/login/', { + 'username': u'chris'}) + context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html'] + form = context['login_form'] + assert form.password.errors == [u'This field is required.'] + + # Failed login - bad user + # ----------------------- + util.clear_test_template_context() + response = test_app.post( + '/auth/login/', { + 'username': u'steve', + 'password': 'toast'}) + context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html'] + assert context['login_failed'] + + # Failed login - bad password + # --------------------------- + util.clear_test_template_context() + response = test_app.post( + '/auth/login/', { + 'username': u'chris', + 'password': 'jam'}) + context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html'] + assert context['login_failed'] + + # Successful login + # ---------------- util.clear_test_template_context() response = test_app.post( '/auth/login/', { 'username': u'chris', 'password': 'toast'}) + + # User should be redirected response.follow() assert_equal( urlparse.urlsplit(response.location)[2], @@ -260,10 +312,38 @@ def test_authentication_views(test_app): assert util.TEMPLATE_TEST_CONTEXT.has_key( 'mediagoblin/root.html') - # Make sure we're in the session or something - session = util.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']['request'].session + # Make sure user is in the session + context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html'] + session = context['request'].session assert session['user_id'] == unicode(test_user['_id']) - # Log out as that user - # Make sure we're not in the session + # Successful logout + # ----------------- + util.clear_test_template_context() + response = test_app.get('/auth/logout/') + + # Should be redirected to index page + response.follow() + assert_equal( + urlparse.urlsplit(response.location)[2], + '/') + assert util.TEMPLATE_TEST_CONTEXT.has_key( + 'mediagoblin/root.html') + + # Make sure the user is not in the session + context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html'] + session = context['request'].session + assert session.has_key('user_id') == False + + # User is redirected to custom URL if POST['next'] is set + # ------------------------------------------------------- + util.clear_test_template_context() + response = test_app.post( + '/auth/login/', { + 'username': u'chris', + 'password': 'toast', + 'next' : '/u/chris/'}) + assert_equal( + urlparse.urlsplit(response.location)[2], + '/u/chris/') diff --git a/mediagoblin/tests/test_server.ini b/mediagoblin/tests/test_paste.ini similarity index 100% rename from mediagoblin/tests/test_server.ini rename to mediagoblin/tests/test_paste.ini diff --git a/mediagoblin/tests/tools.py b/mediagoblin/tests/tools.py index 515bccd4..9e36fc5c 100644 --- a/mediagoblin/tests/tools.py +++ b/mediagoblin/tests/tools.py @@ -30,7 +30,7 @@ from mediagoblin.db.open import setup_connection_and_db_from_config MEDIAGOBLIN_TEST_DB_NAME = '__mediagoblinunittests__' TEST_SERVER_CONFIG = pkg_resources.resource_filename( - 'mediagoblin.tests', 'test_server.ini') + 'mediagoblin.tests', 'test_paste.ini') TEST_APP_CONFIG = pkg_resources.resource_filename( 'mediagoblin.tests', 'test_mgoblin_app.ini') TEST_USER_DEV = pkg_resources.resource_filename( diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py index 88b5dfe5..d6cd6034 100644 --- a/mediagoblin/user_pages/views.py +++ b/mediagoblin/user_pages/views.py @@ -108,10 +108,10 @@ def atom_feed(request): feed = AtomFeed(request.matchdict['user'], feed_url=request.url, url=request.host_url) - + for entry in cursor: feed.add(entry.get('title'), - entry.get('description'), + entry.get('description_html'), content_type='html', author=request.matchdict['user'], updated=entry.get('created'), diff --git a/mediagoblin/util.py b/mediagoblin/util.py index 349bc027..0e43a1f5 100644 --- a/mediagoblin/util.py +++ b/mediagoblin/util.py @@ -29,11 +29,11 @@ import jinja2 import translitcodec from webob import Response, exc from lxml.html.clean import Cleaner +import markdown from mediagoblin import mg_globals from mediagoblin.db.util import ObjectId - TESTS_ENABLED = False def _activate_testing(): """ @@ -98,7 +98,7 @@ def get_jinja_env(template_loader, locale): template_env = jinja2.Environment( loader=template_loader, autoescape=True, - extensions=['jinja2.ext.i18n']) + extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape']) template_env.install_gettext_callables( mg_globals.translations.gettext, @@ -376,6 +376,16 @@ def clean_html(html): return HTML_CLEANER.clean_html(html) +MARKDOWN_INSTANCE = markdown.Markdown(safe_mode='escape') + + +def cleaned_markdown_conversion(text): + """ + Take a block of text, run it through MarkDown, and clean its HTML. + """ + return clean_html(MARKDOWN_INSTANCE.convert(text)) + + SETUP_GETTEXTS = {} def setup_gettext(locale): diff --git a/server.ini b/paste.ini similarity index 100% rename from server.ini rename to paste.ini diff --git a/setup.py b/setup.py index cd0e7f0b..2a007f4e 100644 --- a/setup.py +++ b/setup.py @@ -43,6 +43,7 @@ setup( 'argparse', 'webtest', 'ConfigObj', + 'Markdown', ## For now we're expecting that users will install this from ## their package managers. # 'lxml',