diff options
author | Christopher Allan Webber <cwebber@dustycloud.org> | 2012-01-10 08:12:30 -0600 |
---|---|---|
committer | Christopher Allan Webber <cwebber@dustycloud.org> | 2012-01-10 08:12:30 -0600 |
commit | 73079ac4b8a8b3b355867a1e98aca63313597ad0 (patch) | |
tree | 614424e7222f81a29f82e580f5dc97baebffb1f6 | |
parent | 1df68a3524d92caee5601a8acc011ac8e1fe16d4 (diff) | |
parent | 914b8bcde3e01c2dd3e5679fb7733fc194b34d68 (diff) | |
download | mediagoblin-73079ac4b8a8b3b355867a1e98aca63313597ad0.tar.lz mediagoblin-73079ac4b8a8b3b355867a1e98aca63313597ad0.tar.xz mediagoblin-73079ac4b8a8b3b355867a1e98aca63313597ad0.zip |
Merge branch 'master' of gitorious.org:mediagoblin/mediagoblin
Conflicts:
mediagoblin/db/mongo/models.py
-rw-r--r-- | mediagoblin/db/mixin.py | 90 | ||||
-rw-r--r-- | mediagoblin/db/mongo/models.py | 44 | ||||
-rw-r--r-- | mediagoblin/db/sql/models.py | 5 | ||||
-rw-r--r-- | mediagoblin/staticdirect.py | 11 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/base.html | 4 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/user_pages/media.html | 1 | ||||
-rw-r--r-- | mediagoblin/tests/test_mgoblin_app.ini | 3 | ||||
-rw-r--r-- | mediagoblin/tests/test_submission.py | 14 | ||||
-rw-r--r-- | paste.ini | 22 |
9 files changed, 145 insertions, 49 deletions
diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py new file mode 100644 index 00000000..4fb325d2 --- /dev/null +++ b/mediagoblin/db/mixin.py @@ -0,0 +1,90 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011,2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +""" +This module contains some Mixin classes for the db objects. + +A bunch of functions on the db objects are really more like +"utility functions": They could live outside the classes +and be called "by hand" passing the appropiate reference. +They usually only use the public API of the object and +rarely use database related stuff. + +These functions now live here and get "mixed in" into the +real objects. +""" + +from mediagoblin.auth import lib as auth_lib +from mediagoblin.tools import common + + +class UserMixin(object): + def check_login(self, password): + """ + See if a user can login with this password + """ + return auth_lib.bcrypt_check_password( + password, self.pw_hash) + + +class MediaEntryMixin(object): + def get_display_media(self, media_map, + fetch_order=common.DISPLAY_IMAGE_FETCHING_ORDER): + """ + Find the best media for display. + + Args: + - media_map: a dict like + {u'image_size': [u'dir1', u'dir2', u'image.jpg']} + - fetch_order: the order we should try fetching images in + + Returns: + (media_size, media_path) + """ + media_sizes = media_map.keys() + + for media_size in common.DISPLAY_IMAGE_FETCHING_ORDER: + if media_size in media_sizes: + return media_map[media_size] + + def main_mediafile(self): + pass + + def url_for_self(self, urlgen): + """ + Generate an appropriate url for ourselves + + Use a slug if we have one, else use our '_id'. + """ + uploader = self.get_uploader + + if self.get('slug'): + return urlgen( + 'mediagoblin.user_pages.media_home', + user=uploader.username, + media=self.slug) + else: + return urlgen( + 'mediagoblin.user_pages.media_home', + user=uploader.username, + media=unicode(self._id)) + + def get_fail_exception(self): + """ + Get the exception that's appropriate for this error + """ + if self['fail_error']: + return common.import_component(self['fail_error']) diff --git a/mediagoblin/db/mongo/models.py b/mediagoblin/db/mongo/models.py index f1e8eae6..d9b5a570 100644 --- a/mediagoblin/db/mongo/models.py +++ b/mediagoblin/db/mongo/models.py @@ -18,12 +18,12 @@ import datetime from mongokit import Document -from mediagoblin.auth import lib as auth_lib from mediagoblin import mg_globals from mediagoblin.db.mongo import migrations from mediagoblin.db.mongo.util import ASCENDING, DESCENDING, ObjectId from mediagoblin.tools.pagination import Pagination -from mediagoblin.tools import url, common +from mediagoblin.tools import url +from mediagoblin.db.mixin import UserMixin, MediaEntryMixin ################### # Custom validators @@ -34,7 +34,7 @@ from mediagoblin.tools import url, common ######## -class User(Document): +class User(Document, UserMixin): """ A user of MediaGoblin. @@ -89,15 +89,8 @@ class User(Document): 'status': u'needs_email_verification', 'is_admin': False} - def check_login(self, password): - """ - See if a user can login with this password - """ - return auth_lib.bcrypt_check_password( - password, self.pw_hash) - -class MediaEntry(Document): +class MediaEntry(Document, MediaEntryMixin): """ Record of a piece of media. @@ -224,28 +217,6 @@ class MediaEntry(Document): return self.db.MediaComment.find({ 'media_entry': self._id}).sort('created', order) - def get_display_media(self, media_map, - fetch_order=common.DISPLAY_IMAGE_FETCHING_ORDER): - """ - Find the best media for display. - - Args: - - media_map: a dict like - {u'image_size': [u'dir1', u'dir2', u'image.jpg']} - - fetch_order: the order we should try fetching images in - - Returns: - (media_size, media_path) - """ - media_sizes = media_map.keys() - - for media_size in common.DISPLAY_IMAGE_FETCHING_ORDER: - if media_size in media_sizes: - return media_map[media_size] - - def main_mediafile(self): - pass - def generate_slug(self): self.slug = url.slugify(self.title) @@ -303,13 +274,6 @@ class MediaEntry(Document): def get_uploader(self): return self.db.User.find_one({'_id': self.uploader}) - def get_fail_exception(self): - """ - Get the exception that's appropriate for this error - """ - if self['fail_error']: - return common.import_component(self['fail_error']) - class MediaComment(Document): """ diff --git a/mediagoblin/db/sql/models.py b/mediagoblin/db/sql/models.py index 31a6ed3b..95821b4f 100644 --- a/mediagoblin/db/sql/models.py +++ b/mediagoblin/db/sql/models.py @@ -7,6 +7,7 @@ from sqlalchemy import ( from sqlalchemy.orm import relationship from mediagoblin.db.sql.base import GMGTableBase +from mediagoblin.db.mixin import UserMixin, MediaEntryMixin Base = declarative_base(cls=GMGTableBase) @@ -24,7 +25,7 @@ class SimpleFieldAlias(object): setattr(instance, self.fieldname, val) -class User(Base): +class User(Base, UserMixin): __tablename__ = "users" id = Column(Integer, primary_key=True) @@ -48,7 +49,7 @@ class User(Base): _id = SimpleFieldAlias("id") -class MediaEntry(Base): +class MediaEntry(Base, MediaEntryMixin): __tablename__ = "media_entries" id = Column(Integer, primary_key=True) diff --git a/mediagoblin/staticdirect.py b/mediagoblin/staticdirect.py index c6d2b374..2bddb160 100644 --- a/mediagoblin/staticdirect.py +++ b/mediagoblin/staticdirect.py @@ -14,9 +14,6 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import pkg_resources -import urlparse - #################################### # Staticdirect infrastructure. # Borrowed largely from cc.engine @@ -26,7 +23,9 @@ import urlparse #################################### import pkg_resources -import urlparse +import logging + +_log = logging.getLogger(__name__) class StaticDirect(object): @@ -37,6 +36,10 @@ class StaticDirect(object): if filepath in self.cache: return self.cache[filepath] + if not pkg_resources.resource_exists('mediagoblin', + 'static' + filepath): + _log.info("StaticDirect resource %r not found locally", + filepath) static_direction = self.cache[filepath] = self.get(filepath) return static_direction diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html index 82ee41b7..5335ebe3 100644 --- a/mediagoblin/templates/mediagoblin/base.html +++ b/mediagoblin/templates/mediagoblin/base.html @@ -22,11 +22,9 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <title>{% block title %}{{ app_config['html_title'] }}{% endblock %}</title> <link rel="stylesheet" type="text/css" - href="{{ request.staticdirect('/css/reset.css') }}"/> + href="{{ request.staticdirect('/css/extlib/reset.css') }}"/> <link rel="stylesheet" type="text/css" href="{{ request.staticdirect('/css/base.css') }}"/> - <link rel="stylesheet" type="text/css" - href="{{ request.staticdirect('/css/video-js.css') }}"/> <link rel="shortcut icon" href="{{ request.staticdirect('/images/goblin.ico') }}" /> <script src="{{ request.staticdirect('/js/extlib/jquery.js') }}"></script> diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html index 10525f4c..583e4ebd 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media.html @@ -158,6 +158,7 @@ </ul> {% endif %} {% if app_config['allow_attachments'] + and request.user and (media.uploader == request.user._id or request.user.is_admin) %} <p> diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini index 2525a4f9..c91ed92b 100644 --- a/mediagoblin/tests/test_mgoblin_app.ini +++ b/mediagoblin/tests/test_mgoblin_app.ini @@ -7,6 +7,9 @@ db_name = __mediagoblin_tests__ # tag parsing tags_max_length = 50 +# So we can start to test attachments: +allow_attachments = True + # Celery shouldn't be set up by the application as it's setup via # mediagoblin.init.celery.from_celery celery_setup_elsewhere = true diff --git a/mediagoblin/tests/test_submission.py b/mediagoblin/tests/test_submission.py index 2b17c515..b3c11249 100644 --- a/mediagoblin/tests/test_submission.py +++ b/mediagoblin/tests/test_submission.py @@ -51,11 +51,17 @@ class TestSubmission: self.test_user = test_user + self.login() + + def login(self): self.test_app.post( '/auth/login/', { 'username': u'chris', 'password': 'toast'}) + def logout(self): + self.test_app.get('/auth/logout/') + def test_missing_fields(self): # Test blank form # --------------- @@ -95,6 +101,14 @@ class TestSubmission: assert template.TEMPLATE_TEST_CONTEXT.has_key( 'mediagoblin/user_pages/user.html') + # Make sure the media view is at least reachable, logged in... + self.test_app.get('/u/chris/m/normal-upload-1/') + # ... and logged out too. + self.logout() + self.test_app.get('/u/chris/m/normal-upload-1/') + # Log back in for the remaining tests. + self.login() + # Test PNG # -------- template.clear_test_template_context() @@ -19,6 +19,28 @@ use = egg:mediagoblin#app filter-with = beaker config = %(here)s/mediagoblin_local.ini %(here)s/mediagoblin.ini +[loggers] +keys = root + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-7.7s [%(name)s] %(message)s + [app:publicstore_serve] use = egg:Paste#static document_root = %(here)s/user_dev/media/public/ |