Added a url_for_self method for generating mediaentry links
[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
86f9b473 20from paste.deploy.converters import asbool
b61874b2 21from webob import Request, exc
31a8ff42 22
0f18ed8f 23from mediagoblin import routing, util, storage, staticdirect
a67fec81 24from mediagoblin.db.open import setup_connection_and_db_from_config
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 """
a67fec81 37 def __init__(self, connection, db,
5afdd7a1 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
a67fec81 51 self.db = db
5afdd7a1
CAW
52
53 # set up routing
0f63a944 54 self.routing = routing.get_mapper()
31a8ff42 55
582c4d5f
CAW
56 # set up staticdirector tool
57 self.staticdirector = staticdirector
2b4e236a 58
df9809c2
CAW
59 # certain properties need to be accessed globally eg from
60 # validators, etc, which might not access to the request
61 # object.
62 setup_globals(
4c093e85 63 email_sender_address=email_sender_address,
29f3fb70 64 email_debug_mode=email_debug_mode,
df9809c2
CAW
65 db_connection=connection,
66 database=self.db,
67 public_store=self.public_store,
68 queue_store=self.queue_store)
69
31a8ff42
CAW
70 def __call__(self, environ, start_response):
71 request = Request(environ)
72 path_info = request.path_info
582c4d5f
CAW
73
74 ## Routing / controller loading stuff
0f63a944 75 route_match = self.routing.match(path_info)
31a8ff42
CAW
76
77 # No matching page?
78 if route_match is None:
79 # Try to do see if we have a match with a trailing slash
80 # added and if so, redirect
81 if not path_info.endswith('/') \
82 and request.method == 'GET' \
0f63a944 83 and self.routing.match(path_info + '/'):
31a8ff42
CAW
84 new_path_info = path_info + '/'
85 if request.GET:
86 new_path_info = '%s?%s' % (
87 new_path_info, urllib.urlencode(request.GET))
1bb0fdf2 88 redirect = exc.HTTPFound(location=new_path_info)
31a8ff42
CAW
89 return request.get_response(redirect)(environ, start_response)
90
91 # Okay, no matches. 404 time!
92 return exc.HTTPNotFound()(environ, start_response)
93
cb8ea0fe 94 controller = util.import_component(route_match['controller'])
31a8ff42
CAW
95 request.start_response = start_response
96
582c4d5f 97 ## Attach utilities to the request object
31a8ff42 98 request.matchdict = route_match
0f63a944 99 request.urlgen = routes.URLGenerator(self.routing, environ)
7846e406 100 # Do we really want to load this via middleware? Maybe?
14ba9383 101 request.session = request.environ['beaker.session']
0dd65945
CAW
102 # Attach self as request.app
103 # Also attach a few utilities from request.app for convenience?
104 request.app = self
0e0e3d9a
CAW
105 request.locale = util.get_locale_from_request(request)
106
107 request.template_env = util.get_jinja_env(
108 self.template_loader, request.locale)
0dd65945
CAW
109 request.db = self.db
110 request.staticdirect = self.staticdirector
31a8ff42 111
ddff7cce
CAW
112 util.setup_user_in_request(request)
113
31a8ff42
CAW
114 return controller(request)(environ, start_response)
115
116
5784c4e9 117def paste_app_factory(global_config, **app_config):
cb8ea0fe 118 # Get the database connection
a67fec81 119 connection, db = setup_connection_and_db_from_config(app_config)
73e0dbcc 120
cb8ea0fe 121 # Set up the storage systems.
5afdd7a1 122 public_store = storage.storage_system_from_paste_config(
5784c4e9 123 app_config, 'publicstore')
5afdd7a1 124 queue_store = storage.storage_system_from_paste_config(
5784c4e9 125 app_config, 'queuestore')
5afdd7a1 126
582c4d5f 127 # Set up the staticdirect system
5784c4e9 128 if app_config.has_key('direct_remote_path'):
582c4d5f 129 staticdirector = staticdirect.RemoteStaticDirect(
5784c4e9
CAW
130 app_config['direct_remote_path'].strip())
131 elif app_config.has_key('direct_remote_paths'):
132 direct_remote_path_lines = app_config[
133 'direct_remote_paths'].strip().splitlines()
582c4d5f
CAW
134 staticdirector = staticdirect.MultiRemoteStaticDirect(
135 dict([line.strip().split(' ', 1)
5784c4e9 136 for line in direct_remote_path_lines]))
582c4d5f
CAW
137 else:
138 raise ImproperlyConfigured(
139 "One of direct_remote_path or direct_remote_paths must be provided")
140
5784c4e9
CAW
141 setup_celery_from_config(app_config, global_config)
142
8e1e744d 143 mgoblin_app = MediaGoblinApp(
a67fec81 144 connection, db,
5afdd7a1 145 public_store=public_store, queue_store=queue_store,
582c4d5f 146 staticdirector=staticdirector,
29f3fb70
CAW
147 email_sender_address=app_config.get(
148 'email_sender_address', 'notice@mediagoblin.example.org'),
cd847fd3 149 email_debug_mode=asbool(app_config.get('email_debug_mode')),
5784c4e9 150 user_template_path=app_config.get('local_templates'))
b61874b2 151
c4d71564 152 return mgoblin_app