~jcsackett/charmworld/bac-tag-constraints

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# Copyright 2012, 2013 Marco Ceppi, Canonical Ltd.  This software is
# licensed under the GNU Affero General Public License version 3 (see
# the file LICENSE).

from pyramid.authentication import AuthTktAuthenticationPolicy
from pyramid.authorization import ACLAuthorizationPolicy
from pyramid.config import Configurator
from pyramid.security import Allow
from pyramid.security import Everyone
from pyramid.view import view_config
from pyramid_beaker import session_factory_from_settings
import venusian

from charmworld.forms import setup_custom_deform
from charmworld.lib.auth import RequestWithUserAttribute
from charmworld.models import acquire_session_secret
from charmworld.models import getconnection
from charmworld.models import getdb
from charmworld.models import UserMgr
from charmworld.routes import build_routes
from charmworld.globals import default_globals_factory
from charmworld.utils import (
    get_session_url,
    record_server_start_time,
)


class cached_view_config(view_config):
    """ A replacement for the built in view_config to set HTTP_CACHE

    Add a new param
    :param http_cache_modifier: a multiple to use against the current cache
    value.

    Reads the http_cache time from the settings dict and appends that to all
    views.

    This is a copied view_config from the Pyramid version and updated to
    specifically handle the http_cache setting.

    """
    venusian = venusian  # for testing injection

    def __init__(self, **settings):
        # Catch and work in the new http_cache_modifier setting.
        if 'http_cache_modifier' in settings:
            self.http_cache_modifier = settings['http_cache_modifier']
            del settings['http_cache_modifier']
        super(cached_view_config, self).__init__(**settings)

    def __call__(self, wrapped):

        settings = self.__dict__.copy()
        depth = settings.pop('_depth', 0)

        def callback(context, name, ob):
            config = context.config.with_package(info.module)
            app_settings = context.config.registry.settings

            if 'http_cache' not in settings:
                http_cache = app_settings.get('http_cache')
                if http_cache is not None:
                    http_cache = int(http_cache)
                settings['http_cache'] = http_cache
            if 'http_cache_modifier' in settings:
                mod = settings['http_cache_modifier']
                if settings['http_cache'] is not None:
                    settings['http_cache'] = int(settings['http_cache'] * mod)
                # We can't let the new setting to get add_view or it blows up
                # with an unexpected kwarg.
                del settings['http_cache_modifier']

            config.add_view(view=ob, **settings)

        info = self.venusian.attach(wrapped, callback, category='pyramid',
                                    depth=depth + 1)

        if info.scope == 'class':
            # if the decorator was attached to a method in a class, or
            # otherwise executed at class scope, we need to set an
            # 'attr' into the settings if one isn't already in there
            if settings.get('attr') is None:
                settings['attr'] = wrapped.__name__

        settings['_info'] = info.codeinfo  # fbo "action_method"
        return wrapped


class RootFactory(object):
    """This is a simple factory to allow all logged in users all acl access.

    We'll not be needing full acl so we just allow everything for now. We'll
    manually investigate the request.user as required for actual access.

    """
    __acl__ = [
        (Allow, Everyone, 'view'),
        (Allow, 'group charmers', 'edit'),
        (Allow, 'group juju-jitsu', 'edit'),
    ]

    def __init__(self, request):
        pass


def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    # Setup the data store connections based on the ini settings.
    setup_custom_deform()

    # Set the mongodb connection into the settings to cache it for the request
    # factory to use as request.db.
    settings['connection'] = getconnection(settings)

    # Load up the beaker sessions into the same mongodb used for the
    # application.
    settings['session.url'] = get_session_url(settings)
    database = getdb(settings['connection'], settings['mongo.database'])
    authn_policy = AuthTktAuthenticationPolicy(
        acquire_session_secret(database),
        callback=UserMgr.auth_principalfinder,
        hashalg='sha512',
    )

    # Turn the string ini config to a list.
    openid_teams = settings.get('openid_teams', '')
    settings['openid_teams'] = openid_teams.split(',')

    authz_policy = ACLAuthorizationPolicy()
    session_factory = session_factory_from_settings(settings)

    config = Configurator(
        authentication_policy=authn_policy,
        authorization_policy=authz_policy,
        request_factory=RequestWithUserAttribute,
        root_factory='charmworld.RootFactory',
        session_factory=session_factory,
        settings=settings,
    )

    # Template globals
    config.set_renderer_globals_factory(default_globals_factory)

    config.add_static_view('static', 'charmworld:static', cache_max_age=3600)
    config = build_routes(config)
    config.scan("charmworld.views")
    record_server_start_time(database)

    return config.make_wsgi_app()