Revision 98c1bcf7
tburguie: 1ere version fonctionnelle (ou qui ne plante pas...)
git-svn-id: https://vigilo-dev.si.c-s.fr/svn@922 b22e2e97-25c9-44ff-b637-2e5ceca36478
development.ini | ||
---|---|---|
26 | 26 |
cache_dir = %(here)s/data |
27 | 27 |
beaker.session.key = vigigraph |
28 | 28 |
beaker.session.secret = somesecret |
29 |
app.vigicore = / |
|
29 | 30 |
|
30 | 31 |
# If you'd like to fine-tune the individual locations of the cache data dirs |
31 | 32 |
# for the Cache data, or the Session saves, un-comment the desired settings |
setup.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 |
# vim:set expandtab tabstop=4 shiftwidth=4: |
|
2 | 3 |
try: |
3 | 4 |
from setuptools import setup, find_packages |
4 | 5 |
except ImportError: |
... | ... | |
22 | 23 |
"ToscaWidgets >= 0.9.7.1", |
23 | 24 |
"zope.sqlalchemy >= 0.4 ", |
24 | 25 |
"repoze.tm2 >= 1.0a4", |
25 |
|
|
26 | 26 |
"repoze.what-quickstart >= 1.0", |
27 |
], |
|
27 |
"psycopg2", |
|
28 |
"vigilo-models", |
|
29 |
"vigilo-themes-default", |
|
30 |
"PasteScript >= 1.7", # setup_requires has issues |
|
31 |
"PasteDeploy", |
|
32 |
"Paste", |
|
33 |
"decorator != 3.1.0", # Blacklist bad version |
|
34 |
], |
|
28 | 35 |
paster_plugins=['PasteScript', 'Pylons', 'TurboGears2', 'tg.devtools'], |
29 | 36 |
packages=find_packages(exclude=['ez_setup']), |
30 | 37 |
include_package_data=True, |
vigigraph/config/app_cfg.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 |
# vim: set fileencoding=utf-8 sw=4 ts=4 et : |
|
2 | 3 |
""" |
3 | 4 |
Global configuration file for TG2-specific settings in vigigraph. |
4 | 5 |
|
... | ... | |
15 | 16 |
|
16 | 17 |
from tg.configuration import AppConfig |
17 | 18 |
|
19 |
class MyAppConfig(AppConfig): |
|
20 |
"""We overload AppConfig for our needs.""" |
|
21 |
|
|
22 |
def __init__(self, app_name): |
|
23 |
super(MyAppConfig, self).__init__() |
|
24 |
self.__app_name = app_name |
|
25 |
self.__tpl_translator = None |
|
26 |
|
|
27 |
def __setup_template_translator(self): |
|
28 |
from pkg_resources import resource_filename |
|
29 |
import gettext |
|
30 |
from tg.i18n import get_lang |
|
31 |
|
|
32 |
if self.__tpl_translator is None: |
|
33 |
i18n_dir = resource_filename('vigilo.themes', 'i18n') |
|
34 |
lang = get_lang() |
|
35 |
|
|
36 |
# During unit tests, no language is defined |
|
37 |
# which results in an error if gettext.translation |
|
38 |
# is used to retrieve translations. |
|
39 |
if lang is None: |
|
40 |
self.__tpl_translator = gettext.NullTranslations() |
|
41 |
else: |
|
42 |
self.__tpl_translator = gettext.translation( |
|
43 |
'theme', i18n_dir, get_lang()) |
|
44 |
|
|
45 |
def setup_paths(self): |
|
46 |
"""Add egg-aware search path to genshi.""" |
|
47 |
super(MyAppConfig, self).setup_paths() |
|
48 |
from pkg_resources import resource_filename |
|
49 |
|
|
50 |
app_templates = resource_filename( |
|
51 |
'vigilo.themes.templates', self.__app_name) |
|
52 |
common_templates = resource_filename( |
|
53 |
'vigilo.themes.templates', 'common') |
|
54 |
self.paths['templates'] = [app_templates, common_templates] |
|
55 |
|
|
56 |
def setup_genshi_renderer(self): |
|
57 |
"""Setup templates to use an alternate translator.""" |
|
58 |
# On reprend plusieurs éléments de "tg.configuration". |
|
59 |
from genshi.template import TemplateLoader |
|
60 |
from genshi.filters import Translator |
|
61 |
from tg.render import render_genshi |
|
62 |
from pkg_resources import resource_filename |
|
63 |
from tg.configuration import config |
|
64 |
|
|
65 |
def template_loaded(template): |
|
66 |
"""Called when a template is done loading.""" |
|
67 |
self.__setup_template_translator() |
|
68 |
template.filters.insert(0, Translator(self.__tpl_translator.ugettext)) |
|
69 |
|
|
70 |
def my_render_genshi(template_name, template_vars, **kwargs): |
|
71 |
self.__setup_template_translator() |
|
72 |
template_vars['l_'] = self.__tpl_translator.ugettext |
|
73 |
return render_genshi(template_name, template_vars, **kwargs) |
|
74 |
|
|
75 |
loader = TemplateLoader(search_path=self.paths.templates, |
|
76 |
auto_reload=self.auto_reload_templates, |
|
77 |
callback=template_loaded) |
|
78 |
|
|
79 |
config['pylons.app_globals'].genshi_loader = loader |
|
80 |
self.render_functions.genshi = my_render_genshi |
|
81 |
|
|
82 |
def setup_sqlalchemy(self): |
|
83 |
""" |
|
84 |
TG2 needs to configure the DB session before anything else, then it |
|
85 |
calls init_model(). In our case, the DB session is already configured |
|
86 |
so the function call is unnecessary. We suppress TG2's behaviour here. |
|
87 |
""" |
|
88 |
pass |
|
89 |
|
|
18 | 90 |
import vigigraph |
19 | 91 |
from vigigraph import model |
20 |
from vigigraph.lib import app_globals, helpers
|
|
92 |
from vigigraph.lib import app_globals, helpers |
|
21 | 93 |
|
22 |
base_config = AppConfig()
|
|
94 |
base_config = MyAppConfig('vigigraph')
|
|
23 | 95 |
base_config.renderers = [] |
24 | 96 |
|
97 |
# Pour gérer les thèmes, la notation "pointée" n'est pas utilisée. |
|
98 |
# À la place, on indique le nom complet du template (ex: "index.html") |
|
99 |
# lors de l'appel au décorateur @expose. |
|
100 |
base_config.use_dotted_templatenames = False |
|
101 |
|
|
102 |
# On définit la variable à False. En réalité, le comportement |
|
103 |
# est le même que si elle valait toujours True, sauf que l'on |
|
104 |
# met en place les middlewares nous même pour pouvoir gérer les |
|
105 |
# thèmes (cf. ./middleware.py). |
|
106 |
base_config.serve_static = False |
|
107 |
|
|
25 | 108 |
base_config.package = vigigraph |
26 | 109 |
|
27 | 110 |
#Set the default renderer |
... | ... | |
34 | 117 |
|
35 | 118 |
#Configure the base SQLALchemy Setup |
36 | 119 |
base_config.use_sqlalchemy = True |
37 |
base_config.model = vigigraph.model
|
|
38 |
base_config.DBSession = vigigraph.model.DBSession
|
|
120 |
base_config.model = model |
|
121 |
base_config.DBSession = model.DBSession |
|
39 | 122 |
|
40 | 123 |
# Configure the authentication backend |
41 | 124 |
base_config.auth_backend = 'sqlalchemy' |
... | ... | |
43 | 126 |
# what is the class you want to use to search for users in the database |
44 | 127 |
base_config.sa_auth.user_class = model.User |
45 | 128 |
# what is the class you want to use to search for groups in the database |
46 |
base_config.sa_auth.group_class = model.Group |
|
129 |
base_config.sa_auth.group_class = model.UserGroup
|
|
47 | 130 |
# what is the class you want to use to search for permissions in the database |
48 | 131 |
base_config.sa_auth.permission_class = model.Permission |
132 |
# The name "groups" is already used for groups of hosts. |
|
133 |
# We use "usergroups" when referering to users to avoid confusion. |
|
134 |
base_config.sa_auth.translations.groups = 'usergroups' |
|
49 | 135 |
|
50 | 136 |
# override this if you would like to provide a different who plugin for |
51 | 137 |
# managing login and logout of your application |
... | ... | |
58 | 144 |
# You may optionally define a page where you want users to be redirected to |
59 | 145 |
# on logout: |
60 | 146 |
base_config.sa_auth.post_logout_url = '/post_logout' |
147 |
|
|
148 |
|
|
149 |
################################## |
|
150 |
# Settings specific to Vigigraph # |
|
151 |
################################## |
|
152 |
|
|
153 |
# Vigigraph version |
|
154 |
base_config['vigigraph_version'] = u'0.1' |
|
155 |
|
vigigraph/config/middleware.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 |
# vim: set fileencoding=utf-8 sw=4 ts=4 et : |
|
2 | 3 |
"""WSGI middleware initialization for the vigigraph application.""" |
3 | 4 |
|
4 | 5 |
from vigigraph.config.app_cfg import base_config |
5 | 6 |
from vigigraph.config.environment import load_environment |
6 | 7 |
|
8 |
from pkg_resources import resource_filename |
|
9 |
from paste.cascade import Cascade |
|
10 |
from paste.urlparser import StaticURLParser |
|
7 | 11 |
|
8 | 12 |
__all__ = ['make_app'] |
9 | 13 |
|
... | ... | |
16 | 20 |
""" |
17 | 21 |
Set vigigraph up with the settings found in the PasteDeploy configuration |
18 | 22 |
file used. |
19 |
|
|
20 |
:param global_conf: The global settings for vigigraph (those |
|
21 |
defined under the ``[DEFAULT]`` section). |
|
22 |
:type global_conf: dict |
|
23 |
:param full_stack: Should the whole TG2 stack be set up? |
|
24 |
:type full_stack: str or bool |
|
25 |
:return: The vigigraph application with all the relevant middleware |
|
26 |
loaded. |
|
27 |
|
|
23 |
|
|
28 | 24 |
This is the PasteDeploy factory for the vigigraph application. |
29 | 25 |
|
30 |
``app_conf`` contains all the application-specific settings (those defined
|
|
31 |
under ``[app:main]``. |
|
26 |
C{app_conf} contains all the application-specific settings (those defined
|
|
27 |
under ``[app:main]``).
|
|
32 | 28 |
|
33 |
|
|
29 |
@param global_conf: The global settings for vigigraph (those |
|
30 |
defined under the ``[DEFAULT]`` section). |
|
31 |
@type global_conf: C{dict} |
|
32 |
@param full_stack: Should the whole TG2 stack be set up? |
|
33 |
@type full_stack: C{str} or C{bool} |
|
34 |
@return: The vigigraph application with all the relevant middleware |
|
35 |
loaded. |
|
34 | 36 |
""" |
35 |
app = make_base_app(global_conf, full_stack=True, **app_conf) |
|
36 |
|
|
37 |
# Wrap your base TurboGears 2 application with custom middleware here |
|
37 |
app = make_base_app(global_conf, full_stack=full_stack, **app_conf) |
|
38 | 38 |
|
39 |
# On définit 2 middlewares pour fichiers statiques qui cherchent |
|
40 |
# les fichiers dans le thème actuellement chargé. |
|
41 |
# Le premier va les chercher dans le dossier des fichiers spécifiques |
|
42 |
# à l'application, le second cherche dans les fichiers communs. |
|
43 |
app_static = StaticURLParser(resource_filename( |
|
44 |
'vigilo.themes.public', 'vigigraph')) |
|
45 |
common_static = StaticURLParser(resource_filename( |
|
46 |
'vigilo.themes.public', 'common')) |
|
47 |
app = Cascade([app_static, common_static, app]) |
|
48 |
|
|
39 | 49 |
return app |
50 |
|
vigigraph/controllers/error.py | ||
---|---|---|
18 | 18 |
|
19 | 19 |
""" |
20 | 20 |
|
21 |
@expose('vigigraph.templates.error')
|
|
21 |
@expose('error.html')
|
|
22 | 22 |
def document(self, *args, **kwargs): |
23 | 23 |
"""Render the error document""" |
24 | 24 |
resp = request.environ.get('pylons.original_response') |
vigigraph/controllers/root.py | ||
---|---|---|
3 | 3 |
|
4 | 4 |
from tg import expose, flash, require, url, request, redirect |
5 | 5 |
from pylons.i18n import ugettext as _, lazy_ugettext as l_ |
6 |
from catwalk.tg2 import Catwalk |
|
6 |
#from catwalk.tg2 import Catwalk
|
|
7 | 7 |
from repoze.what import predicates |
8 | 8 |
|
9 | 9 |
from vigigraph.lib.base import BaseController |
10 | 10 |
from vigigraph.model import DBSession, metadata |
11 | 11 |
from vigigraph.controllers.error import ErrorController |
12 | 12 |
from vigigraph import model |
13 |
from vigigraph.controllers.secure import SecureController |
|
13 |
#from vigigraph.controllers.secure import SecureController
|
|
14 | 14 |
|
15 | 15 |
__all__ = ['RootController'] |
16 | 16 |
|
... | ... | |
29 | 29 |
must be wrapped around with :class:`tg.controllers.WSGIAppController`. |
30 | 30 |
|
31 | 31 |
""" |
32 |
secc = SecureController() |
|
32 |
#secc = SecureController()
|
|
33 | 33 |
|
34 |
admin = Catwalk(model, DBSession) |
|
34 |
#admin = Catwalk(model, DBSession)
|
|
35 | 35 |
|
36 | 36 |
error = ErrorController() |
37 | 37 |
|
38 |
@expose('vigigraph.templates.index')
|
|
38 |
@expose('index.html')
|
|
39 | 39 |
def index(self): |
40 | 40 |
"""Handle the front-page.""" |
41 | 41 |
return dict(page='index') |
42 | 42 |
|
43 |
@expose('vigigraph.templates.about') |
|
44 |
def about(self): |
|
45 |
"""Handle the 'about' page.""" |
|
46 |
return dict(page='about') |
|
43 |
#@expose('vigigraph.templates.about')
|
|
44 |
#def about(self):
|
|
45 |
# """Handle the 'about' page."""
|
|
46 |
# return dict(page='about')
|
|
47 | 47 |
|
48 |
@expose('vigigraph.templates.authentication') |
|
49 |
def auth(self): |
|
50 |
"""Display some information about auth* on this application.""" |
|
51 |
return dict(page='auth') |
|
48 |
#@expose('vigigraph.templates.authentication')
|
|
49 |
#def auth(self):
|
|
50 |
# """Display some information about auth* on this application."""
|
|
51 |
# return dict(page='auth')
|
|
52 | 52 |
|
53 |
@expose('vigigraph.templates.index') |
|
54 |
@require(predicates.has_permission('manage', msg=l_('Only for managers'))) |
|
55 |
def manage_permission_only(self, **kw): |
|
56 |
"""Illustrate how a page for managers only works.""" |
|
57 |
return dict(page='managers stuff') |
|
53 |
#@expose('vigigraph.templates.index')
|
|
54 |
#@require(predicates.has_permission('manage', msg=l_('Only for managers')))
|
|
55 |
#def manage_permission_only(self, **kw):
|
|
56 |
# """Illustrate how a page for managers only works."""
|
|
57 |
# return dict(page='managers stuff')
|
|
58 | 58 |
|
59 |
@expose('vigigraph.templates.index') |
|
60 |
@require(predicates.is_user('editor', msg=l_('Only for the editor'))) |
|
61 |
def editor_user_only(self, **kw): |
|
62 |
"""Illustrate how a page exclusive for the editor works.""" |
|
63 |
return dict(page='editor stuff') |
|
59 |
#@expose('vigigraph.templates.index')
|
|
60 |
#@require(predicates.is_user('editor', msg=l_('Only for the editor')))
|
|
61 |
#def editor_user_only(self, **kw):
|
|
62 |
# """Illustrate how a page exclusive for the editor works."""
|
|
63 |
# return dict(page='editor stuff')
|
|
64 | 64 |
|
65 |
@expose('vigigraph.templates.login')
|
|
65 |
@expose('login.html')
|
|
66 | 66 |
def login(self, came_from=url('/')): |
67 | 67 |
"""Start the user login.""" |
68 | 68 |
login_counter = request.environ['repoze.who.logins'] |
vigigraph/controllers/secure.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
"""Sample controller with all its actions protected.""" |
|
3 |
from tg import expose, flash |
|
4 |
from pylons.i18n import ugettext as _, lazy_ugettext as l_ |
|
5 |
from repoze.what.predicates import has_permission |
|
6 |
#from dbsprockets.dbmechanic.frameworks.tg2 import DBMechanic |
|
7 |
#from dbsprockets.saprovider import SAProvider |
|
8 |
|
|
9 |
from vigigraph.lib.base import BaseController |
|
10 |
#from vigigraph.model import DBSession, metadata |
|
11 |
|
|
12 |
__all__ = ['SecureController'] |
|
13 |
|
|
14 |
|
|
15 |
class SecureController(BaseController): |
|
16 |
"""Sample controller-wide authorization""" |
|
17 |
|
|
18 |
# The predicate that must be met for all the actions in this controller: |
|
19 |
allow_only = has_permission('manage', |
|
20 |
msg=l_('Only for people with the "manage" permission')) |
|
21 |
|
|
22 |
@expose('vigigraph.templates.index') |
|
23 |
def index(self): |
|
24 |
"""Let the user know that's visiting a protected controller.""" |
|
25 |
flash(_("Secure Controller here")) |
|
26 |
return dict(page='index') |
|
27 |
|
|
28 |
@expose('vigigraph.templates.index') |
|
29 |
def some_where(self): |
|
30 |
"""Let the user know that this action is protected too.""" |
|
31 |
return dict(page='some_where') |
vigigraph/model/__init__.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 | 2 |
"""The application's model objects""" |
3 | 3 |
|
4 |
from zope.sqlalchemy import ZopeTransactionExtension |
|
5 |
from sqlalchemy.orm import scoped_session, sessionmaker |
|
6 |
#from sqlalchemy import MetaData |
|
7 |
from sqlalchemy.ext.declarative import declarative_base |
|
4 |
from vigilo.models.session import DBSession |
|
5 |
from vigilo.models.vigilo_bdd_config import metadata |
|
8 | 6 |
|
9 |
# Global session manager: DBSession() returns the Thread-local |
|
10 |
# session object appropriate for the current web request. |
|
11 |
maker = sessionmaker(autoflush=True, autocommit=False, |
|
12 |
extension=ZopeTransactionExtension()) |
|
13 |
DBSession = scoped_session(maker) |
|
7 |
metadata.bind = DBSession.bind |
|
14 | 8 |
|
15 |
# Base class for all of our model classes: By default, the data model is |
|
16 |
# defined with SQLAlchemy's declarative extension, but if you need more |
|
17 |
# control, you can switch to the traditional method. |
|
18 |
DeclarativeBase = declarative_base() |
|
19 |
|
|
20 |
# There are two convenient ways for you to spare some typing. |
|
21 |
# You can have a query property on all your model classes by doing this: |
|
22 |
# DeclarativeBase.query = DBSession.query_property() |
|
23 |
# Or you can use a session-aware mapper as it was used in TurboGears 1: |
|
24 |
# DeclarativeBase = declarative_base(mapper=DBSession.mapper) |
|
25 |
|
|
26 |
# Global metadata. |
|
27 |
# The default metadata is the one from the declarative base. |
|
28 |
metadata = DeclarativeBase.metadata |
|
29 |
|
|
30 |
# If you have multiple databases with overlapping table names, you'll need a |
|
31 |
# metadata for each database. Feel free to rename 'metadata2'. |
|
32 |
#metadata2 = MetaData() |
|
33 | 9 |
|
34 | 10 |
##### |
35 | 11 |
# Generally you will not want to define your table's mappers, and data objects |
... | ... | |
38 | 14 |
# |
39 | 15 |
###### |
40 | 16 |
|
41 |
def init_model(engine): |
|
42 |
"""Call me before using any of the tables or classes in the model.""" |
|
43 |
|
|
44 |
DBSession.configure(bind=engine) |
|
45 |
# If you are using reflection to introspect your database and create |
|
46 |
# table objects for you, your tables must be defined and mapped inside |
|
47 |
# the init_model function, so that the engine is available if you |
|
48 |
# use the model outside tg2, you need to make sure this is called before |
|
49 |
# you use the model. |
|
50 |
|
|
51 |
# |
|
52 |
# See the following example: |
|
53 |
|
|
54 |
#global t_reflected |
|
55 |
|
|
56 |
#t_reflected = Table("Reflected", metadata, |
|
57 |
# autoload=True, autoload_with=engine) |
|
58 |
|
|
59 |
#mapper(Reflected, t_reflected) |
|
17 |
from vigilo.models import User, UserGroup, Permission |
|
18 |
from vigilo.models import Host, HostGroup |
|
19 |
from vigilo.models import Service, ServiceGroup |
|
20 |
from vigilo.models import Group |
|
21 |
from vigilo.models import Tag, CustomGraphView, BoardViewFilter |
|
22 |
from vigilo.models import Graph |
|
60 | 23 |
|
61 |
# Import your model modules here. |
|
62 |
from vigigraph.model.auth import User, Group, Permission |
vigigraph/model/auth.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
""" |
|
3 |
Auth* related model. |
|
4 |
|
|
5 |
This is where the models used by :mod:`repoze.who` and :mod:`repoze.what` are |
|
6 |
defined. |
|
7 |
|
|
8 |
It's perfectly fine to re-use this definition in the vigigraph application, |
|
9 |
though. |
|
10 |
|
|
11 |
""" |
|
12 |
import os |
|
13 |
from datetime import datetime |
|
14 |
import sys |
|
15 |
try: |
|
16 |
from hashlib import sha1 |
|
17 |
except ImportError: |
|
18 |
sys.exit('ImportError: No module named hashlib\n' |
|
19 |
'If you are on python2.4 this library is not part of python. ' |
|
20 |
'Please install it. Example: easy_install hashlib') |
|
21 |
|
|
22 |
from sqlalchemy import Table, ForeignKey, Column |
|
23 |
from sqlalchemy.types import Unicode, Integer, DateTime |
|
24 |
from sqlalchemy.orm import relation, synonym |
|
25 |
|
|
26 |
from vigigraph.model import DeclarativeBase, metadata, DBSession |
|
27 |
|
|
28 |
__all__ = ['User', 'Group', 'Permission'] |
|
29 |
|
|
30 |
|
|
31 |
#{ Association tables |
|
32 |
|
|
33 |
|
|
34 |
# This is the association table for the many-to-many relationship between |
|
35 |
# groups and permissions. This is required by repoze.what. |
|
36 |
group_permission_table = Table('tg_group_permission', metadata, |
|
37 |
Column('group_id', Integer, ForeignKey('tg_group.group_id', |
|
38 |
onupdate="CASCADE", ondelete="CASCADE")), |
|
39 |
Column('permission_id', Integer, ForeignKey('tg_permission.permission_id', |
|
40 |
onupdate="CASCADE", ondelete="CASCADE")) |
|
41 |
) |
|
42 |
|
|
43 |
# This is the association table for the many-to-many relationship between |
|
44 |
# groups and members - this is, the memberships. It's required by repoze.what. |
|
45 |
user_group_table = Table('tg_user_group', metadata, |
|
46 |
Column('user_id', Integer, ForeignKey('tg_user.user_id', |
|
47 |
onupdate="CASCADE", ondelete="CASCADE")), |
|
48 |
Column('group_id', Integer, ForeignKey('tg_group.group_id', |
|
49 |
onupdate="CASCADE", ondelete="CASCADE")) |
|
50 |
) |
|
51 |
|
|
52 |
|
|
53 |
#{ The auth* model itself |
|
54 |
|
|
55 |
|
|
56 |
class Group(DeclarativeBase): |
|
57 |
""" |
|
58 |
Group definition for :mod:`repoze.what`. |
|
59 |
|
|
60 |
Only the ``group_name`` column is required by :mod:`repoze.what`. |
|
61 |
|
|
62 |
""" |
|
63 |
|
|
64 |
__tablename__ = 'tg_group' |
|
65 |
|
|
66 |
#{ Columns |
|
67 |
|
|
68 |
group_id = Column(Integer, autoincrement=True, primary_key=True) |
|
69 |
|
|
70 |
group_name = Column(Unicode(16), unique=True, nullable=False) |
|
71 |
|
|
72 |
display_name = Column(Unicode(255)) |
|
73 |
|
|
74 |
created = Column(DateTime, default=datetime.now) |
|
75 |
|
|
76 |
#{ Relations |
|
77 |
|
|
78 |
users = relation('User', secondary=user_group_table, backref='groups') |
|
79 |
|
|
80 |
#{ Special methods |
|
81 |
|
|
82 |
def __repr__(self): |
|
83 |
return '<Group: name=%s>' % self.group_name |
|
84 |
|
|
85 |
def __unicode__(self): |
|
86 |
return self.group_name |
|
87 |
|
|
88 |
#} |
|
89 |
|
|
90 |
|
|
91 |
# The 'info' argument we're passing to the email_address and password columns |
|
92 |
# contain metadata that Rum (http://python-rum.org/) can use generate an |
|
93 |
# admin interface for your models. |
|
94 |
class User(DeclarativeBase): |
|
95 |
""" |
|
96 |
User definition. |
|
97 |
|
|
98 |
This is the user definition used by :mod:`repoze.who`, which requires at |
|
99 |
least the ``user_name`` column. |
|
100 |
|
|
101 |
""" |
|
102 |
__tablename__ = 'tg_user' |
|
103 |
|
|
104 |
#{ Columns |
|
105 |
|
|
106 |
user_id = Column(Integer, autoincrement=True, primary_key=True) |
|
107 |
|
|
108 |
user_name = Column(Unicode(16), unique=True, nullable=False) |
|
109 |
|
|
110 |
email_address = Column(Unicode(255), unique=True, nullable=False, |
|
111 |
info={'rum': {'field':'Email'}}) |
|
112 |
|
|
113 |
display_name = Column(Unicode(255)) |
|
114 |
|
|
115 |
_password = Column('password', Unicode(80), |
|
116 |
info={'rum': {'field':'Password'}}) |
|
117 |
|
|
118 |
created = Column(DateTime, default=datetime.now) |
|
119 |
|
|
120 |
#{ Special methods |
|
121 |
|
|
122 |
def __repr__(self): |
|
123 |
return '<User: email="%s", display name="%s">' % ( |
|
124 |
self.email_address, self.display_name) |
|
125 |
|
|
126 |
def __unicode__(self): |
|
127 |
return self.display_name or self.user_name |
|
128 |
|
|
129 |
#{ Getters and setters |
|
130 |
|
|
131 |
@property |
|
132 |
def permissions(self): |
|
133 |
"""Return a set of strings for the permissions granted.""" |
|
134 |
perms = set() |
|
135 |
for g in self.groups: |
|
136 |
perms = perms | set(g.permissions) |
|
137 |
return perms |
|
138 |
|
|
139 |
@classmethod |
|
140 |
def by_email_address(cls, email): |
|
141 |
"""Return the user object whose email address is ``email``.""" |
|
142 |
return DBSession.query(cls).filter(cls.email_address==email).first() |
|
143 |
|
|
144 |
@classmethod |
|
145 |
def by_user_name(cls, username): |
|
146 |
"""Return the user object whose user name is ``username``.""" |
|
147 |
return DBSession.query(cls).filter(cls.user_name==username).first() |
|
148 |
|
|
149 |
def _set_password(self, password): |
|
150 |
"""Hash ``password`` on the fly and store its hashed version.""" |
|
151 |
hashed_password = password |
|
152 |
|
|
153 |
if isinstance(password, unicode): |
|
154 |
password_8bit = password.encode('UTF-8') |
|
155 |
else: |
|
156 |
password_8bit = password |
|
157 |
|
|
158 |
salt = sha1() |
|
159 |
salt.update(os.urandom(60)) |
|
160 |
hash = sha1() |
|
161 |
hash.update(password_8bit + salt.hexdigest()) |
|
162 |
hashed_password = salt.hexdigest() + hash.hexdigest() |
|
163 |
|
|
164 |
# Make sure the hashed password is an UTF-8 object at the end of the |
|
165 |
# process because SQLAlchemy _wants_ a unicode object for Unicode |
|
166 |
# columns |
|
167 |
if not isinstance(hashed_password, unicode): |
|
168 |
hashed_password = hashed_password.decode('UTF-8') |
|
169 |
|
|
170 |
self._password = hashed_password |
|
171 |
|
|
172 |
def _get_password(self): |
|
173 |
"""Return the hashed version of the password.""" |
|
174 |
return self._password |
|
175 |
|
|
176 |
password = synonym('_password', descriptor=property(_get_password, |
|
177 |
_set_password)) |
|
178 |
|
|
179 |
#} |
|
180 |
|
|
181 |
def validate_password(self, password): |
|
182 |
""" |
|
183 |
Check the password against existing credentials. |
|
184 |
|
|
185 |
:param password: the password that was provided by the user to |
|
186 |
try and authenticate. This is the clear text version that we will |
|
187 |
need to match against the hashed one in the database. |
|
188 |
:type password: unicode object. |
|
189 |
:return: Whether the password is valid. |
|
190 |
:rtype: bool |
|
191 |
|
|
192 |
""" |
|
193 |
hashed_pass = sha1() |
|
194 |
hashed_pass.update(password + self.password[:40]) |
|
195 |
return self.password[40:] == hashed_pass.hexdigest() |
|
196 |
|
|
197 |
|
|
198 |
class Permission(DeclarativeBase): |
|
199 |
""" |
|
200 |
Permission definition for :mod:`repoze.what`. |
|
201 |
|
|
202 |
Only the ``permission_name`` column is required by :mod:`repoze.what`. |
|
203 |
|
|
204 |
""" |
|
205 |
|
|
206 |
__tablename__ = 'tg_permission' |
|
207 |
|
|
208 |
#{ Columns |
|
209 |
|
|
210 |
permission_id = Column(Integer, autoincrement=True, primary_key=True) |
|
211 |
|
|
212 |
permission_name = Column(Unicode(16), unique=True, nullable=False) |
|
213 |
|
|
214 |
description = Column(Unicode(255)) |
|
215 |
|
|
216 |
#{ Relations |
|
217 |
|
|
218 |
groups = relation(Group, secondary=group_permission_table, |
|
219 |
backref='permissions') |
|
220 |
|
|
221 |
#{ Special methods |
|
222 |
|
|
223 |
def __repr__(self): |
|
224 |
return '<Permission: name=%s>' % self.permission_name |
|
225 |
|
|
226 |
def __unicode__(self): |
|
227 |
return self.permission_name |
|
228 |
|
|
229 |
#} |
|
230 |
|
|
231 |
|
|
232 |
#} |
vigigraph/websetup.py | ||
---|---|---|
13 | 13 |
log = logging.getLogger(__name__) |
14 | 14 |
|
15 | 15 |
|
16 |
def setup_app(command, conf, vars): |
|
16 |
def setup_app(command, conf, variables):
|
|
17 | 17 |
"""Place any commands to setup vigigraph here""" |
18 | 18 |
load_environment(conf.global_conf, conf.local_conf) |
19 |
|
|
19 | 20 |
# Load the models |
20 | 21 |
from vigigraph import model |
22 |
from vigilo.models import Version |
|
23 |
|
|
24 |
# Create tables |
|
21 | 25 |
print "Creating tables" |
22 |
model.metadata.create_all(bind=config['pylons.app_globals'].sa_engine)
|
|
26 |
model.metadata.create_all() |
|
23 | 27 |
|
28 |
# Create the default user for TG, must be changed |
|
29 |
# for real tests and production |
|
24 | 30 |
manager = model.User() |
25 | 31 |
manager.user_name = u'manager' |
26 |
manager.display_name = u'Example manager' |
|
27 |
manager.email_address = u'manager@somedomain.com' |
|
28 |
manager.password = u'managepass' |
|
29 |
|
|
32 |
manager.email = u'manager@somedomain.com' |
|
30 | 33 |
model.DBSession.add(manager) |
31 | 34 |
|
32 |
group = model.Group() |
|
35 |
group = model.UserGroup()
|
|
33 | 36 |
group.group_name = u'managers' |
34 |
group.display_name = u'Managers Group' |
|
35 |
|
|
36 | 37 |
group.users.append(manager) |
37 |
|
|
38 | 38 |
model.DBSession.add(group) |
39 | 39 |
|
40 | 40 |
permission = model.Permission() |
41 | 41 |
permission.permission_name = u'manage' |
42 |
permission.description = u'This permission give an administrative right to the bearer' |
|
43 |
permission.groups.append(group) |
|
44 |
|
|
42 |
permission.usergroups.append(group) |
|
45 | 43 |
model.DBSession.add(permission) |
46 | 44 |
|
47 | 45 |
editor = model.User() |
48 | 46 |
editor.user_name = u'editor' |
49 |
editor.display_name = u'Example editor' |
|
50 |
editor.email_address = u'editor@somedomain.com' |
|
51 |
editor.password = u'editpass' |
|
52 |
|
|
47 |
editor.email = u'editor@somedomain.com' |
|
53 | 48 |
model.DBSession.add(editor) |
54 |
model.DBSession.flush() |
|
55 | 49 |
|
50 |
group = model.UserGroup() |
|
51 |
group.group_name = u'editors' |
|
52 |
group.users.append(editor) |
|
53 |
model.DBSession.add(group) |
|
54 |
|
|
55 |
permission = model.Permission() |
|
56 |
permission.permission_name = u'edit' |
|
57 |
permission.usergroups.append(group) |
|
58 |
model.DBSession.add(permission) |
|
59 |
|
|
60 |
version = Version() |
|
61 |
version.name = u'vigigraph' |
|
62 |
version.version = config['vigigraph_version'] |
|
63 |
model.DBSession.add(version) |
|
64 |
|
|
65 |
model.DBSession.flush() |
|
56 | 66 |
transaction.commit() |
57 | 67 |
print "Successfully setup" |
Also available in: Unified diff