Re: [TurboGears] restrict acces to static/public files

123 views
Skip to first unread message

Alessandro Molina

unread,
Jun 18, 2012, 4:28:58 PM6/18/12
to turbo...@googlegroups.com
Static files are served by a middleware in the WSGI chain,
this runs before the authentication layer got in, so it doesn't have
any knowledge of users.

You can roll your own statics serving controller which checks users
and so on, a minima solution can be:

class StaticsController(TGController):
@expose()
def _lookup(self, *args):
return WSGIAppController(StaticURLParser(statics_path)), args

On Mon, Jun 18, 2012 at 2:39 PM, abc_coder <jasinsk...@gmail.com> wrote:
> Hi all
>
> I searched a lot but haven’t found any solution. How can I in turgobears 2
> restrict access to static files only for logged users?
> I want add some protection from unlogged users and web robots.
>
> Please help.
>
> --
> You received this message because you are subscribed to the Google Groups
> "TurboGears" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/turbogears/-/a6oOER4Ps3cJ.
> To post to this group, send email to turbo...@googlegroups.com.
> To unsubscribe from this group, send email to
> turbogears+...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/turbogears?hl=en.

abc_coder

unread,
Jun 19, 2012, 9:10:57 AM6/19/12
to turbo...@googlegroups.com
Thanks for response.
As I understood I need some way to connect turbogears auth with file server auth.
Is there any aplication or add-on to turbogears doing that?
I found one for Django:
http://django-private-files.readthedocs.org/en/0.1.2/index.html
> turbogears+unsubscribe@googlegroups.com.

Alessandro Molina

unread,
Jun 19, 2012, 3:30:59 PM6/19/12
to turbo...@googlegroups.com
There is no such extension, but doing it is just a bunch of lines of
code using the _lookup method.

My example in the previous message provides a quick solution, you just
have to mount that controller as "privatefiles" or something like that
and add a check for request.identity['user'] raising HTTPNotFound or
similar in the case he cannot access the file.
If you are behind a more advanced server you can use the xsendfile
header to let the frontend server take care of the file to serve
without exposing it.
>> > turbogears+...@googlegroups.com.
>> > For more options, visit this group at
>> > http://groups.google.com/group/turbogears?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups
> "TurboGears" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/turbogears/-/1cPLCF7zHFYJ.
>
> To post to this group, send email to turbo...@googlegroups.com.
> To unsubscribe from this group, send email to
> turbogears+...@googlegroups.com.
Message has been deleted

Alessandro Molina

unread,
Jul 4, 2013, 8:16:14 AM7/4/13
to TurboGears

Hi
Which version of turbogears? My solution is explicitly only for turbogears2. That might be the reason TGController is not available

Il giorno 04/lug/2013 12:59, "Maxim Oganesyan" <maxim.o...@gmail.com> ha scritto:
Hi, Alessandro!
I'm trying to use Your solution.

I've got a question:
from ???? import TGController

import TGController does not work...

Best regards.
Maxim.

вторник, 19 июня 2012 г., 0:28:58 UTC+4 пользователь Alessandro Molina написал:
To unsubscribe from this group and stop receiving emails from it, send an email to turbogears+...@googlegroups.com.

To post to this group, send email to turbo...@googlegroups.com.
Visit this group at http://groups.google.com/group/turbogears.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Maxim Oganesyan

