Merge branch 'master' of gitorious.org:mediagoblin/mediagoblin
Conflicts: mediagoblin/db/mongo/models.py
This commit is contained in:
commit
73079ac4b8
90
mediagoblin/db/mixin.py
Normal file
90
mediagoblin/db/mixin.py
Normal file
@ -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'])
|
@ -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):
|
||||
"""
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
22
paste.ini
22
paste.ini
@ -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/
|
||||
|
Loading…
x
Reference in New Issue
Block a user