min=0 makes more sense than min=-1
[mediagoblin.git] / mediagoblin / app.py
CommitLineData
8e1e744d 1# GNU MediaGoblin -- federated, autonomous media hosting
e5572c60
ML
2# Copyright (C) 2011 Free Software Foundation, Inc
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
31a8ff42
CAW
17import urllib
18
31a8ff42 19import routes
2b4e236a 20import mongokit
cd847fd3 21from paste.deploy.converters import asbool, asint
b61874b2 22from webob import Request, exc
31a8ff42 23
582c4d5f 24from mediagoblin import routing, util, models, storage, staticdirect
df9809c2 25from mediagoblin.globals import setup_globals
5784c4e9 26from mediagoblin.celery_setup import setup_celery_from_config
31a8ff42
CAW
27
28
29class Error(Exception): pass
30class ImproperlyConfigured(Error): pass
31
32
8e1e744d 33class MediaGoblinApp(object):
31a8ff42
CAW
34 """
35 Really basic wsgi app using routes and WebOb.
36 """
5afdd7a1
CAW
37 def __init__(self, connection, database_path,
38 public_store, queue_store,
582c4d5f 39 staticdirector,
29f3fb70 40 email_sender_address, email_debug_mode,
5afdd7a1
CAW
41 user_template_path=None):
42 # Get the template environment
0e0e3d9a 43 self.template_loader = util.get_jinja_loader(user_template_path)
5afdd7a1
CAW
44
45 # Set up storage systems
46 self.public_store = public_store
47 self.queue_store = queue_store
48
49 # Set up database
2b4e236a 50 self.connection = connection
65d7374c 51 self.db = connection[database_path]
5afdd7a1
CAW
52 models.register_models(connection)
53
54 # set up routing
0f63a944 55 self.routing = routing.get_mapper()
31a8ff42 56
582c4d5f
CAW
57 # set up staticdirector tool
58 self.staticdirector = staticdirector
2b4e236a 59
df9809c2
CAW
60 # certain properties need to be accessed globally eg from
61 # validators, etc, which might not access to the request
62 # object.
63 setup_globals(
4c093e85 64 email_sender_address=email_sender_address,
29f3fb70 65 email_debug_mode=email_debug_mode,
df9809c2
CAW
66 db_connection=connection,
67 database=self.db,
68 public_store=self.public_store,
69 queue_store=self.queue_store)
70
31a8ff42
CAW
71 def __call__(self, environ, start_response):
72 request = Request(environ)
73 path_info = request.path_info
582c4d5f
CAW
74
75 ## Routing / controller loading stuff
0f63a944 76 route_match = self.routing.match(path_info)
31a8ff42
CAW
77
78 # No matching page?
79 if route_match is None:
80 # Try to do see if we have a match with a trailing slash
81 # added and if so, redirect
82 if not path_info.endswith('/') \
83 and request.method == 'GET' \
0f63a944 84 and self.routing.match(path_info + '/'):
31a8ff42
CAW
85 new_path_info = path_info + '/'
86 if request.GET:
87 new_path_info = '%s?%s' % (
88 new_path_info, urllib.urlencode(request.GET))
1bb0fdf2 89 redirect = exc.HTTPFound(location=new_path_info)
31a8ff42
CAW
90 return request.get_response(redirect)(environ, start_response)
91
92 # Okay, no matches. 404 time!
93 return exc.HTTPNotFound()(environ, start_response)
94
cb8ea0fe 95 controller = util.import_component(route_match['controller'])
31a8ff42
CAW
96 request.start_response = start_response
97
582c4d5f 98 ## Attach utilities to the request object
31a8ff42 99 request.matchdict = route_match
0f63a944 100 request.urlgen = routes.URLGenerator(self.routing, environ)
7846e406 101 # Do we really want to load this via middleware? Maybe?
14ba9383 102 request.session = request.environ['beaker.session']
0dd65945
CAW
103 # Attach self as request.app
104 # Also attach a few utilities from request.app for convenience?
105 request.app = self
0e0e3d9a
CAW
106 request.locale = util.get_locale_from_request(request)
107
108 request.template_env = util.get_jinja_env(
109 self.template_loader, request.locale)
0dd65945
CAW
110 request.db = self.db
111 request.staticdirect = self.staticdirector
31a8ff42 112
ddff7cce
CAW
113 util.setup_user_in_request(request)
114
31a8ff42
CAW
115 return controller(request)(environ, start_response)
116
117
5784c4e9 118def paste_app_factory(global_config, **app_config):
cb8ea0fe 119 # Get the database connection
a1eb1f60
CAW
120 port = app_config.get('db_port')
121 if port:
122 port = asint(port)
2b4e236a 123 connection = mongokit.Connection(
19f8a24e 124 app_config.get('db_host'), port)
73e0dbcc 125
cb8ea0fe 126 # Set up the storage systems.
5afdd7a1 127 public_store = storage.storage_system_from_paste_config(
5784c4e9 128 app_config, 'publicstore')
5afdd7a1 129 queue_store = storage.storage_system_from_paste_config(
5784c4e9 130 app_config, 'queuestore')
5afdd7a1 131
582c4d5f 132 # Set up the staticdirect system
5784c4e9 133 if app_config.has_key('direct_remote_path'):
582c4d5f 134 staticdirector = staticdirect.RemoteStaticDirect(
5784c4e9
CAW
135 app_config['direct_remote_path'].strip())
136 elif app_config.has_key('direct_remote_paths'):
137 direct_remote_path_lines = app_config[
138 'direct_remote_paths'].strip().splitlines()
582c4d5f
CAW
139 staticdirector = staticdirect.MultiRemoteStaticDirect(
140 dict([line.strip().split(' ', 1)
5784c4e9 141 for line in direct_remote_path_lines]))
582c4d5f
CAW
142 else:
143 raise ImproperlyConfigured(
144 "One of direct_remote_path or direct_remote_paths must be provided")
145
5784c4e9
CAW
146 setup_celery_from_config(app_config, global_config)
147
8e1e744d 148 mgoblin_app = MediaGoblinApp(
5784c4e9 149 connection, app_config.get('db_name', 'mediagoblin'),
5afdd7a1 150 public_store=public_store, queue_store=queue_store,
582c4d5f 151 staticdirector=staticdirector,
29f3fb70
CAW
152 email_sender_address=app_config.get(
153 'email_sender_address', 'notice@mediagoblin.example.org'),
cd847fd3 154 email_debug_mode=asbool(app_config.get('email_debug_mode')),
5784c4e9 155 user_template_path=app_config.get('local_templates'))
b61874b2 156
c4d71564 157 return mgoblin_app