| commit 268: | 57af73d603e9 |
| parent 267: | 6a689e9a2741 |
| branch: | default |
2 months ago
Changed (Δ3.9 KB):
docs/shabti_templates/shabti_formalchemy.rst (2 lines added, 2 lines removed)
setup.py (1 lines added, 1 lines removed)
shabti/templates/auth/+package+/lib/auth/__init__.py_tmpl (3 lines added, 3 lines removed)
shabti/templates/auth/+package+/lib/decorators.py_tmpl (63 lines added, 0 lines removed)
shabti/templates/auth_couchdb/+package+/lib/auth/__init__.py_tmpl (3 lines added, 3 lines removed)
shabti/templates/auth_rdfalchemy/+package+/lib/auth/__init__.py_tmpl (3 lines added, 3 lines removed)
shabti/templates/default/+package+/lib/fixtures.py_tmpl (2 lines added, 2 lines removed)
shabti/templates/microsite/+package+/config/routing.py_tmpl (46 lines added, 0 lines removed)
shabti/templates/microsite/+package+/lib/fixtures.py_tmpl (2 lines added, 2 lines removed)
tests/test_make_project.py (1 lines added, 2 lines removed)
Up to file-list docs/shabti_templates/shabti_formalchemy.rst:
4 |
4 |
|
5 |
5 |
.. _shabti-formalchemy: |
6 |
6 |
|
7 |
**shabti_formalchemy** -- |
|
7 |
**shabti_formalchemy** -- "Pylons Admin" Web UI |
|
8 |
8 |
=============================================== |
9 |
9 |
|
10 |
10 |
.. note:: This Shabti template was kindly contributed by Gaƫl Pasgrimaud of the Formalchemy development team. |
| … | … | @@ -230,7 +230,7 @@ Creating a new user entity |
230 |
230 |
.. seealso:: Form structure, content and appearance can all be customized. For details on how to customize the forms and the fields, see the docs for the `Formalchemy Pylons extension <http://docs.formalchemy.org/current/ext/pylons.html#customization>`_ |
231 |
231 |
|
232 |
232 |
TODO |
233 |
==== |
|
233 |
---- |
|
234 |
234 |
|
235 |
235 |
1. Adjust the generation of the form so that password fields are presented unpopulated. |
236 |
236 |
| … | … | @@ -24,7 +24,7 @@ Current Status |
24 |
24 |
Shabti %s described on this page is stable. |
25 |
25 |
|
26 |
26 |
There is also an unstable `development version |
27 |
<http://www.bitbucket.org/gjhiggins/shabti/ |
|
27 |
<http://www.bitbucket.org/gjhiggins/shabti/get/tip.tar.gz#egg=Shabti-dev>`_ of Shabti. |
|
28 |
28 |
|
29 |
29 |
Download and Installation |
30 |
30 |
------------------------- |
Up to file-list shabti/templates/auth/+package+/lib/auth/__init__.py_tmpl:
1 |
from pylons import request, session |
|
2 |
from pylons.controllers.util import redirect_to |
|
1 |
from pylons import request, session, url |
|
2 |
from pylons.controllers.util import redirect |
|
3 |
3 |
from {{package}} import model as model |
4 |
4 |
|
5 |
5 |
_login_url = '/login' |
| … | … | @@ -26,7 +26,7 @@ def logout(): |
26 |
26 |
session.delete() |
27 |
27 |
|
28 |
28 |
def redirect_to_login(): |
29 |
redirect |
|
29 |
redirect(url(controller=_login_url)) |
|
30 |
30 |
|
31 |
31 |
|
32 |
32 |
Up to file-list shabti/templates/auth/+package+/lib/decorators.py_tmpl:
| … | … | @@ -18,3 +18,66 @@ def authorize(permission): |
18 |
18 |
redirect_to_login() |
19 |
19 |
return decorator(wrapper) |
20 |
20 |
|
21 |
# Alternatively, use the decorators listed below, taken from |
|
22 |
# Ben Bangert's pastie: |
|
23 |
# http://pylonshq.com/pasties/ad4b1f541220b4099c97d573a6673e41 |
|
24 |
# N.B. Assumed to be implemented: |
|
25 |
# User.in_group(self, group): returns True or False |
|
26 |
# User.computed_permissions(self): returns list_of_computed_permissions |
|
27 |
# |
|
28 |
from {{package}}.model import meta |
|
29 |
from pylons.controllers.util import abort |
|
30 |
||
31 |
def in_group(group): |
|
32 |
"""Requires a user to be logged in, and the group specified""" |
|
33 |
def wrapper(func, *args, **kwargs): |
|
34 |
user = pylons.tmpl_context.user |
|
35 |
if not user: |
|
36 |
log.debug("No user logged in for permission restricted function") |
|
37 |
abort(401, "Not Authorized") |
|
38 |
if user.in_group(group): |
|
39 |
log.debug("User %s verified in group %s", user, group) |
|
40 |
return func(*args, **kwargs) |
|
41 |
else: |
|
42 |
log.debug("User %s not in group %s", user, group) |
|
43 |
abort(401, "Not Authorized") |
|
44 |
return decorator(wrapper) |
|
45 |
||
46 |
def not_in_group(group): |
|
47 |
"""Requires a user to be logged in, and NOT in the group specified""" |
|
48 |
def wrapper(func, *args, **kwargs): |
|
49 |
user = pylons.tmpl_context.user |
|
50 |
if not user: |
|
51 |
log.debug("No user logged in for permission restricted function") |
|
52 |
abort(401, "Not Authorized") |
|
53 |
if not user.in_group(group): |
|
54 |
log.debug("User %s verified in group %s", user, group) |
|
55 |
return func(*args, **kwargs) |
|
56 |
else: |
|
57 |
log.debug("User %s not in group %s", user, group) |
|
58 |
abort(401, "Not Authorized") |
|
59 |
return decorator(wrapper) |
|
60 |
||
61 |
||
62 |
def has_permission(permission): |
|
63 |
"""Requires a user to be logged in, and have the permission""" |
|
64 |
def wrapper(func, *args, **kwargs): |
|
65 |
user = pylons.tmpl_context.user |
|
66 |
if not user: |
|
67 |
log.debug("No user logged in for permission restricted function") |
|
68 |
abort(401, "Not Authorized") |
|
69 |
if permission in user.computed_permissions(): |
|
70 |
log.debug("User %s verified in group %s", user, permission) |
|
71 |
return func(*args, **kwargs) |
|
72 |
else: |
|
73 |
log.debug("User %s does not have permission %s", user, permission) |
|
74 |
abort(401, "Not Authorized") |
|
75 |
return decorator(wrapper) |
|
76 |
||
77 |
@decorator |
|
78 |
def logged_in(func, *args, **kwargs): |
|
79 |
user = pylons.tmpl_context.user |
|
80 |
if not user: |
|
81 |
log.debug("No user logged in for permission restricted function") |
|
82 |
abort(401, "Not Authorized") |
|
83 |
return func(*args, **kwargs) |
Up to file-list shabti/templates/auth_couchdb/+package+/lib/auth/__init__.py_tmpl:
1 |
from pylons import request, session |
|
2 |
from pylons.controllers.util import redirect_to |
|
1 |
from pylons import request, session, url |
|
2 |
from pylons.controllers.util import redirect |
|
3 |
3 |
from {{package}}.model import * |
4 |
4 |
|
5 |
5 |
_login_url = '/login' |
| … | … | @@ -25,5 +25,5 @@ def logout(): |
25 |
25 |
session.delete() |
26 |
26 |
|
27 |
27 |
def redirect_to_login(): |
28 |
redirect |
|
28 |
redirect(url(controller=_login_url)) |
|
29 |
29 |
Up to file-list shabti/templates/auth_rdfalchemy/+package+/lib/auth/__init__.py_tmpl:
1 |
from pylons import request, session |
|
2 |
from pylons.controllers.util import redirect_to |
|
1 |
from pylons import request, session, url |
|
2 |
from pylons.controllers.util import redirect |
|
3 |
3 |
from {{package}}.model.rdfmodel import * |
4 |
4 |
|
5 |
5 |
_login_url = '/login' |
| … | … | @@ -25,5 +25,5 @@ def logout(): |
25 |
25 |
session.delete() |
26 |
26 |
|
27 |
27 |
def redirect_to_login(): |
28 |
redirect |
|
28 |
redirect(url(controller=_login_url)) |
|
29 |
29 |
Up to file-list shabti/templates/default/+package+/lib/fixtures.py_tmpl:
| … | … | @@ -120,7 +120,7 @@ def _dump_data_to_file(model, filename, |
120 |
120 |
def _load_instance_from_dict(model, dict): |
121 |
121 |
if not dict: return |
122 |
122 |
instance = model() |
123 |
fields = model._descriptor. |
|
123 |
fields = model._descriptor.columns.keys() |
|
124 |
124 |
for k, v in dict.iteritems(): |
125 |
125 |
if k in fields: |
126 |
126 |
setattr(instance, k, v) |
| … | … | @@ -131,7 +131,7 @@ def _dump_instance_to_dict(instance): |
131 |
131 |
if hasattr(instance, 'to_json'): |
132 |
132 |
return instance.to_json() |
133 |
133 |
d = {} |
134 |
fields = instance._descriptor. |
|
134 |
fields = instance._descriptor.columns.keys() |
|
135 |
135 |
for field in fields: |
136 |
136 |
d[field] = getattr(instance, field) |
137 |
137 |
return d |
Up to file-list shabti/templates/microsite/+package+/config/routing.py_tmpl:
| … | … | @@ -6,6 +6,52 @@ refer to the routes manual at http://rou |
6 |
6 |
""" |
7 |
7 |
from routes import Mapper |
8 |
8 |
|
9 |
import routes.mapper |
|
10 |
||
11 |
class Mapper(routes.Mapper): |
|
12 |
# |
|
13 |
# Pretty string representation - returns a string formatted like this: |
|
14 |
# |
|
15 |
# Route name Methods Path |
|
16 |
# /error/{action} |
|
17 |
# /error/{action}/{id} |
|
18 |
# home GET / |
|
19 |
# things GET /things |
|
20 |
# create_thing POST /things |
|
21 |
# new_thing GET /things/new |
|
22 |
# thing GET /thing/{id} |
|
23 |
# |
|
24 |
# etc |
|
25 |
# |
|
26 |
# Enter 'print mapper' in the paster shell to use it, or (TBD) run it via a |
|
27 |
# configured paster command. |
|
28 |
# |
|
29 |
def __str__(self): |
|
30 |
def format_methods(r): |
|
31 |
if r.conditions: |
|
32 |
method = r.conditions.get('method', '') |
|
33 |
return method if type(method) is str else ', '.join(method) |
|
34 |
else: |
|
35 |
return '' |
|
36 |
||
37 |
table = [('Route name', 'Methods', 'Path')] + [ |
|
38 |
( |
|
39 |
r.name or '', |
|
40 |
format_methods(r), |
|
41 |
r.routepath or'' |
|
42 |
) |
|
43 |
for r in self.matchlist] |
|
44 |
||
45 |
widths = [ |
|
46 |
max(len(row[col]) for row in table) |
|
47 |
for col in range(len(table[0]))] |
|
48 |
||
49 |
return '\n'.join( |
|
50 |
' '.join( |
|
51 |
row[col].ljust(widths[col]) |
|
52 |
for col in range(len(widths)) |
|
53 |
).rstrip() |
|
54 |
for row in table) |
|
9 |
55 |
# from formalchemy.ext.pylons import maps |
10 |
56 |
# from coastal.controllers.admin import AdminController |
11 |
57 |
Up to file-list shabti/templates/microsite/+package+/lib/fixtures.py_tmpl:
| … | … | @@ -120,7 +120,7 @@ def _dump_data_to_file(model, filename, |
120 |
120 |
def _load_instance_from_dict(model, dict): |
121 |
121 |
if not dict: return |
122 |
122 |
instance = model() |
123 |
fields = model._descriptor. |
|
123 |
fields = model._descriptor.columns.keys() |
|
124 |
124 |
for k, v in dict.iteritems(): |
125 |
125 |
if k in fields: |
126 |
126 |
setattr(instance, k, v) |
| … | … | @@ -131,7 +131,7 @@ def _dump_instance_to_dict(instance): |
131 |
131 |
if hasattr(instance, 'to_json'): |
132 |
132 |
return instance.to_json() |
133 |
133 |
d = {} |
134 |
fields = instance._descriptor. |
|
134 |
fields = instance._descriptor.columns.keys() |
|
135 |
135 |
for field in fields: |
136 |
136 |
d[field] = getattr(instance, field) |
137 |
137 |
return d |
Up to file-list tests/test_make_project.py:
| … | … | @@ -60,7 +60,6 @@ def paster_create(project_name, template |
60 |
60 |
projenv.environ['PYTHONPATH'] = ( |
61 |
61 |
projenv.environ.get('PYTHONPATH', '') + ':' |
62 |
62 |
+ projenv.base_path) |
63 |
||
64 |
63 |
return projenv |
65 |
64 |
|
66 |
65 |
|
| … | … | @@ -92,7 +91,6 @@ def setup_model(): |
92 |
91 |
os.path.join(projenv_files, 'news.json_tmpl') : os.path.join('projectname', 'tests', 'fixtures', 'news', 'newsitems.json' ), |
93 |
92 |
os.path.join(projenv_files, 'test_news.py_tmpl') : os.path.join('projectname', 'tests', 'unit', 'test_news.py'), |
94 |
93 |
os.path.join(projenv_files, 'news.py_tmpl') : os.path.join('projectname', 'model', 'news.py' )}) |
95 |
||
96 |
94 |
res = projenv.run(_get_script_name('paster')+' setup-app development.ini', expect_stderr='expect_error') |
97 |
95 |
|
98 |
96 |
|
| … | … | @@ -202,3 +200,4 @@ def test_project(): |
202 |
200 |
yield (migrate_commit, ) |
203 |
201 |
yield (migrate_upgrade, ) |
204 |
202 |
yield (migrate_downgrade, ) |
203 |