unread,
Jul 4, 2013, 8:51:41 AM7/4/13
to turbo...@googlegroups.com
I found solution after "googling". After that I removed post (well, I can remove post, but I can't stop email :) )

My code is now:

from tg.controllers.tgcontroller import TGController                   
from tg.controllers import WSGIAppController                           
                                                                       
class PrivateStatics(TGController):                                    
    @expose()                                                          
    def lookup(self, *args):                                           
        site_dir = os.path.join(config.get('here'), '/myapp/private')
        return WSGIAppController(StaticURLParser(site_dir)), args      
                                                                       
    _lookup = lookup                                                   


But when I try to get files using path "http://www.mysite.com/private/img.png" I have another error:

Traceback (most recent call last):
File "/www/tg2env/local/lib/python2.7/site-packages/Paste-1.7.5.1-py2.7.egg/paste/httpserver.py", line 1068, in process_request_in_thread
self.finish_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 323, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib/python2.7/SocketServer.py", line 638, in __init__
self.handle()
File "/www/tg2env/local/lib/python2.7/site-packages/Paste-1.7.5.1-py2.7.egg/paste/httpserver.py", line 442, in handle
BaseHTTPRequestHandler.handle(self)
File "/usr/lib/python2.7/BaseHTTPServer.py", line 340, in handle
self.handle_one_request()
File "/www/tg2env/local/lib/python2.7/site-packages/Paste-1.7.5.1-py2.7.egg/paste/httpserver.py", line 437, in handle_one_request
self.wsgi_execute()
File "/www/tg2env/local/lib/python2.7/site-packages/Paste-1.7.5.1-py2.7.egg/paste/httpserver.py", line 287, in wsgi_execute
self.wsgi_start_response)
File "/www/tg2env/local/lib/python2.7/site-packages/Paste-1.7.5.1-py2.7.egg/paste/cascade.py", line 130, in __call__
return self.apps[-1](environ, start_response)
File "/www/tg2env/local/lib/python2.7/site-packages/Paste-1.7.5.1-py2.7.egg/paste/registry.py", line 379, in __call__ app_iter = self.application(environ, start_response)
File "/www/tg2env/local/lib/python2.7/site-packages/Pylons-1.0-py2.7.egg/pylons/middleware.py", line 150, in __call__
self.app, environ, catch_exc_info=True)
File "/www/tg2env/local/lib/python2.7/site-packages/Pylons-1.0-py2.7.egg/pylons/util.py", line 48, in call_wsgi_application
app_iter = application(environ, start_response)
File "/www/tg2env/local/lib/python2.7/site-packages/WebError-0.10.3-py2.7.egg/weberror/evalexception.py", line 235, in __call__
return self.respond(environ, start_response)
File "/www/tg2env/local/lib/python2.7/site-packages/WebError-0.10.3-py2.7.egg/weberror/evalexception.py", line 483, in respond
return debug_info.content()
File "/www/tg2env/local/lib/python2.7/site-packages/WebError-0.10.3-py2.7.egg/weberror/evalexception.py", line 539, in content
self.base_path, self.counter, self.libraries)
File "/www/tg2env/local/lib/python2.7/site-packages/WebError-0.10.3-py2.7.egg/weberror/evalexception.py", line 657, in format_eval_html
short_er, extra_data = short_formatter.format_collected_data(exc_data)
File "/www/tg2env/local/lib/python2.7/site-packages/WebError-0.10.3-py2.7.egg/weberror/formatter.py", line 73, in format_collected_data
importance, title, value)
File "/www/tg2env/local/lib/python2.7/site-packages/WebError-0.10.3-py2.7.egg/weberror/formatter.py", line 345, in format_extra_data
return self.zebra_table(title, value)
File "/www/tg2env/local/lib/python2.7/site-packages/WebError-0.10.3-py2.7.egg/weberror/formatter.py", line 390, in zebra_table
% make_wrappable(self.quote(truncate(value))))
File "/www/tg2env/local/lib/python2.7/site-packages/WebError-0.10.3-py2.7.egg/weberror/formatter.py", line 295, in quote
s = s.encode('latin1', 'htmlentityreplace')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd0 in position 279: ordinal not in range(128)


The same error was when I wrote Your part of code without importing TGController and WSGIAppController.
Looks like I missed something... :(

четверг, 4 июля 2013 г., 16:16:14 UTC+4 пользователь Alessandro Molina написал:

Maxim Oganesyan

unread,
Jul 4, 2013, 8:53:31 AM7/4/13
to turbo...@googlegroups.com
tg.__version__ is '2.2.2'

Maxim Oganesyan

unread,
Jul 4, 2013, 9:14:44 AM7/4/13
to turbo...@googlegroups.com

I'm sorry. The reason of error was in "display_name" property of "User" class (it is written in Unicode). So to see error log I have to logout.

Also 3 lines are required:

from paste.urlparser import StaticURLParser
from tg import config
import os

And of course we need a line inside RootController:

private = PrivateStatics()

But in the end I have 404 error...

Sorry for interruption...

четверг, 4 июля 2013 г., 16:51:41 UTC+4 пользователь Maxim Oganesyan написал:

Maxim Oganesyan

unread,
Jul 4, 2013, 9:19:54 AM7/4/13
to turbo...@googlegroups.com
Well, using os.path.join does not need slashes.
My mistake was using '/myapp/private' instead of 'myapp/private'.

It works, deamn it!

Thank You for solution and I'm sorry for time loss.
Best regards!
Maxim.

abc_coder

unread,
Jun 23, 2016, 10:05:34 AM6/23/16
to TurboGears
Hi all

I have some problem with my script

I try to use this example in turbogears 2.3.8

# -*- coding: utf-8 -*-
from tg.controllers.tgcontroller import TGController
from tg.predicates import not_anonymous
from tg import expose, config
import os

try:
   
from tg.controllers import WSGIAppController
except ImportError:
   
from tg.controllers.wsgiappcontroller import WSGIAppController

try:
   
from paste.urlparser import StaticURLParser
except ImportError:
   
from  webob.static import DirectoryApp as StaticURLParser


                                                                       
class PrivateStatics(TGController):                                    
   
@expose()                                                          
   
def lookup(self, *args):                                          
        site_dir
= os.path.join(config.get('here'), '/myapp/private')

       
return WSGIAppController(StaticURLParser(site_dir), allow_only=not_anonymous()), args
                                                                       
    _lookup
= lookup

and I got the error:

RuntimeError: Mounting nested WSGI apps requires make_body_seekable=True option

what am I doing wrong or how can I set this option ?


W dniu poniedziałek, 18 czerwca 2012 22:28:58 UTC+2 użytkownik Alessandro Molina napisał:

Alessandro Molina

unread,
Jun 24, 2016, 6:13:56 PM6/24/16
to TurboGears
On Thu, Jun 23, 2016 at 4:05 PM, abc_coder <jasinsk...@gmail.com> wrote:
what am I doing wrong or how can I set this option ?

As stated by the error being able to call a WSGI Application from inside TG itself requires the request body to be seekable, as both TG and the app need to be able to consume it. This is usually disable for performance reasons, see http://docs.webob.org/en/stable/api/request.html#webob.request.BaseRequest.make_body_seekable

Just set base_config['make_body_seekable'] = True in your app_cfg.py and it should work.

But note that as DirectoryApp allows to be called with a request and returns a Response, you can probably just do "return DirectoryApp(site_dir)(tg.request)" without the need to use WSGIAppController

abc_coder

unread,
Jun 30, 2016, 3:19:17 AM6/30/16
to TurboGears
Allesandro,

Thank you very much for your response.

The solution using WSGI is working fine, but when I try using DirectoryApp:


# -*- coding: utf-8 -*-
from tg.controllers.tgcontroller import TGController
from tg.predicates import not_anonymous
from tg import expose, config
import os, tg

try:
   
from tg.controllers import WSGIAppController
except ImportError:
   
from tg.controllers.wsgiappcontroller import WSGIAppController


from paste.urlparser import StaticURLParser
from  webob.static import DirectoryApp


                                                                       
class PrivateStatics(TGController):                                    
   
@expose()                                                          
   
def lookup(self, *args):
                                         
        site_dir
= os.path.join(config.get('here'), 'myapp/private')
       
# return WSGIAppController(StaticURLParser(site_dir), allow_only=not_anonymous()), args
       
return DirectoryApp(site_dir)(tg.request)
                                                                 
    _lookup
= lookup


I got an error:

ValueError: need more than 1 value to unpack

Traceback (most recent call last)

    File "/home/user/tg2env/lib/python2.7/site-packages/TurboGears2-2.3.8-py2.7.egg/tg/wsgiapp.py", line 120, in __call__

    response = self.wrapped_dispatch(controller, environ, context)

    File "/home/user/tg2env/lib/python2.7/site-packages/TurboGears2-2.3.8-py2.7.egg/tg/appwrappers/errorpage.py", line 56, in __call__

    resp = self.next_handler(controller, environ, context)

    File "/home/user/tg2env/lib/python2.7/site-packages/TurboGears2-2.3.8-py2.7.egg/tg/appwrappers/transaction_manager.py", line 107, in __call__

    reraise(*exc_info)

    File "/home/user/tg2env/lib/python2.7/site-packages/TurboGears2-2.3.8-py2.7.egg/tg/appwrappers/transaction_manager.py", line 83, in __call__

    response = self.next_handler(controller, environ, context)

    File "/home/user/tg2env/lib/python2.7/site-packages/TurboGears2-2.3.8-py2.7.egg/tg/appwrappers/caching.py", line 54, in __call__

    return self.next_handler(controller, environ, context)

    File "/home/user/tg2env/lib/python2.7/site-packages/TurboGears2-2.3.8-py2.7.egg/tg/appwrappers/session.py", line 71, in __call__

    response = self.next_handler(controller, environ, context)

    File "/home/user/tg2env/lib/python2.7/site-packages/TurboGears2-2.3.8-py2.7.egg/tg/appwrappers/identity.py", line 75, in __call__

    return self.next_handler(controller, environ, context)

    File "/home/user/tg2env/lib/python2.7/site-packages/TurboGears2-2.3.8-py2.7.egg/tg/appwrappers/i18n.py", line 71, in __call__

    return self.next_handler(controller, environ, context)

    File "/home/user/tg2env/lib/python2.7/site-packages/TurboGears2-2.3.8-py2.7.egg/tg/wsgiapp.py", line 285, in _dispatch

    return controller(environ, context)

    File "/home/user/tg2env/myapp/myapp/lib/base.py", line 30, in __call__

    return TGController.__call__(self, environ, start_response)

    File "/home/user/tg2env/lib/python2.7/site-packages/TurboGears2-2.3.8-py2.7.egg/tg/controllers/dispatcher.py", line 119, in __call__

    response = self._perform_call(context)

    File "/home/user/tg2env/lib/python2.7/site-packages/TurboGears2-2.3.8-py2.7.egg/tg/controllers/dispatcher.py", line 99, in _perform_call

    state = self._get_dispatchable(context, py_request.quoted_path_info)

    File "/home/user/tg2env/lib/python2.7/site-packages/TurboGears2-2.3.8-py2.7.egg/tg/controllers/dispatcher.py", line 73, in _get_dispatchable

    state = state.resolve()

    File "build/bdist.linux-x86_64/egg/crank/dispatchstate.py", line 178, in resolve

    return self._root_dispatcher._dispatch(self, self._path)

    File "build/bdist.linux-x86_64/egg/crank/objectdispatcher.py", line 178, in _dispatch

    state, current_args)

    File "build/bdist.linux-x86_64/egg/crank/objectdispatcher.py", line 103, in _dispatch_controller

    return dispatcher(state, remainder)

    File "build/bdist.linux-x86_64/egg/crank/objectdispatcher.py", line 181, in _dispatch

    return self._dispatch_first_found_default_or_lookup(state, remainder)

    File "build/bdist.linux-x86_64/egg/crank/objectdispatcher.py", line 129, in _dispatch_first_found_default_or_lookup

    new_controller, new_remainder = meth(*m_remainder)

    ValueError: need more than 1 value to unpack

abc_coder

unread,
Jun 30, 2016, 5:29:04 AM6/30/16
to TurboGears
adding args on the end of line results as 404 error,

return DirectoryApp(site_dir)(tg.request), args


Alessandro Molina

unread,
Jul 5, 2016, 7:54:15 AM7/5/16
to TurboGears
You should use `_default` not `_lookup` in this case as you are not returning a controller anymore, but the response itself.

On Thu, Jun 30, 2016 at 11:29 AM, abc_coder <jasinsk...@gmail.com> wrote:
adding args on the end of line results as 404 error,

return DirectoryApp(site_dir)(tg.request), args


--
You received this message because you are subscribed to the Google Groups "TurboGears" group.
To unsubscribe from this group and stop receiving emails from it, send an email to turbogears+...@googlegroups.com.
To post to this group, send email to turbo...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages