commit 3e95b9a9d6dc591feed925412f525a85d6199743 Author: Roven Gabriel Date: Sat Sep 29 15:38:19 2012 +0200 initial commit : Brie avec lecture LDAP diff --git a/.hgignore b/.hgignore new file mode 100644 index 0000000..1ed8a40 --- /dev/null +++ b/.hgignore @@ -0,0 +1,6 @@ +syntax: glob + +Brie/data/sessions/* +*.pyc +*.swp +*.swo diff --git a/Brie/Brie.egg-info/PKG-INFO b/Brie/Brie.egg-info/PKG-INFO new file mode 100644 index 0000000..829e9c0 --- /dev/null +++ b/Brie/Brie.egg-info/PKG-INFO @@ -0,0 +1,10 @@ +Metadata-Version: 1.0 +Name: Brie +Version: 0.1dev +Summary: UNKNOWN +Home-page: UNKNOWN +Author: UNKNOWN +Author-email: UNKNOWN +License: UNKNOWN +Description: UNKNOWN +Platform: UNKNOWN diff --git a/Brie/Brie.egg-info/SOURCES.txt b/Brie/Brie.egg-info/SOURCES.txt new file mode 100644 index 0000000..b893d4e --- /dev/null +++ b/Brie/Brie.egg-info/SOURCES.txt @@ -0,0 +1,68 @@ +MANIFEST.in +README.txt +setup.cfg +setup.py +Brie.egg-info/PKG-INFO +Brie.egg-info/SOURCES.txt +Brie.egg-info/dependency_links.txt +Brie.egg-info/entry_points.txt +Brie.egg-info/paster_plugins.txt +Brie.egg-info/requires.txt +Brie.egg-info/top_level.txt +brie/__init__.py +brie/websetup.py +brie/config/__init__.py +brie/config/app_cfg.py +brie/config/environment.py +brie/config/middleware.py +brie/controllers/__init__.py +brie/controllers/error.py +brie/controllers/root.py +brie/controllers/secure.py +brie/controllers/template.py +brie/i18n/ru/LC_MESSAGES/brie.po +brie/lib/__init__.py +brie/lib/app_globals.py +brie/lib/base.py +brie/lib/helpers.py +brie/model/__init__.py +brie/model/auth.py +brie/public/favicon.ico +brie/public/css/style.css +brie/public/images/contentbg.png +brie/public/images/error.png +brie/public/images/header_inner2.png +brie/public/images/headerbg.png +brie/public/images/info.png +brie/public/images/inputbg.png +brie/public/images/loginbg.png +brie/public/images/loginbottombg.png +brie/public/images/loginheader-left.png +brie/public/images/loginheader-right.png +brie/public/images/menu-item-actibg-first.png +brie/public/images/menu-item-actibg.png +brie/public/images/menu-item-border.png +brie/public/images/menubg.png +brie/public/images/ok.png +brie/public/images/pagebg.png +brie/public/images/star.png +brie/public/images/strype2.png +brie/public/images/under_the_hood_blue.png +brie/public/images/warning.png +brie/templates/__init__.py +brie/templates/about.html +brie/templates/authentication.html +brie/templates/debug.html +brie/templates/error.html +brie/templates/footer.html +brie/templates/header.html +brie/templates/index.html +brie/templates/login.html +brie/templates/master.html +brie/templates/sidebars.html +brie/tests/__init__.py +brie/tests/functional/__init__.py +brie/tests/functional/test_authentication.py +brie/tests/functional/test_root.py +brie/tests/models/__init__.py +brie/tests/models/test_auth.py \ No newline at end of file diff --git a/Brie/Brie.egg-info/dependency_links.txt b/Brie/Brie.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/Brie/Brie.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/Brie/Brie.egg-info/entry_points.txt b/Brie/Brie.egg-info/entry_points.txt new file mode 100644 index 0000000..374c6a8 --- /dev/null +++ b/Brie/Brie.egg-info/entry_points.txt @@ -0,0 +1,7 @@ + + [paste.app_factory] + main = brie.config.middleware:make_app + + [paste.app_install] + main = pylons.util:PylonsInstaller + \ No newline at end of file diff --git a/Brie/Brie.egg-info/paster_plugins.txt b/Brie/Brie.egg-info/paster_plugins.txt new file mode 100644 index 0000000..ab508e5 --- /dev/null +++ b/Brie/Brie.egg-info/paster_plugins.txt @@ -0,0 +1,4 @@ +PasteScript +Pylons +TurboGears2 +tg.devtools diff --git a/Brie/Brie.egg-info/requires.txt b/Brie/Brie.egg-info/requires.txt new file mode 100644 index 0000000..ad4a852 --- /dev/null +++ b/Brie/Brie.egg-info/requires.txt @@ -0,0 +1,7 @@ +TurboGears2 >= 2.0b7 +Catwalk >= 2.0.2 +Babel >=0.9.4 +toscawidgets >= 0.9.7.1 +zope.sqlalchemy >= 0.4 +repoze.tm2 >= 1.0a4 +repoze.what-quickstart >= 1.0 \ No newline at end of file diff --git a/Brie/Brie.egg-info/top_level.txt b/Brie/Brie.egg-info/top_level.txt new file mode 100644 index 0000000..777d1fd --- /dev/null +++ b/Brie/Brie.egg-info/top_level.txt @@ -0,0 +1 @@ +brie diff --git a/Brie/MANIFEST.in b/Brie/MANIFEST.in new file mode 100644 index 0000000..2c5e8d0 --- /dev/null +++ b/Brie/MANIFEST.in @@ -0,0 +1,4 @@ +recursive-include brie/public * +include brie/public/favicon.ico +recursive-include brie/i18n * +recursive-include brie/templates * diff --git a/Brie/README.txt b/Brie/README.txt new file mode 100644 index 0000000..39ece5f --- /dev/null +++ b/Brie/README.txt @@ -0,0 +1,24 @@ +This file is for you to describe the Brie application. Typically +you would include information such as the information below: + +Installation and Setup +====================== + +Install ``Brie`` using the setup.py script:: + + $ cd Brie + $ python setup.py install + +Create the project database for any model classes defined:: + + $ paster setup-app development.ini + +Start the paste http server:: + + $ paster serve development.ini + +While developing you may want the server to reload after changes in package files (or its dependencies) are saved. This can be achieved easily by adding the --reload option:: + + $ paster serve --reload development.ini + +Then you are ready to go. diff --git a/Brie/REAME b/Brie/REAME new file mode 100644 index 0000000..c22489c --- /dev/null +++ b/Brie/REAME @@ -0,0 +1 @@ +migrate_* sont des scripts temporaires d'entre deux diff --git a/Brie/__init__.py b/Brie/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Brie/brie/__init__.py b/Brie/brie/__init__.py new file mode 100644 index 0000000..6189499 --- /dev/null +++ b/Brie/brie/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +"""The Brie package""" diff --git a/Brie/brie/config/__init__.py b/Brie/brie/config/__init__.py new file mode 100644 index 0000000..633f866 --- /dev/null +++ b/Brie/brie/config/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- + diff --git a/Brie/brie/config/app_cfg.py b/Brie/brie/config/app_cfg.py new file mode 100644 index 0000000..b35b8fc --- /dev/null +++ b/Brie/brie/config/app_cfg.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +""" +Global configuration file for TG2-specific settings in Brie. + +This file complements development/deployment.ini. + +Please note that **all the argument values are strings**. If you want to +convert them into boolean, for example, you should use the +:func:`paste.deploy.converters.asbool` function, as in:: + + from paste.deploy.converters import asbool + setting = asbool(global_conf.get('the_setting')) + +""" + +from tg.configuration import AppConfig + +import brie +from brie import model +from brie.lib import app_globals, helpers + +base_config = AppConfig() +base_config.renderers = [] + +base_config.package = brie + +#Set the default renderer +base_config.default_renderer = 'genshi' +base_config.renderers.append('genshi') +# if you want raw speed and have installed chameleon.genshi +# you should try to use this renderer instead. +# warning: for the moment chameleon does not handle i18n translations +#base_config.renderers.append('chameleon_genshi') + +#Configure the base SQLALchemy Setup +base_config.use_sqlalchemy = True +base_config.model = brie.model +base_config.DBSession = brie.model.DBSession + + +# YOU MUST CHANGE THIS VALUE IN PRODUCTION TO SECURE YOUR APP +base_config.sa_auth.cookie_secret = "ChangeME" + +# Configure the authentication backend +base_config.auth_backend = 'sqlalchemy' +base_config.sa_auth.dbsession = model.DBSession +# what is the class you want to use to search for users in the database +base_config.sa_auth.user_class = model.User +# what is the class you want to use to search for groups in the database +base_config.sa_auth.group_class = model.Group +# what is the class you want to use to search for permissions in the database +base_config.sa_auth.permission_class = model.Permission + + +# override this if you would like to provide a different who plugin for +# managing login and logout of your application +base_config.sa_auth.form_plugin = None + +# You may optionally define a page where you want users to be redirected to +# on login: +base_config.sa_auth.post_login_url = '/post_login' + +# You may optionally define a page where you want users to be redirected to +# on logout: +base_config.sa_auth.post_logout_url = '/post_logout' diff --git a/Brie/brie/config/deployment.ini_tmpl b/Brie/brie/config/deployment.ini_tmpl new file mode 100644 index 0000000..8244b6f --- /dev/null +++ b/Brie/brie/config/deployment.ini_tmpl @@ -0,0 +1,95 @@ +# +# Brie - TurboGears configuration +# +# The %(here)s variable will be replaced with the parent directory of this file +# +[DEFAULT] +# WARGING == If debug is not set to false, you'll get the interactive +# debugger on production, which is a huge security hole. + +debug = false +email_to = you@yourdomain.com +smtp_server = localhost +error_email_from = paste@localhost + +[server:main] +use = egg:Paste#http +host = 0.0.0.0 +port = 8080 + +[app:main] +use = egg:Brie +full_stack = true +cache_dir = %(here)s/data +beaker.session.key = brie +beaker.session.secret = ${app_instance_secret} +app_instance_uuid = ${app_instance_uuid} + +# If you'd like to fine-tune the individual locations of the cache data dirs +# for the Cache data, or the Session saves, un-comment the desired settings +# here: +#beaker.cache.data_dir = %(here)s/data/cache +#beaker.session.data_dir = %(here)s/data/sessions +# Specify the database for SQLAlchemy to use via +# turbogears.database +# %(here) may include a ':' character on Windows environments; this can +# invalidate the URI when specifying a SQLite db via path name +sqlalchemy.url = sqlite:///%(here)s/somedb.db +sqlalchemy.echo = False + +# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* +# Debug mode will enable the interactive debugging tool, allowing ANYONE to +# execute malicious code after an exception is raised. +#set debug = false + +# Logging configuration +# Add additional loggers, handlers, formatters here +# Uses python's logging config file format +# http://docs.python.org/lib/logging-config-fileformat.html + +[loggers] +keys = root, brie, sqlalchemy, auth + +[handlers] +keys = console + +[formatters] +keys = generic + +# If you create additional loggers, add them as a key to [loggers] +[logger_root] +level = INFO +handlers = console + +[logger_brie] +level = INFO +handlers = +qualname = brie + +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine +# "level = INFO" logs SQL queries. +# "level = DEBUG" logs SQL queries and results. +# "level = WARN" logs neither. (Recommended for production systems.) + + +# A logger for authentication, identification and authorization -- this is +# repoze.who and repoze.what: +[logger_auth] +level = WARN +handlers = +qualname = auth + +# If you create additional handlers, add them as a key to [handlers] +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +# If you create additional formatters, add them as a key to [formatters] +[formatter_generic] +format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/Brie/brie/config/environment.py b/Brie/brie/config/environment.py new file mode 100644 index 0000000..71bf30f --- /dev/null +++ b/Brie/brie/config/environment.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +"""WSGI environment setup for Brie.""" + +from brie.config.app_cfg import base_config + +__all__ = ['load_environment'] + +#Use base_config to setup the environment loader function +load_environment = base_config.make_load_environment() diff --git a/Brie/brie/config/ldap_config.py b/Brie/brie/config/ldap_config.py new file mode 100644 index 0000000..4e0f5be --- /dev/null +++ b/Brie/brie/config/ldap_config.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- + +uri = "ldaps://ldap.pacaterie.u-psud.fr" + +base_dn = "dc=pacaterie,dc=u-psud,dc=fr" + +username_base_dn = "ou=membres," + base_dn + +room_base_dn = "ou=chambres," + base_dn +area_filter = "(objectClass=pacateriearea)" +floor_filter = "(objectClass=pacateriefloor)" +room_filter = "(objectClass=pacaterieRoom)" diff --git a/Brie/brie/config/middleware.py b/Brie/brie/config/middleware.py new file mode 100644 index 0000000..e0361aa --- /dev/null +++ b/Brie/brie/config/middleware.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +"""WSGI middleware initialization for the Brie application.""" + +from brie.config.app_cfg import base_config +from brie.config.environment import load_environment + + +__all__ = ['make_app'] + +# Use base_config to setup the necessary PasteDeploy application factory. +# make_base_app will wrap the TG2 app with all the middleware it needs. +make_base_app = base_config.setup_tg_wsgi_app(load_environment) + + +def make_app(global_conf, full_stack=True, **app_conf): + """ + Set Brie up with the settings found in the PasteDeploy configuration + file used. + + :param global_conf: The global settings for Brie (those + defined under the ``[DEFAULT]`` section). + :type global_conf: dict + :param full_stack: Should the whole TG2 stack be set up? + :type full_stack: str or bool + :return: The Brie application with all the relevant middleware + loaded. + + This is the PasteDeploy factory for the Brie application. + + ``app_conf`` contains all the application-specific settings (those defined + under ``[app:main]``. + + + """ + app = make_base_app(global_conf, full_stack=True, **app_conf) + + # Wrap your base TurboGears 2 application with custom middleware here + + return app diff --git a/Brie/brie/controllers/__init__.py b/Brie/brie/controllers/__init__.py new file mode 100644 index 0000000..1e6f2e3 --- /dev/null +++ b/Brie/brie/controllers/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +"""Controllers for the Brie application.""" diff --git a/Brie/brie/controllers/auth.py b/Brie/brie/controllers/auth.py new file mode 100644 index 0000000..dc492d4 --- /dev/null +++ b/Brie/brie/controllers/auth.py @@ -0,0 +1,142 @@ +# -*- coding: utf-8 -*- + +from tg import session +from tg.controllers import RestController, redirect +from tg.decorators import expose, validate + +from brie.lib.base import BaseController +from brie.config import ldap_config +from brie.lib.ldap_helper import * + +class User(object): + ldap_bind = None + attrs = None + + def __init__(self, ldap_bind, attrs): + self.ldap_bind = ldap_bind + self.attrs = attrs + #end def +#end class + +class AuthHandler(object): + __users = dict() + __user_session_name = "user" + __anon_bind = None + + def get_anon_bind(self): + if self.__anon_bind is not None: + return self.__anon_bind + else: + self.__anon_bind = Ldap.connect("", "") + return self.__anon_bind + #end if + #end def + + def login(self, username, password): + if self.get_anon_bind() is None: + return False + + actual_user = self.get_anon_bind().search_first(ldap_config.username_base_dn, "(uid=" + username + ")") + + if actual_user is None: + return False + + username_dn = actual_user.dn + bind = Ldap.connect(username_dn, password) + + if bind is None: + return False + + attributes = bind.search_first(username_dn, "(uid=" + username + ")") + + user = User(bind, attributes) + + AuthHandler.__users[username] = user + + session[AuthHandler.__user_session_name] = username + session.save() + + return True + #end def + + def logout(self): + user = session[AuthHandler.__user_session_name] + if user in AuthHandler.__users: + stored_user = AuthHandler.__users[user] + stored_user.ldap_bind.close() + del AuthHandler.__users[user] + #end if + session[AuthHandler.__user_session_name] = None + session.save() + #end def + + def get_user(self): + if not AuthHandler.__user_session_name in session: + return None + + user = session[AuthHandler.__user_session_name] + if user in AuthHandler.__users: + return AuthHandler.__users[user] + + return None + #end def + + def get_user_or_redirect(self): + maybe_user = self.get_user() + if maybe_user is None: + redirect("/auth/login/") # TODO from config + #end if + + return maybe_user + #end def + +#end class + +class AuthenticatedRestController(RestController): + user = None + + def __before__(self, *args, **kwargs): + self.user = current.get_user_or_redirect() + #end def +#end def + +class AuthenticatedBaseController(BaseController): + user = None + + def __before__(self, *args, **kwargs): + self.user = current.get_user_or_redirect() + #end def +#end def + +current = AuthHandler() + +class LoginRestController(RestController): + + @expose("brie.templates.auth.login") + def get(self): + return dict(login = "", error = "") + + @expose("brie.templates.auth.login") + def post(self, username, password): + success = current.login(username, password) + + if success: + redirect("/") + #end if + + return dict(login = username, error = "erreur de connexion") + #end def + + +class AuthRestController(BaseController): + login = LoginRestController() + + @expose() + def logout(self): + current.logout() + redirect("/") +#end class + + + + diff --git a/Brie/brie/controllers/controller.template b/Brie/brie/controllers/controller.template new file mode 100644 index 0000000..70acbe9 --- /dev/null +++ b/Brie/brie/controllers/controller.template @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +"""Sample controller module""" + +# turbogears imports +from tg import expose +#from tg import redirect, validate, flash + +# third party imports +#from pylons.i18n import ugettext as _ +#from repoze.what import predicates + +# project specific imports +from brie.lib.base import BaseController +#from brie.model import DBSession, metadata + + +class SampleController(BaseController): + #Uncomment this line if your controller requires an authenticated user + #allow_only = authorize.not_anonymous() + + @expose('brie.templates.index') + def index(self): + return dict(page='index') diff --git a/Brie/brie/controllers/edit.py b/Brie/brie/controllers/edit.py new file mode 100644 index 0000000..136c578 --- /dev/null +++ b/Brie/brie/controllers/edit.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- + +from tg import session +from tg.controllers import redirect +from tg.decorators import expose, validate + +from brie.lib.camembert_helpers import * + +from brie.config import ldap_config +from brie.lib.ldap_helper import * +from brie.model import DBSession +from brie.model.ldap import * + +from brie.controllers import auth +from brie.controllers.auth import AuthenticatedBaseController, AuthenticatedRestController + +from operator import itemgetter + + +#root = tg.config['application_root_module'].RootController + +""" Controller d'affichage de details de membres, chambres et interfaces """ +class EditController(AuthenticatedBaseController): + show = None + wifi = None + + def __init__(self, new_show): + self.show = new_show + self.wifi = WifiRestController(new_show) + + """ Affiche les détails du membre, de la chambre et de l'interface """ + @expose("brie.templates.edit.member") + def member(self, uid): + return self.show.member(uid) + #end def + + @expose("brie.templates.edit.room") + def room(self, room_number): + return self.show.room(room_number) + #end def + + @expose("brie.templates.edit.interface") + def interface(self, interface_id): + return self.show.interface(interface_id) + #end def +#end class + +class WifiRestController(AuthenticatedRestController): + show = None + + def __init__(self, new_show): + self.show = new_show + + @expose("brie.templates.edit.wifi") + def get(self, uid): + member = Member.get_by_uid(self.user, uid) + + if member is None: + self.show.error_no_entry() + + + def post(self, uid, password): + member = Member.get_by_uid(self.user, uid) + + if member is None: + self.show.error_no_entry() + + wifi = Wifi.get_by_dn(self.user, member.dn) + + if wifi is None: + wifi_dn = "cn=wifi," + member.dn + self.user.ldap_bind.add_entry(wifi_dn, Wifi.entry_attr(password)) + else: + attr = { + "userPassword" : password + } + self.user.ldap_bind.replace_attr(wifi.dn, attr) + #end if + + redirect("/show/member/" + uid) + #end def +#end class + diff --git a/Brie/brie/controllers/rooms.py b/Brie/brie/controllers/rooms.py new file mode 100644 index 0000000..256cbe2 --- /dev/null +++ b/Brie/brie/controllers/rooms.py @@ -0,0 +1,111 @@ +from tg import session +from tg.controllers import redirect +from tg.decorators import expose, validate +from brie.lib.base import BaseController + +from brie.lib.camembert_helpers import * + +from brie.config import ldap_config +from brie.lib.ldap_helper import * +from brie.model import DBSession +from brie.model.camembert import * +from brie.model.ldap import * + +from brie.controllers import auth +from brie.controllers.auth import AuthenticatedBaseController, AuthenticatedRestController + +from operator import itemgetter + + +class RoomsController(AuthenticatedBaseController): + __default_color = "ok_color" + __error_colors = { + "PAS PAYE" : "non_paye_color", + "CERTIF" : "non_certif_color", + "VIDE" : "vide_color" + } + + + def color_picker(self, description): + for color in self.__error_colors.iteritems(): + if color[0] in description: + return color[1] + #end if + #end for + + return self.__default_color + #end def + + def reverse_sort_name(self, name_items): + return sorted(name_items, key=itemgetter(0), reverse=True) + + def sort_name(self, name_items): + return sorted(name_items, key=itemgetter(0)) + + @expose("brie.templates.rooms.index") + def index(self): + result = DBSession.query(Interface) + + interfaces_dict = dict() + for interface in result: + interfaces_dict[str(interface.idinterface)] = interface + + stats = dict() + areas = dict() + + rooms = self.user.ldap_bind.search(ldap_config.room_base_dn, ldap_config.room_filter) + + rooms = sorted(rooms, key = lambda a: a.cn.first()) + for room in rooms: + interface = interfaces_dict[room.get("x-switchInterface").first()] + + color = self.color_picker(interface.ifdescription) + if color in stats: + stats[color] = stats[color] + 1 + else: + stats[color] = 0 + #end if + + room_id = int(room.uid.first()) + floor = Translations.floor_of_room(room_id) + area = Translations.area_of_room(room_id) + + if area not in areas: + areas[area] = dict() + #end if + + if floor not in areas[area]: + areas[area][floor] = [] + #end if + + areas[area][floor].append((room, interface)) + #end for + + return { "areas" : areas, "color_picker" : self.color_picker, "reverse_sorted_name" : self.reverse_sort_name, "sorted_name" : self.sort_name, "stats" : stats} + #end def + + @expose("brie.templates.rooms.index") + def preview(self, number): + if not number.isdigit(): redirect("/rooms/") + + index_result = self.index() + + room = Room.get_by_uid(self.user, number) + + + member = None + if room.has("x-memberIn"): + member = Member.get_by_dn(self.user, room.get("x-memberIn").first()) + + + interface = ( + DBSession.query(Interface) + .filter(Interface.idinterface == room.get("x-switchInterface").first()) + .first() + ) + + preview = member, room, interface + index_result["preview"] = preview + + return index_result + #end def diff --git a/Brie/brie/controllers/root.py b/Brie/brie/controllers/root.py new file mode 100644 index 0000000..b837fb0 --- /dev/null +++ b/Brie/brie/controllers/root.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +"""Main Controller""" + +from tg import expose, flash, require, url, request, redirect +from pylons.i18n import ugettext as _, lazy_ugettext as l_ +from catwalk.tg2 import Catwalk +from repoze.what import predicates + +from brie.lib.base import BaseController +from brie.model import DBSession, metadata +from brie import model +#from brie.controllers.secure import SecureController +import brie.controllers.auth as auth_handler +from brie.controllers.auth import AuthRestController +from brie.controllers.rooms import RoomsController +from brie.controllers.show import ShowController +from brie.controllers.edit import EditController + +from brie.model.camembert import Materiel + +__all__ = ['RootController'] + + +class RootController(BaseController): + """ + The root controller for the Brie application. + + All the other controllers and WSGI applications should be mounted on this + controller. For example:: + + panel = ControlPanelController() + another_app = AnotherWSGIApplication() + + Keep in mind that WSGI applications shouldn't be mounted directly: They + must be wrapped around with :class:`tg.controllers.WSGIAppController`. + + """ +# admin = Catwalk(model, DBSession) + + auth = AuthRestController() + rooms = RoomsController() + show = ShowController() + edit = EditController(show) + + @expose('brie.templates.index') + def index(self): + """Handle the front-page.""" + materiel = DBSession.query(Materiel) + user = auth_handler.current.get_user() + + return { "user" : user, "materiel" : materiel } + + @expose() + def foobar(self): + redirect("http://172.17.22.10:9000/toto") + #end def + +# @expose('brie.templates.index') +# @require(predicates.has_permission('manage', msg=l_('Only for managers'))) +# def manage_permission_only(self, **kw): +# """Illustrate how a page for managers only works.""" +# return dict(page='managers stuff') diff --git a/Brie/brie/controllers/show.py b/Brie/brie/controllers/show.py new file mode 100644 index 0000000..92c5a50 --- /dev/null +++ b/Brie/brie/controllers/show.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- + +from tg import session +from tg.controllers import redirect +from tg.decorators import expose, validate + +from brie.lib.camembert_helpers import * + +from brie.config import ldap_config +from brie.lib.ldap_helper import * +from brie.model import DBSession +from brie.model.camembert import Interface +from brie.model.ldap import * + +from brie.controllers import auth +from brie.controllers.auth import AuthenticatedBaseController, AuthenticatedRestController + +from operator import itemgetter + +""" Controller d'affichage de details de membres, chambres et interfaces """ +class ShowController(AuthenticatedBaseController): + + @expose("brie.templates.show.error") + def error_no_entry(self): + return { "error" : "Entrée non existante" } + + """ Affiche les détails du membre, de la chambre et de l'interface """ + @expose("brie.templates.show.member") + def member(self, uid): + member = Member.get_by_uid(self.user, uid) + + if member is None: + return self.error_no_entry() + + room = Room.get_by_member_dn(self.user, member.dn) + interface = ( + DBSession.query(Interface) + .filter(Interface.idinterface == room.get("x-switchInterface").first()) + .first() + ) + + return { "member_ldap" : member, "interface" : interface, "room_ldap" : room } + #end def + + @expose("brie.templates.show.room") + def room(self, room_id): + room = Room.get_by_uid(self.user, room_id) + + if room is None: + return self.error_no_entry() + + interface = ( + DBSession.query(Interface) + .filter(Interface.idinterface == room.get("x-switchInterface").first()) + .first() + ) + + member = None + if room.has("x-memberIn"): + member = Member.get_by_dn(self.user, room.get("x-memberIn").first()) + + return { "interface" : interface, "room_ldap" : room, "member_ldap" : member } + #end def + + @expose("brie.templates.show.interface") + def interface(self, interface_id): + interface = ( + DBSession.query(Interface) + .filter(Interface.idinterface == interface_id) + .first() + ) + + if interface is None: + return self.error_no_entry() + + room = Room.get_by_interface(self.user, interface.idinterface) + + return { "interface" : interface, "room_ldap" : room } + #end def +#end class + diff --git a/Brie/brie/controllers/template.py b/Brie/brie/controllers/template.py new file mode 100644 index 0000000..4c9f801 --- /dev/null +++ b/Brie/brie/controllers/template.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +"""Fallback controller.""" + +from brie.lib.base import BaseController + +__all__ = ['TemplateController'] + + +class TemplateController(BaseController): + """ + The fallback controller for Brie. + + By default, the final controller tried to fulfill the request + when no other routes match. It may be used to display a template + when all else fails, e.g.:: + + def view(self, url): + return render('/%s' % url) + + Or if you're using Mako and want to explicitly send a 404 (Not + Found) response code when the requested template doesn't exist:: + + import mako.exceptions + + def view(self, url): + try: + return render('/%s' % url) + except mako.exceptions.TopLevelLookupException: + abort(404) + + """ + + def view(self, url): + """Abort the request with a 404 HTTP status code.""" + abort(404) diff --git a/Brie/brie/i18n/ru/LC_MESSAGES/brie.po b/Brie/brie/i18n/ru/LC_MESSAGES/brie.po new file mode 100644 index 0000000..36532d4 --- /dev/null +++ b/Brie/brie/i18n/ru/LC_MESSAGES/brie.po @@ -0,0 +1,24 @@ +# Russian translations for ${package}. +# Copyright (C) 2008 ORGANIZATION +# This file is distributed under the same license as the ${package} project. +# FIRST AUTHOR , 2008. +# +msgid "" +msgstr "" +"Project-Id-Version: ${package} 0.0.0\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2008-01-13 14:00+0200\n" +"PO-Revision-Date: 2008-01-13 14:00+0200\n" +"Last-Translator: FULL NAME \n" +"Language-Team: ru \n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 0.9.1\n" + +#: ${package}/controllers/root.py:13 +msgid "Your application is now running" +msgstr "Ваши приложение успешно запущено" + diff --git a/Brie/brie/lib/__init__.py b/Brie/brie/lib/__init__.py new file mode 100644 index 0000000..633f866 --- /dev/null +++ b/Brie/brie/lib/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- + diff --git a/Brie/brie/lib/app_globals.py b/Brie/brie/lib/app_globals.py new file mode 100644 index 0000000..0bd3089 --- /dev/null +++ b/Brie/brie/lib/app_globals.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- + +"""The application's Globals object""" + +__all__ = ['Globals'] + + +class Globals(object): + """Container for objects available throughout the life of the application. + + One instance of Globals is created during application initialization and + is available during requests via the 'app_globals' variable. + + """ + + def __init__(self): + """Do nothing, by default.""" + pass diff --git a/Brie/brie/lib/base.py b/Brie/brie/lib/base.py new file mode 100644 index 0000000..b7cfc4f --- /dev/null +++ b/Brie/brie/lib/base.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- + +"""The base Controller API.""" + +from tg import TGController, tmpl_context +from tg.render import render +from tg import request +from pylons.i18n import _, ungettext, N_ +from tw.api import WidgetBunch +import brie.model as model + +__all__ = ['Controller', 'BaseController'] + + +class BaseController(TGController): + """ + Base class for the controllers in the application. + + Your web application should have one of these. The root of + your application is used to compute URLs used by your app. + + """ + + def __call__(self, environ, start_response): + """Invoke the Controller""" + # TGController.__call__ dispatches to the Controller method + # the request is routed to. This routing information is + # available in environ['pylons.routes_dict'] + + request.identity = request.environ.get('repoze.who.identity') + tmpl_context.identity = request.identity + return TGController.__call__(self, environ, start_response) diff --git a/Brie/brie/lib/camembert_helpers.py b/Brie/brie/lib/camembert_helpers.py new file mode 100644 index 0000000..317db5d --- /dev/null +++ b/Brie/brie/lib/camembert_helpers.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +import unicodedata + + +class Translations(object): + + @staticmethod + def to_uid(name, surname): + clean_name = Translations.strip_accents(name.replace(" ", "")).lower()[:15] + clean_surname = Translations.strip_accents(surname.replace(" ", "")).lower()[:15] + + return clean_name + "." + clean_surname + #end def + + @staticmethod + def floor_of_room(room): + return room / 100 + #end def + + @staticmethod + def area_of_room(room): + if Translations.floor_of_room(room) == 5: + return "crous" + + floor_number = room % 100 + + if floor_number <= 33: + return "sud" + else: + return "nord" + #end if + #end def + +#end class + + + + # http://stackoverflow.com/questions/517923/what-is-the-best-way-to-remove-accents-in-a-python-unicode-string + @staticmethod + def strip_accents(s): + return ''.join((c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn')) + #end def diff --git a/Brie/brie/lib/helpers.py b/Brie/brie/lib/helpers.py new file mode 100644 index 0000000..8dc40b5 --- /dev/null +++ b/Brie/brie/lib/helpers.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +"""WebHelpers used in Brie.""" + +from webhelpers import date, feedgenerator, html, number, misc, text diff --git a/Brie/brie/lib/ldap_helper.py b/Brie/brie/lib/ldap_helper.py new file mode 100644 index 0000000..531a953 --- /dev/null +++ b/Brie/brie/lib/ldap_helper.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- +import ldap +#import ldap.modlist as modlist + +from brie.config import ldap_config + +class Ldap(object): + __connection = None + + def __init__(self, connection): + self.__connection = connection + #end def + + @staticmethod + def connect(dn, password): + connection = None + try: + connection = ldap.initialize(ldap_config.uri) + connection.simple_bind_s(dn, password) + except: + return None + #end try + + if connection is not None: + return Ldap(connection) + #end + + return None + #end def + + def search(self, dn, filter, scope = ldap.SCOPE_SUBTREE): + try: + results = self.__connection.search_s(dn, scope, filter) + except: + return None + #end try + + ldap_results = [] + + for result in results: + result_dn = result[0] + attributes = result[1] + val_dict = dict() + + for attribute in attributes.iteritems(): + name = attribute[0] + values = attribute[1] + ldap_value = LdapValue(name, values) + val_dict[name] = ldap_value + #end for + + ldap_result = LdapResult(result_dn, val_dict) + ldap_results.append(ldap_result) + #end for + + return ldap_results + #end def + + def search_first(self, dn, filter, scope = ldap.SCOPE_SUBTREE): + results = self.search(dn, filter, scope) + if results is None: return None + + for result in results: + return result + #end for + + return None + #end def + + def search_dn(self, dn): + return self.search_first(dn, "(objectClass=*)", ldap.SCOPE_BASE) + + def replace_attr(self, dn, attributes): + modlist = [] + for attribute in attributes.iteritems(): + modlist.append((ldap.MOD_REPLACE, attribute[0], attribute[1])) + #end for + self.__connection.modify_s(dn, modlist) + #end def + + def add_attr(self, dn, attributes): + modlist = [] + for attribute in attributes.iteritems(): + modlist.append((ldap.MOD_ADD, attribute[0], attribute[1])) + #end for + try: + self.__connection.modify_s(dn, modlist) + except ldap.TYPE_OR_VALUE_EXISTS: + pass + #end def + + def delete_attr(self, dn, attributes): + modlist = [] + for attribute in attributes.iteritems(): + modlist.append((ldap.MOD_DELETE, attribute[0], attribute[1])) + #end for + #try: + self.__connection.modify_s(dn, modlist) + #except: + # pass + #end def + + def add_entry(self, dn, attributes): + modlist = [] + for attribute in attributes.iteritems(): + modlist.append((attribute[0], attribute[1])) + #end for + + ##try: + self.__connection.add_s(dn, modlist) + ##except: + ## pass + #end def + + def delete_entry(self, dn): + #try: + self.__connection.delete_s(dn) + #except: + # pass + #end def + + def delete_entry_subtree(self, dn): + entries = self.search(dn, "(objectClass=*)") + for entry in reversed(entries): + self.delete_entry(entry.dn) + #end for + #end def + + def rename_entry(self, dn, newdn, superior): + self.__connection.rename_s(dn, newdn, newsuperior= superior) + + def close(self): + self.__connection.unbind() + +#end class + +class LdapResult(object): + dn = None + + def __init__(self, dn, var_dict): + self.__dict__ = var_dict + self.dn = dn + #end def + + def has(self, attribute_name): + return attribute_name in self.__dict__ + #end def + + def get(self, name): + if name in self.__dict__: + return self.__dict__[name] + else: + return self.__getattr__(name) + #end if + #end def + + def __getattr__(self, name): + return None + #end def + +#end class + +class LdapValue(object): + name = None + values = [] + + def __init__(self, name, values): + self.values = [value.decode("utf-8") for value in values] + self.name = name + #end def + + def first(self, default = None): + for value in self.values: + return value + #end for + + return default + #end def +#end class + diff --git a/Brie/brie/model/__init__.py b/Brie/brie/model/__init__.py new file mode 100644 index 0000000..e57b92e --- /dev/null +++ b/Brie/brie/model/__init__.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +"""The application's model objects""" + +from zope.sqlalchemy import ZopeTransactionExtension +from sqlalchemy.orm import scoped_session, sessionmaker +#from sqlalchemy import MetaData +from sqlalchemy.ext.declarative import declarative_base + +# Global session manager: DBSession() returns the Thread-local +# session object appropriate for the current web request. +maker = sessionmaker(autoflush=True, autocommit=False, + extension=ZopeTransactionExtension()) +DBSession = scoped_session(maker) + +# Base class for all of our model classes: By default, the data model is +# defined with SQLAlchemy's declarative extension, but if you need more +# control, you can switch to the traditional method. +DeclarativeBase = declarative_base() + +# There are two convenient ways for you to spare some typing. +# You can have a query property on all your model classes by doing this: +# DeclarativeBase.query = DBSession.query_property() +# Or you can use a session-aware mapper as it was used in TurboGears 1: +# DeclarativeBase = declarative_base(mapper=DBSession.mapper) + +# Global metadata. +# The default metadata is the one from the declarative base. +metadata = DeclarativeBase.metadata + +# If you have multiple databases with overlapping table names, you'll need a +# metadata for each database. Feel free to rename 'metadata2'. +#metadata2 = MetaData() + +##### +# Generally you will not want to define your table's mappers, and data objects +# here in __init__ but will want to create modules them in the model directory +# and import them at the bottom of this file. +# +###### + +def init_model(engine): + """Call me before using any of the tables or classes in the model.""" + + DBSession.configure(bind=engine) + # If you are using reflection to introspect your database and create + # table objects for you, your tables must be defined and mapped inside + # the init_model function, so that the engine is available if you + # use the model outside tg2, you need to make sure this is called before + # you use the model. + + # + # See the following example: + + #global t_reflected + + #t_reflected = Table("Reflected", metadata, + # autoload=True, autoload_with=engine) + + #mapper(Reflected, t_reflected) + +# Import your model modules here. +from brie.model.auth import User, Group, Permission diff --git a/Brie/brie/model/auth.py b/Brie/brie/model/auth.py new file mode 100644 index 0000000..4448aba --- /dev/null +++ b/Brie/brie/model/auth.py @@ -0,0 +1,232 @@ +# -*- coding: utf-8 -*- +""" +Auth* related model. + +This is where the models used by :mod:`repoze.who` and :mod:`repoze.what` are +defined. + +It's perfectly fine to re-use this definition in the Brie application, +though. + +""" +import os +from datetime import datetime +import sys +try: + from hashlib import sha1 +except ImportError: + sys.exit('ImportError: No module named hashlib\n' + 'If you are on python2.4 this library is not part of python. ' + 'Please install it. Example: easy_install hashlib') + +from sqlalchemy import Table, ForeignKey, Column +from sqlalchemy.types import Unicode, Integer, DateTime +from sqlalchemy.orm import relation, synonym + +from brie.model import DeclarativeBase, metadata, DBSession + +__all__ = ['User', 'Group', 'Permission'] + + +#{ Association tables + + +# This is the association table for the many-to-many relationship between +# groups and permissions. This is required by repoze.what. +group_permission_table = Table('tg_group_permission', metadata, + Column('group_id', Integer, ForeignKey('tg_group.group_id', + onupdate="CASCADE", ondelete="CASCADE")), + Column('permission_id', Integer, ForeignKey('tg_permission.permission_id', + onupdate="CASCADE", ondelete="CASCADE")) +) + +# This is the association table for the many-to-many relationship between +# groups and members - this is, the memberships. It's required by repoze.what. +user_group_table = Table('tg_user_group', metadata, + Column('user_id', Integer, ForeignKey('tg_user.user_id', + onupdate="CASCADE", ondelete="CASCADE")), + Column('group_id', Integer, ForeignKey('tg_group.group_id', + onupdate="CASCADE", ondelete="CASCADE")) +) + + +#{ The auth* model itself + + +class Group(DeclarativeBase): + """ + Group definition for :mod:`repoze.what`. + + Only the ``group_name`` column is required by :mod:`repoze.what`. + + """ + + __tablename__ = 'tg_group' + + #{ Columns + + group_id = Column(Integer, autoincrement=True, primary_key=True) + + group_name = Column(Unicode(16), unique=True, nullable=False) + + display_name = Column(Unicode(255)) + + created = Column(DateTime, default=datetime.now) + + #{ Relations + + users = relation('User', secondary=user_group_table, backref='groups') + + #{ Special methods + + def __repr__(self): + return '' % self.group_name + + def __unicode__(self): + return self.group_name + + #} + + +# The 'info' argument we're passing to the email_address and password columns +# contain metadata that Rum (http://python-rum.org/) can use generate an +# admin interface for your models. +class User(DeclarativeBase): + """ + User definition. + + This is the user definition used by :mod:`repoze.who`, which requires at + least the ``user_name`` column. + + """ + __tablename__ = 'tg_user' + + #{ Columns + + user_id = Column(Integer, autoincrement=True, primary_key=True) + + user_name = Column(Unicode(16), unique=True, nullable=False) + + email_address = Column(Unicode(255), unique=True, nullable=False, + info={'rum': {'field':'Email'}}) + + display_name = Column(Unicode(255)) + + _password = Column('password', Unicode(80), + info={'rum': {'field':'Password'}}) + + created = Column(DateTime, default=datetime.now) + + #{ Special methods + + def __repr__(self): + return '' % ( + self.email_address, self.display_name) + + def __unicode__(self): + return self.display_name or self.user_name + + #{ Getters and setters + + @property + def permissions(self): + """Return a set of strings for the permissions granted.""" + perms = set() + for g in self.groups: + perms = perms | set(g.permissions) + return perms + + @classmethod + def by_email_address(cls, email): + """Return the user object whose email address is ``email``.""" + return DBSession.query(cls).filter(cls.email_address==email).first() + + @classmethod + def by_user_name(cls, username): + """Return the user object whose user name is ``username``.""" + return DBSession.query(cls).filter(cls.user_name==username).first() + + def _set_password(self, password): + """Hash ``password`` on the fly and store its hashed version.""" + hashed_password = password + + if isinstance(password, unicode): + password_8bit = password.encode('UTF-8') + else: + password_8bit = password + + salt = sha1() + salt.update(os.urandom(60)) + hash = sha1() + hash.update(password_8bit + salt.hexdigest()) + hashed_password = salt.hexdigest() + hash.hexdigest() + + # Make sure the hashed password is an UTF-8 object at the end of the + # process because SQLAlchemy _wants_ a unicode object for Unicode + # columns + if not isinstance(hashed_password, unicode): + hashed_password = hashed_password.decode('UTF-8') + + self._password = hashed_password + + def _get_password(self): + """Return the hashed version of the password.""" + return self._password + + password = synonym('_password', descriptor=property(_get_password, + _set_password)) + + #} + + def validate_password(self, password): + """ + Check the password against existing credentials. + + :param password: the password that was provided by the user to + try and authenticate. This is the clear text version that we will + need to match against the hashed one in the database. + :type password: unicode object. + :return: Whether the password is valid. + :rtype: bool + + """ + hashed_pass = sha1() + hashed_pass.update(password + self.password[:40]) + return self.password[40:] == hashed_pass.hexdigest() + + +class Permission(DeclarativeBase): + """ + Permission definition for :mod:`repoze.what`. + + Only the ``permission_name`` column is required by :mod:`repoze.what`. + + """ + + __tablename__ = 'tg_permission' + + #{ Columns + + permission_id = Column(Integer, autoincrement=True, primary_key=True) + + permission_name = Column(Unicode(16), unique=True, nullable=False) + + description = Column(Unicode(255)) + + #{ Relations + + groups = relation(Group, secondary=group_permission_table, + backref='permissions') + + #{ Special methods + + def __repr__(self): + return '' % self.permission_name + + def __unicode__(self): + return self.permission_name + + #} + + +#} diff --git a/Brie/brie/model/camembert.py b/Brie/brie/model/camembert.py new file mode 100644 index 0000000..41f3e81 --- /dev/null +++ b/Brie/brie/model/camembert.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- +"""Sample model module.""" + +from sqlalchemy import * +from sqlalchemy.orm import mapper, relation +from sqlalchemy import Table, ForeignKey, Column +from sqlalchemy.types import Integer, Unicode +from sqlalchemy.dialects.postgresql import MACADDR, INET, BOOLEAN, DATE +#from sqlalchemy.orm import relation, backref + +from brie.model import DeclarativeBase, metadata, DBSession + + +class Materiel(DeclarativeBase): + __tablename__ = 'materiel' + + #{ Columns + + idmateriel = Column(Integer, primary_key=True) + + hostname = Column(Unicode(64)) + manageable = Column(Integer) + snmpversion = Column(Integer) + type = Column(Unicode(64)) + ostype = Column(Unicode(512)) + capabilities = Column(Integer) + datecreation = Column(Integer) + datelast = Column(Integer) + + #} + +class Room(DeclarativeBase): + __tablename__ = "room" + + idroom = Column(Integer, primary_key=True) + + idinterface = Column(Integer) + name = Column(Unicode(32)) + +class Computer(DeclarativeBase): + __tablename__ = "computer" + + idcomp = Column(Integer, primary_key = True) + + name = Column(Unicode(32), nullable = False) + mac = Column(MACADDR, nullable = False) + iduser = Column(Integer) + ip = Column(INET) +#end class + +class UserPacaterie(DeclarativeBase): + __tablename__ = "user_pac" + + iduser = Column(Integer, primary_key = True) + + nom = Column(Unicode(64), nullable = False) + prenom = Column(Unicode(64), nullable = False) + datedeco = Column(DATE, nullable = False) + mail = Column(Unicode(64)) + certif = Column(BOOLEAN, nullable = False) + idroom = Column(Integer) + special_case = Column(BOOLEAN) + comment = Column(Unicode(64)) +#end class + +class Ip(DeclarativeBase): + __tablename__ = "ip" + + ip = Column(INET, primary_key = True) + idmateriel = Column(Integer, primary_key = True) + main = Column(BOOLEAN) + datecreation = Column(Integer) + datelast = Column(Integer) +#end class + +class IpUser(DeclarativeBase): + __tablename__ = "ip_user" + + ip = Column(INET, primary_key = True) + free = Column(BOOLEAN) +#end class + +class Fdb(DeclarativeBase): + __tablename__ = "fdb" + + idinterface = Column(Integer, primary_key = True) + vlan = Column(Integer, primary_key = True) + mac = Column(MACADDR, primary_key = True) + datefirst = Column(Integer) + datelast = Column(Integer) + type = Column(Integer) +#end class + +class Action(DeclarativeBase): + __tablename__ = "action" + + idaction = Column(Integer, primary_key = True) + idinterface = Column(Integer) + numaction = Column(Integer, nullable = False) + option = Column(Unicode(256)) +#end class + +class ActionLog(DeclarativeBase): + __tablename__ = "action_log" + + idlog = Column(Integer, primary_key = True) + loggeduser = Column(Unicode(64), nullable = False) + logdate = Column(Integer, nullable = False) + idinterface = Column(Integer) + numaction = Column(Integer, nullable = False) + oldoption = Column(Unicode(256)) + newoption = Column(Unicode(256)) + iduser = Column(Integer) + amount = Column(Unicode(64)) +#end class + +class Interface(DeclarativeBase): + __tablename__ = "interface" + + idinterface = Column(Integer, primary_key = True) + idmateriel = Column(Integer, nullable = False) + ifnumber = Column(Integer, nullable = False) + ifname = Column(Unicode(64)) + ifdescription = Column(Unicode(256)) + ifaddress = Column(MACADDR) + ifspeed = Column(Integer) + ifadminstatus = Column(Integer) + ifoperstatus = Column(Integer) + iftype = Column(Integer) + ifvlan = Column(Integer) + ifvoicevlan = Column(Integer) + ifnativevlan = Column(Integer) + ifmodule = Column(Integer) + ifport = Column(Integer) + portdot1d = Column(Integer) + portfast = Column(BOOLEAN) + portsecenable = Column(BOOLEAN) + portsecstatus = Column(Integer) + portsecmaxmac = Column(Integer) + portseccurrmac = Column(Integer) + portsecviolation = Column(Integer) + portseclastsrcaddr = Column(MACADDR) + portsecsticky = Column(BOOLEAN) +#end class diff --git a/Brie/brie/model/ldap.py b/Brie/brie/model/ldap.py new file mode 100644 index 0000000..f45596f --- /dev/null +++ b/Brie/brie/model/ldap.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- + +from brie.config import ldap_config + +class Member(object): + + @staticmethod + def get_by_dn(user_session, dn): + return user_session.ldap_bind.search_dn(dn) + #end def + + @staticmethod + def get_by_uid(user_session, uid): + return user_session.ldap_bind.search_first(ldap_config.username_base_dn, "(uid=" + uid + ")") + #end def + +#end class + +class Room(object): + + @staticmethod + def get_by_name(user_session, name): + return user_session.ldap_bind.search_first(ldap_config.room_base_dn, "(&" + ldap_config.room_filter + "(cn=" + name + "))") + #end def + + @staticmethod + def get_by_uid(user_session, uid): + return user_session.ldap_bind.search_first(ldap_config.room_base_dn, "(&" + ldap_config.room_filter + "(uid=" + uid + "))") + #end def + + @staticmethod + def get_by_member_dn(user_session, dn): + return user_session.ldap_bind.search_first(ldap_config.room_base_dn, "(&" + ldap_config.room_filter + "(x-memberIn=" + dn + "))") + #end def + + @staticmethod + def get_by_interface(user_session, interface_id): + return user_session.ldap_bind.search_first(ldap_config.room_base_dn, "(&" + ldap_config.room_filter + "(x-switchInterface=" + str(interface_id) + "))") + +#end class + + +class Wifi(object): + + @staticmethod + def entry_attr(password): + return { + "objectClass" : ["top", "organizationalRole", "simpleSecurityObject"], + "cn" : "wifi", + "userPassword" : password + } + #end def + + @staticmethod + def get_by_dn(user_session, dn): + return user_session.ldap_bind.search_first("cn=wifi," + dn) + #end def + +#end class diff --git a/Brie/brie/model/model.template b/Brie/brie/model/model.template new file mode 100644 index 0000000..8bc6e73 --- /dev/null +++ b/Brie/brie/model/model.template @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +"""Sample model module.""" + +from sqlalchemy import * +from sqlalchemy.orm import mapper, relation +from sqlalchemy import Table, ForeignKey, Column +from sqlalchemy.types import Integer, Unicode +#from sqlalchemy.orm import relation, backref + +from brie.model import DeclarativeBase, metadata, DBSession + + +class SampleModel(DeclarativeBase): + __tablename__ = 'sample_model' + + #{ Columns + + id = Column(Integer, primary_key=True) + + data = Column(Unicode(255), nullable=False) + + #} diff --git a/Brie/brie/public/css/common.css b/Brie/brie/public/css/common.css new file mode 100644 index 0000000..124d2c3 --- /dev/null +++ b/Brie/brie/public/css/common.css @@ -0,0 +1,31 @@ +html { + font-family: sans-serif; + color: #444444; +} + +a { + color: #444444; + text-decoration: none; +} + +a:hover { + color: white; + background-color: black; +} + +.section { + font-family: sans-serif; + margin-bottom: 20px; +} + +.section_name, .section_name_no_caps { + color: grey; + font-weight: bold; + margin-bottom: 6px; + display: inline-block; +} + +.section_name { + text-transform: capitalize; +} + diff --git a/Brie/brie/public/css/rooms.css b/Brie/brie/public/css/rooms.css new file mode 100644 index 0000000..7f8f456 --- /dev/null +++ b/Brie/brie/public/css/rooms.css @@ -0,0 +1,68 @@ +html { + font-family: sans-serif; +} + +a { + color: #444444; + text-decoration: none; +} + +a:hover { + color: white; + background-color: black; +} + + + +.floor_name { + color: lightgrey; +} + +.room_number, .interface_status { + display: inline-block; + color: #444444; + font-weight: bold; + padding: 3px; + margin: 2px; +} + +.area { + width: 1300px +} + +.preview_part { + display: inline-block; +} + +.preview_name { + color: #444444; + font-weight: bold; +} + +.ok_color { + background-color: #D1F2C4 +} + +.vide_color { + background-color: white; +} + +.non_certif_color { + background-color: #F2E1C4; +} + +.non_paye_color { + background-color: #F2C4C4; +} + +.shut_color { + background-color: lightgray; +} + +.violation_color { + background-color: #F2C4C4; +} + +.rooms_legend { + float: right; +} diff --git a/Brie/brie/public/css/show.css b/Brie/brie/public/css/show.css new file mode 100644 index 0000000..4de718b --- /dev/null +++ b/Brie/brie/public/css/show.css @@ -0,0 +1,12 @@ +.show_section_name { + margin-left: 200px; +} + +.item_name { + width: 196px; + color: #A0A0A0; + display: inline-block; + height: 22px; + text-align: right; + padding-right: 4px; +} diff --git a/Brie/brie/public/css/style.css b/Brie/brie/public/css/style.css new file mode 100644 index 0000000..32b3b91 --- /dev/null +++ b/Brie/brie/public/css/style.css @@ -0,0 +1,303 @@ +html { + background: #555555 url('../images/pagebg.png') top left repeat-x; + text-align: center; + margin: 0; + padding: 0; +} + +body { + text-align: left; + width: 960px; + margin: 0 auto; + padding: 0; + font-size: 12px; + font-family:"Lucida Grande","Lucida Sans Unicode",geneva,verdana,sans-serif; +} + +a { + color: #286571; +} + +#header { + height: 132px; + margin: 10px 10px 0 10px; + background: url('../images/headerbg.png') top left no-repeat; +} + +#header h1 { + padding: 0; + margin: 0; + padding-top: 30px; + padding-left: 180px; + color: #fff; + position: relative; + font-size: 36px; +} + +#header h1 .subtitle { + font-size: 60%; + position: absolute; + left: 240px; + top: 70px; +} + +ul#mainmenu { + margin: 0; + padding: 0 10px; + background: url('../images/menubg.png') top left no-repeat; + height: 38px; +} + +ul#mainmenu li { + list-style-type: none; + margin: 0; + padding: 0; + position: relative; + display: inline; + float: left; +} + +ul#mainmenu li a { + color: #fff; + float: left; + height: 31px; + display: block; + line-height: 30px; + vertical-align: middle; + padding: 0 10px; + font-size: 12px; + text-decoration: none; + background: url('../images/menu-item-border.png') left top no-repeat; +} + +ul#mainmenu li a:hover, ul#mainmenu li a.active { + background: url('../images/menu-item-actibg.png') left top no-repeat; +} + +ul#mainmenu li.first a { + background: none; +} + +ul#mainmenu li.first a:hover, ul#mainmenu li.first a.active { + background: url('../images/menu-item-actibg-first.png') left top no-repeat; +} + +ul#mainmenu li.loginlogout +{ + float: right; + right: 10px; +} + +ul#mainmenu li.loginlogout a:hover +{ + background: url('../images/menu-item-border.png') left top no-repeat; +} + +#content { + background: #fff url('../images/contentbg.png') left bottom no-repeat; + margin : 0 10px 10px 10px; + padding: 0 10px; + overflow: hidden; +} + +#content .currentpage { + margin-top: 0; +} + +/* Login form*/ + +#loginform +{ + text-align: center; +} + +form.loginfields +{ + text-align: left; + width: 270px; + background: url('../images/loginbg.png') top left no-repeat; + padding: 0; + margin: 0 auto; + border: 0; +} + +form.loginfields h2 +{ + font-size: 16px; + float: left; + padding: 0; + margin: 5px; + margin-top: 0; + background: url('../images/loginheader-left.png') top left no-repeat; +} + +* html form.loginfields h2 +{ + margin-left: 3px; + width: 80px; + text-align: center; +} + +form.loginfields h2 span +{ + background: url('../images/loginheader-right.png') right top no-repeat; + height: 30px; + line-height: 30px; + display: block; + font-size: 100%; + font-weight: normal; + color: #fff; + padding: 0 10px; +} + +*+html form.loginfields h2 span +{ + padding: 0 20px; +} + +form.loginfields label +{ + clear: left; + float: left; + margin-top: 5px; + margin-left: 10px; + width: 65px; + line-height: 31px; + vertical-align: middle; +} + +form.loginfields input.text +{ + float: left; + margin-left: 10px; + margin-top: 5px; + width: 165px; + height: 21px; + padding: 5px; + border: 0; + background: url('../images/inputbg.png') top left no-repeat; + color: #fff; +} + +form.loginfields input#submit +{ + background: url('../images/loginbottombg.png') bottom left no-repeat; + width: 270px; + height: 61px; + border: 0; + margin-top: 10px; + color: #fff; + padding: 10px 140px 20px 10px; +} + +* html form.loginfields input#submit +{ + clear: both; + margin-left: -10px; +} + +/* Sidebar */ +.sidebar { + border: 1px solid #cce; + background-color: #eee; + margin: 0.5em; + margin-left: 1.5em; + padding: 1em; + float: right; + width: 200px; + font-size: 88%; +} + +.sidebar h2 { + margin-top: 0; + color: black; +} + +.sidebar ul { + margin-left: 1.5em; + padding-left: 0; +} + + + +#sb_top { + clear: right; +} + +#sb_bottom { + clear: right; +} + +#getting_started { + margin-left: 20px; +} + +#getting_started_steps a { + text-decoration: none; +} + +#getting_started_steps a:hover { + text-decoration: underline; +} + +#getting_started_steps li { + margin-bottom: 0.5em; +} + +/* Other and footer */ +#footer { + background: #fff; + padding: 10px; + color:#888888; + font-size:90%; +} +.flogo { + float:left; + margin-bottom:0px; + padding-left:20px; + padding-right:20px; + padding-top:0px; +} +.foottext p { + margin: 0; padding: 0; +} +.code { +font-family:monospace; +font-size:127%; +} +span.code { +background:#EEEEEE none repeat scroll 0% 0%; +font-weight:bold; +} +#flash, .notice { +font-size:120%; +font-weight:bolder; +margin:0pt auto 0.5em; +width:680px; +} +#flash div, .notice { +padding:20px 15px 20px 65px; +} +#flash .ok { +background:#d8ecd8 url(../images/ok.png) no-repeat scroll 10px center; +} +#flash .warning { +background:#fff483 url(../images/warning.png) no-repeat scroll 10px center; +} +#flash .error { +background:#f9c5c1 url(../images/error.png) no-repeat scroll 10px center; +} +#flash .alert, +#flash .info { +background:#EEEEFF url(../images/info.png) no-repeat scroll 10px center; +} +.notice { +background:#EEEEFF url(../images/info.png) no-repeat scroll 10px center; +} +.fielderror { +color:red; +font-weight:bold; +} +div.clearingdiv { +clear:both; +} diff --git a/Brie/brie/public/favicon.ico b/Brie/brie/public/favicon.ico new file mode 100644 index 0000000..840986e Binary files /dev/null and b/Brie/brie/public/favicon.ico differ diff --git a/Brie/brie/templates/__init__.py b/Brie/brie/templates/__init__.py new file mode 100644 index 0000000..a2daccf --- /dev/null +++ b/Brie/brie/templates/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +"""Templates package for the application.""" diff --git a/Brie/brie/templates/auth/__init__.py b/Brie/brie/templates/auth/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Brie/brie/templates/auth/login.html b/Brie/brie/templates/auth/login.html new file mode 100644 index 0000000..99f1d03 --- /dev/null +++ b/Brie/brie/templates/auth/login.html @@ -0,0 +1,16 @@ + + +
+

${error}

+
+ Nom d'utilisateur + +
+
+ Nom d'utilisateur + +
+ +
+ + diff --git a/Brie/brie/templates/edit/__init__.py b/Brie/brie/templates/edit/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Brie/brie/templates/edit/error.html b/Brie/brie/templates/edit/error.html new file mode 100644 index 0000000..0fe9074 --- /dev/null +++ b/Brie/brie/templates/edit/error.html @@ -0,0 +1,6 @@ + + ${error} + diff --git a/Brie/brie/templates/edit/member.html b/Brie/brie/templates/edit/member.html new file mode 100644 index 0000000..6339084 --- /dev/null +++ b/Brie/brie/templates/edit/member.html @@ -0,0 +1,23 @@ + + + + + + + +
+ Entrée inexistante +
${member_view(member_ldap)}
+
+
+ Pas de chambre associée +
${room_view(room)}
+
+
+ Pas d'interface associée +
${interface_view(interface)}
+
+ + diff --git a/Brie/brie/templates/edit/member_room_interface_edit_views.html b/Brie/brie/templates/edit/member_room_interface_edit_views.html new file mode 100644 index 0000000..726a926 --- /dev/null +++ b/Brie/brie/templates/edit/member_room_interface_edit_views.html @@ -0,0 +1,133 @@ + + +
+ ${member_ldap.cn.first()} +
+
+ Fin de connexion + + Pas de fin de connexion + ${member_ldap.get("x-connectionEnd").first()} + +
+
+ E-mail + +
+
+ Certificat + + + oui + non + + +
+
+ Commentaire + + + ${member_ldap.get("x-comment").first()} + +
+
+ Cas spécial + + + oui + non + + +
+
+ Wifi +
+
+
+
+ + +
+ CHAMBRE ${room.cn.first()} +
+
+ Membre + + ${member_in.cn.first()} + +
+
+
+
+ + +
+ INFOS INTERFACE +
+
+ Nombre de mac max + ${interface.portsecmaxmac} +
+
+ Violation + ${interface.portsecviolation} +
+
+
+
+ INFOS AVANCÉES +
+
+ ifNumber + ${interface.ifnumber} +
+
+ ifAddress + ${interface.ifaddress} +
+
+ ifType + ${interface.iftype} +
+
+ Description + ${interface.ifdescription} +
+
+ Etat + + Up + Down + Error + Inconnu + +
+
+ Vitesse + + 10 Mb/s + 100 Mb/s + 1 Gb/s + interface.ifspeed + +
+
+ Vlan + ${interface.ifvlan} +
+
+ Native Vlan + ${interface.ifnativevlan} +
+
+ SpanningTree Portfast + ${interface.portfast} +
+
+
+
+ + diff --git a/Brie/brie/templates/edit/room.html b/Brie/brie/templates/edit/room.html new file mode 100644 index 0000000..f778b3c --- /dev/null +++ b/Brie/brie/templates/edit/room.html @@ -0,0 +1,19 @@ + + + + + + + +
+ Pas de chambre associée +
${room_view(room, member_ldap)}
+
+
+ Pas d'interface associée +
${interface_view(interface)}
+
+ + diff --git a/Brie/brie/templates/index.html b/Brie/brie/templates/index.html new file mode 100644 index 0000000..024d337 --- /dev/null +++ b/Brie/brie/templates/index.html @@ -0,0 +1,10 @@ + + + +
${login_widget(user)}
+

Test

+
+ ${item.hostname} +
+ + diff --git a/Brie/brie/templates/login_widget.html b/Brie/brie/templates/login_widget.html new file mode 100644 index 0000000..0c160e3 --- /dev/null +++ b/Brie/brie/templates/login_widget.html @@ -0,0 +1,17 @@ + + +
+ +
+ ${user.attrs.cn.first()} + Deconnection +
+
+
+ diff --git a/Brie/brie/templates/models/__init__.py b/Brie/brie/templates/models/__init__.py new file mode 100644 index 0000000..a2daccf --- /dev/null +++ b/Brie/brie/templates/models/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +"""Templates package for the application.""" diff --git a/Brie/brie/templates/models/about.html b/Brie/brie/templates/models/about.html new file mode 100644 index 0000000..39e349b --- /dev/null +++ b/Brie/brie/templates/models/about.html @@ -0,0 +1,132 @@ + + + + + + + + Learning TurboGears 2.0: Quick guide to the Quickstart pages. + + + + ${sidebar_top()} + ${sidebar_bottom()} +
+

Architectural basics of a quickstart TG2 site.

+

The TG2 quickstart command produces this basic TG site. Here's how it works.

+
    +
  1. +

    Code my data model

    +

    When you want a model for storing favorite links or wiki content, + the /model folder in your site is ready to go.

    +

    You can build a dynamic site without any data model at all. There + still be a default data-model template for you if you didn't enable + authentication and authorization in quickstart. If you enabled + it, you got auth data-model made for you.

    +
  2. +
  3. +

    Design my URL structure

    +

    The "root.py" file under the + /controllers folder has your URLs. When you + called this url (about), + the command went through the RootController class to the + about() method.

    +

    Those Python methods are responsible to create the dictionary of + variables that will be used in your web views (template).

    +
  4. +
  5. +

    Reuse the web page elements

    +

    A web page viewed by user could be constructed by single or + several reusable templates under /templates. + Take 'about' page for example, each reusable templates generating + a part of the page. We'll cover them in the order of where they are + found, listed near the top of the about.html template

    +

    header.html - The + "header.html" template contains the HTML code to display the + 'header': The blue gradient, TG2 logo, and some site text at the + top of every page it is included on. When the "about.html" template + is called, it includes this "header.html" template (and the others) + with a <xi:include /> tag, part of + the Genshi templating system. The "header.html" template is not a + completely static HTML -- it also dynamically displays the current + page name with a Genshi template method called "replace" with the + code: <span py:replace="page"/>. + It means replace this <span /> + region with the contents found in the variable 'page' that has + been sent in the dictionary to this "about.html" template, and is + available through that namespace for use by this "header.html" + template. That's how it changes in the header depending on what + page you are visiting. +

    +

    sidebars.html - The + sidebars (navigation areas on the right side of the page) are + generated as two separate py:def blocks + in the "sidebars.html" template. The py:def + construct is best thought of as a "macro" code... a simple way to + separate and reuse common code snippets. All it takes to include + these on the "about.html" page template is to write + +

    + $${sidebar_top()} +
    + $${sidebar_bottom()} +

    +
    in the page where they are wanted. CSS styling (in + "/public/css/style.css") floats them off to the right side. You can + remove a sidebar or add more of them, and the CSS will place them one + atop the other.

    +

    This is, of course, also exactly how the header and footer + templates are also displayed in their proper places, but we'll + cover that in the "master.html" template below.

    +

    Oh, and in sidebar_top we've added a dynamic menu that shows the + link to this page at the top when you're at the "index" page, and + shows a link to the Home (index) page when you're here. Study the + "sidebars.html" template to see how we used + py:choose for that.

    +

    footer.html - The + "footer.html" block is simple, but also utilizes a special + "replace" method to set the current YEAR in the footer copyright + message. The code is: + <span py:replace="now.strftime('%Y')"> + and it uses the variable "now" that was passed + in with the dictionary of variables. But because "now" is a + datetime object, we can use the Python + "strftime()" method with the "replace" + call to say "Just Display The Year Here". Simple, elegant; we + format the date display in the template (the View in the + Model/View/Controller architecture) rather than formatting it in + the Controller method and sending it to the template as a string + variable.

    +

    master.html - The + "master.html" template is called last, by design. The "master.html" + template controls the overall design of the page we're looking at, + calling first the "header" py:def macro, then the putting everything + from this "about.html" template into the "content" div, and + then calling the "footer" macro at the end. Thus the "master.html" + template provides the overall architecture for each page in this + site.

    +

    But why then shouldn't we call it first? Isn't it the most + important? Perhaps, but that's precisely why we call it LAST. + The "master.html" template needs to know where to find everything + else, everything that it will use in py:def macros to build the + page. So that means we call the other templates first, and then + call "master.html".

    +

    There's more to the "master.html" template... study it to see how + the <title> tags and static JS and CSS files are brought into + the page. Templating with Genshi is a powerful tool and we've only + scratched the surface. There are also a few little CSS tricks + hidden in these pages, like the use of a "clearingdiv" to make + sure that your footer stays below the sidebars and always looks + right. That's not TG2 at work, just CSS. You'll need all your + skills to build a fine web app, but TG2 will make the hard parts + easier so that you can concentrate more on good design and content + rather than struggling with mechanics.

    +
  6. +
+

Good luck with TurboGears 2!

+
+ + diff --git a/Brie/brie/templates/models/authentication.html b/Brie/brie/templates/models/authentication.html new file mode 100644 index 0000000..d86204b --- /dev/null +++ b/Brie/brie/templates/models/authentication.html @@ -0,0 +1,67 @@ + + + + + + + + Learning TurboGears 2.0: Quick guide to authentication. + + + + ${sidebar_top()} + ${sidebar_bottom()} +
+

Authentication & Authorization in a TG2 site.

+

If you have access to this page, this means you have enabled authentication and authorization + in the quickstart to create your project.

+

+ The paster command will have created a few specific controllers for you. But before you + go to play with those controllers you'll need to make sure your application has been + properly bootstapped. + This is dead easy, here is how to do this: +

+ + + paster setup-app development.ini + + +

+ inside your application's folder and you'll get a database setup (using the preferences you have + set in your development.ini file). This database will also have been prepopulated with some + default logins/passwords so that you can test the secured controllers and methods. +

+

+ To change the comportement of this setup-app command you just need to edit the websetup.py file. +

+

+ Now try to visiting the manage_permission_only URL. You will be challenged with a login/password form. +

+

+ Only managers are authorized to visit this method. You will need to log-in using: +

+ + login: manager + +

+

+ + password: managepass + +

+

+

+ Another protected resource is editor_user_only. This one is protected by a different set of permissions. + You will need to be editor with a password of editpass to be able to access it. +

+

+ The last kind of protected resource in this quickstarted app is a full so called secure controller. This controller is protected globally. + Instead of having a @require decorator on each method, we have set an allow_only attribute at the class level. All the methods in this controller will + require the same level of access. You need to be manager to access secc or secc/some_where. +

+
+ + diff --git a/Brie/brie/templates/models/debug.html b/Brie/brie/templates/models/debug.html new file mode 100644 index 0000000..b415a72 --- /dev/null +++ b/Brie/brie/templates/models/debug.html @@ -0,0 +1,20 @@ + + + + + + + + Sample Template, for looking at template locals + + + +

All objects from locals():

+ +
+ ${item}: ${repr(locals()['data'][item])}
+ + diff --git a/Brie/brie/templates/models/error.html b/Brie/brie/templates/models/error.html new file mode 100644 index 0000000..161ad82 --- /dev/null +++ b/Brie/brie/templates/models/error.html @@ -0,0 +1,19 @@ + + + + + + + + A ${code} Error has Occurred + + + +

Error ${code}

+ +
${XML(message)}
+ + \ No newline at end of file diff --git a/Brie/brie/templates/models/footer.html b/Brie/brie/templates/models/footer.html new file mode 100644 index 0000000..1f042cd --- /dev/null +++ b/Brie/brie/templates/models/footer.html @@ -0,0 +1,17 @@ + + + + + diff --git a/Brie/brie/templates/models/header.html b/Brie/brie/templates/models/header.html new file mode 100644 index 0000000..0429cd0 --- /dev/null +++ b/Brie/brie/templates/models/header.html @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/Brie/brie/templates/models/index.html b/Brie/brie/templates/models/index.html new file mode 100644 index 0000000..ddb03aa --- /dev/null +++ b/Brie/brie/templates/models/index.html @@ -0,0 +1,40 @@ + + + + + + + + Welcome to TurboGears 2.0, standing on the + shoulders of giants, since 2007 + + + + ${sidebar_top()} +
+

Presentation

+

TurboGears 2 is rapid web application development toolkit designed to make your life easier.

+
    +
  1. +

    Code your data model

    +

    Design your data model, Create the database, and Add some bootstrap data.

    +
  2. +
  3. +

    Design your URL architecture

    +

    Decide your URLs, Program your controller methods, Design your + templates, and place some static files (CSS and/or JavaScript).

    +
  4. +
  5. +

    Distribute your app

    +

    Test your source, Generate project documents, Build a distribution.

    +
  6. +
+
+
+
Thank you for choosing TurboGears. +
+ + diff --git a/Brie/brie/templates/models/login.html b/Brie/brie/templates/models/login.html new file mode 100644 index 0000000..7095d8a --- /dev/null +++ b/Brie/brie/templates/models/login.html @@ -0,0 +1,24 @@ + + + + + + + +Login Form + + + +
+
+

Login

+
+ + +
+
+ + diff --git a/Brie/brie/templates/models/master.html b/Brie/brie/templates/models/master.html new file mode 100644 index 0000000..e267395 --- /dev/null +++ b/Brie/brie/templates/models/master.html @@ -0,0 +1,44 @@ + + + + + + + + Your title goes here + + + + + + ${header()} + +
+ +
+ Now Viewing: +
+
+ +
+ +
+ + ${footer()} +
+ + diff --git a/Brie/brie/templates/models/sidebars.html b/Brie/brie/templates/models/sidebars.html new file mode 100644 index 0000000..9a8252c --- /dev/null +++ b/Brie/brie/templates/models/sidebars.html @@ -0,0 +1,38 @@ + + + + + + + + + + + diff --git a/Brie/brie/templates/rooms/__init__.py b/Brie/brie/templates/rooms/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Brie/brie/templates/rooms/index.html b/Brie/brie/templates/rooms/index.html new file mode 100644 index 0000000..9998884 --- /dev/null +++ b/Brie/brie/templates/rooms/index.html @@ -0,0 +1,61 @@ + + + + + +
+ +
${"%03d" % stats[name]}
+
+
+ ${display_stat("ok_color")} + ordinateurs connectés +
+
+ ${display_stat("non_certif_color")} + certifs manquants +
+
+ ${display_stat("non_paye_color")} + fins de connexions passées +
+
+ ${display_stat("vide_color")} + chambres vides +
+
+
+ PREVIEW +
+ + + +
+ Ordinateur branché + Violation mac + Ordinateur débranché + Inteface éteinte +
+
+
+
+
+
+ ${("Aile " + area_name).upper()} +
+ étage ${floor_name} + +
+
+
+ diff --git a/Brie/brie/templates/show/__init__.py b/Brie/brie/templates/show/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Brie/brie/templates/show/error.html b/Brie/brie/templates/show/error.html new file mode 100644 index 0000000..0fe9074 --- /dev/null +++ b/Brie/brie/templates/show/error.html @@ -0,0 +1,6 @@ + + ${error} + diff --git a/Brie/brie/templates/show/member.html b/Brie/brie/templates/show/member.html new file mode 100644 index 0000000..89c610b --- /dev/null +++ b/Brie/brie/templates/show/member.html @@ -0,0 +1,23 @@ + + + + + + + +
+ Entrée inexistante +
${member_view(member_ldap)}
+
+
+ Pas de chambre associée +
${room_view(room_ldap)}
+
+
+ Pas d'interface associée +
${interface_view(interface)}
+
+ + diff --git a/Brie/brie/templates/show/member_room_interface_views.html b/Brie/brie/templates/show/member_room_interface_views.html new file mode 100644 index 0000000..3e77d80 --- /dev/null +++ b/Brie/brie/templates/show/member_room_interface_views.html @@ -0,0 +1,133 @@ + + +
+ ${member_ldap.cn.first()} +
+
+ Fin de connexion + + Pas de fin de connexion + ${member_ldap.get("x-connectionEnd").first()} + +
+
+ E-mail + ${member_ldap.mail.first('')} +
+
+ Certificat + + + oui + non + + +
+
+ Commentaire + + + ${member_ldap.get("x-comment").first()} + +
+
+ Cas spécial + + + oui + non + + +
+
+ Wifi +
+
+
+
+ + +
+ CHAMBRE ${room.cn.first()} +
+
+ Membre + + ${member_in.cn.first()} + +
+
+
+
+ + +
+ INFOS INTERFACE +
+
+ Nombre de mac max + ${interface.portsecmaxmac} +
+
+ Violation + ${interface.portsecviolation} +
+
+
+
+ INFOS AVANCÉES +
+
+ ifNumber + ${interface.ifnumber} +
+
+ ifAddress + ${interface.ifaddress} +
+
+ ifType + ${interface.iftype} +
+
+ Description + ${interface.ifdescription} +
+
+ Etat + + Up + Down + Error + Inconnu + +
+
+ Vitesse + + 10 Mb/s + 100 Mb/s + 1 Gb/s + interface.ifspeed + +
+
+ Vlan + ${interface.ifvlan} +
+
+ Native Vlan + ${interface.ifnativevlan} +
+
+ SpanningTree Portfast + ${interface.portfast} +
+
+
+
+ + diff --git a/Brie/brie/templates/show/room.html b/Brie/brie/templates/show/room.html new file mode 100644 index 0000000..7d846c8 --- /dev/null +++ b/Brie/brie/templates/show/room.html @@ -0,0 +1,19 @@ + + + + + + + +
+ Pas de chambre associée +
${room_view(room_ldap, member_ldap)}
+
+
+ Pas d'interface associée +
${interface_view(interface)}
+
+ + diff --git a/Brie/brie/tests/__init__.py b/Brie/brie/tests/__init__.py new file mode 100644 index 0000000..5cf3f37 --- /dev/null +++ b/Brie/brie/tests/__init__.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +"""Unit and functional test suite for Brie.""" + +from os import path +import sys + +from tg import config +from paste.deploy import loadapp +from paste.script.appinstall import SetupCommand +from routes import url_for +from webtest import TestApp +from nose.tools import eq_ + +from brie import model + +__all__ = ['setup_db', 'teardown_db', 'TestController', 'url_for'] + +def setup_db(): + """Method used to build a database""" + engine = config['pylons.app_globals'].sa_engine + model.init_model(engine) + model.metadata.create_all(engine) + +def teardown_db(): + """Method used to destroy a database""" + engine = config['pylons.app_globals'].sa_engine + model.metadata.drop_all(engine) + + +class TestController(object): + """ + Base functional test case for the controllers. + + The Brie application instance (``self.app``) set up in this test + case (and descendants) has authentication disabled, so that developers can + test the protected areas independently of the :mod:`repoze.who` plugins + used initially. This way, authentication can be tested once and separately. + + Check brie.tests.functional.test_authentication for the repoze.who + integration tests. + + This is the officially supported way to test protected areas with + repoze.who-testutil (http://code.gustavonarea.net/repoze.who-testutil/). + + """ + + application_under_test = 'main_without_authn' + + def setUp(self): + """Method called by nose before running each test""" + # Loading the application: + conf_dir = config.here + wsgiapp = loadapp('config:test.ini#%s' % self.application_under_test, + relative_to=conf_dir) + self.app = TestApp(wsgiapp) + # Setting it up: + test_file = path.join(conf_dir, 'test.ini') + cmd = SetupCommand('setup-app') + cmd.run([test_file]) + + def tearDown(self): + """Method called by nose after running each test""" + # Cleaning up the database: + teardown_db() diff --git a/Brie/brie/tests/functional/__init__.py b/Brie/brie/tests/functional/__init__.py new file mode 100644 index 0000000..74b869b --- /dev/null +++ b/Brie/brie/tests/functional/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +"""Functional test suite for the controllers of the application.""" \ No newline at end of file diff --git a/Brie/brie/tests/functional/test_authentication.py b/Brie/brie/tests/functional/test_authentication.py new file mode 100644 index 0000000..5ab04fc --- /dev/null +++ b/Brie/brie/tests/functional/test_authentication.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +""" +Integration tests for the :mod:`repoze.who`-powered authentication sub-system. + +As Brie grows and the authentication method changes, only these tests +should be updated. + +""" + +from brie.tests import TestController + + +class TestAuthentication(TestController): + """ + Tests for the default authentication setup. + + By default in TurboGears 2, :mod:`repoze.who` is configured with the same + plugins specified by repoze.what-quickstart (which are listed in + http://code.gustavonarea.net/repoze.what-quickstart/#repoze.what.plugins.quickstart.setup_sql_auth). + + As the settings for those plugins change, or the plugins are replaced, + these tests should be updated. + + """ + + application_under_test = 'main' + + def test_forced_login(self): + """ + Anonymous users must be redirected to the login form when authorization + is denied. + + Next, upon successful login they should be redirected to the initially + requested page. + + """ + # Requesting a protected area + resp = self.app.get('/secc/', status=302) + assert resp.location.startswith('http://localhost/login') + # Getting the login form: + resp = resp.follow(status=200) + form = resp.form + # Submitting the login form: + form['login'] = u'manager' + form['password'] = 'managepass' + post_login = form.submit(status=302) + # Being redirected to the initially requested page: + assert post_login.location.startswith('http://localhost/post_login') + initial_page = post_login.follow(status=302) + assert 'authtkt' in initial_page.request.cookies, \ + "Session cookie wasn't defined: %s" % initial_page.request.cookies + assert initial_page.location.startswith('http://localhost/secc/'), \ + initial_page.location + + def test_voluntary_login(self): + """Voluntary logins must work correctly""" + # Going to the login form voluntarily: + resp = self.app.get('/login', status=200) + form = resp.form + # Submitting the login form: + form['login'] = u'manager' + form['password'] = 'managepass' + post_login = form.submit(status=302) + # Being redirected to the home page: + assert post_login.location.startswith('http://localhost/post_login') + home_page = post_login.follow(status=302) + assert 'authtkt' in home_page.request.cookies, \ + 'Session cookie was not defined: %s' % home_page.request.cookies + assert home_page.location == 'http://localhost/' + + def test_logout(self): + """Logouts must work correctly""" + # Logging in voluntarily the quick way: + resp = self.app.get('/login_handler?login=manager&password=managepass', + status=302) + resp = resp.follow(status=302) + assert 'authtkt' in resp.request.cookies, \ + 'Session cookie was not defined: %s' % resp.request.cookies + # Logging out: + resp = self.app.get('/logout_handler', status=302) + assert resp.location.startswith('http://localhost/post_logout') + # Finally, redirected to the home page: + home_page = resp.follow(status=302) + assert home_page.request.cookies.get('authtkt') == '', \ + 'Session cookie was not deleted: %s' % home_page.request.cookies + assert home_page.location == 'http://localhost/', home_page.location diff --git a/Brie/brie/tests/functional/test_root.py b/Brie/brie/tests/functional/test_root.py new file mode 100644 index 0000000..4e4a76b --- /dev/null +++ b/Brie/brie/tests/functional/test_root.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +""" +Functional test suite for the root controller. + +This is an example of how functional tests can be written for controllers. + +As opposed to a unit-test, which test a small unit of functionality, +functional tests exercise the whole application and its WSGI stack. + +Please read http://pythonpaste.org/webtest/ for more information. + +""" +from nose.tools import assert_true + +from brie.tests import TestController + + +class TestRootController(TestController): + def test_index(self): + response = self.app.get('/') + msg = 'TurboGears 2 is rapid web application development toolkit '\ + 'designed to make your life easier.' + # You can look for specific strings: + assert_true(msg in response) + + # You can also access a BeautifulSoup'ed response in your tests + # (First run $ easy_install BeautifulSoup + # and then uncomment the next two lines) + + #links = response.html.findAll('a') + #print links + #assert_true(links, "Mummy, there are no links here!") + def test_secc_with_manager(self): + """Only the manager can access the secure controller""" + # Note how authentication is forged: + environ = {'REMOTE_USER': 'manager'} + resp = self.app.get('/secc', extra_environ=environ, status=200) + assert 'Secure Controller here' in resp.body, resp.body + + def test_secc_with_editor(self): + """The editor shouldn't access the secure controller""" + environ = {'REMOTE_USER': 'editor'} + self.app.get('/secc', extra_environ=environ, status=403) + # It's enough to know that authorization was denied with a 403 status + + def test_secc_with_anonymous(self): + """Anonymous users must not access the secure controller""" + self.app.get('/secc', status=401) + # It's enough to know that authorization was denied with a 401 status diff --git a/Brie/brie/tests/models/__init__.py b/Brie/brie/tests/models/__init__.py new file mode 100644 index 0000000..e3078a6 --- /dev/null +++ b/Brie/brie/tests/models/__init__.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +"""Unit test suite for the models of the application.""" +from nose.tools import assert_equals + +from brie.model import DBSession +from brie.tests import setup_db, teardown_db + +__all__ = ['ModelTest'] + +#Create an empty database before we start our tests for this module +def setup(): + """Function called by nose on module load""" + setup_db() + +#Teardown that database +def teardown(): + """Function called by nose after all tests in this module ran""" + teardown_db() + +class ModelTest(object): + """Base unit test case for the models.""" + + klass = None + attrs = {} + + def setup(self): + try: + new_attrs = {} + new_attrs.update(self.attrs) + new_attrs.update(self.do_get_dependencies()) + self.obj = self.klass(**new_attrs) + DBSession.add(self.obj) + DBSession.flush() + return self.obj + except: + DBSession.rollback() + raise + + def tearDown(self): + DBSession.rollback() + + def do_get_dependencies(self): + """Use this method to pull in other objects that need to be created for this object to be build properly""" + return {} + + def test_create_obj(self): + pass + + def test_query_obj(self): + obj = DBSession.query(self.klass).one() + for key, value in self.attrs.iteritems(): + assert_equals(getattr(obj, key), value) diff --git a/Brie/brie/tests/models/test_auth.py b/Brie/brie/tests/models/test_auth.py new file mode 100644 index 0000000..1ba526a --- /dev/null +++ b/Brie/brie/tests/models/test_auth.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +"""Test suite for the TG app's models""" +from nose.tools import eq_ + +from brie import model +from brie.tests.models import ModelTest + +class TestGroup(ModelTest): + """Unit test case for the ``Group`` model.""" + klass = model.Group + attrs = dict( + group_name = u"test_group", + display_name = u"Test Group" + ) + + +class TestUser(ModelTest): + """Unit test case for the ``User`` model.""" + + klass = model.User + attrs = dict( + user_name = u"ignucius", + email_address = u"ignucius@example.org" + ) + + def test_obj_creation_username(self): + """The obj constructor must set the user name right""" + eq_(self.obj.user_name, u"ignucius") + + def test_obj_creation_email(self): + """The obj constructor must set the email right""" + eq_(self.obj.email_address, u"ignucius@example.org") + + def test_no_permissions_by_default(self): + """User objects should have no permission by default.""" + eq_(len(self.obj.permissions), 0) + + def test_getting_by_email(self): + """Users should be fetcheable by their email addresses""" + him = model.User.by_email_address(u"ignucius@example.org") + eq_(him, self.obj) + + +class TestPermission(ModelTest): + """Unit test case for the ``Permission`` model.""" + + klass = model.Permission + attrs = dict( + permission_name = u"test_permission", + description = u"This is a test Description" + ) diff --git a/Brie/brie/websetup.py b/Brie/brie/websetup.py new file mode 100644 index 0000000..b91f462 --- /dev/null +++ b/Brie/brie/websetup.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +"""Setup the Brie application""" + +import logging + +import transaction +from tg import config + +from brie.config.environment import load_environment + +__all__ = ['setup_app'] + +log = logging.getLogger(__name__) + + +def setup_app(command, conf, vars): + """Place any commands to setup brie here""" + load_environment(conf.global_conf, conf.local_conf) + # Load the models + from brie import model + print "Creating tables" + model.metadata.create_all(bind=config['pylons.app_globals'].sa_engine) + + manager = model.User() + manager.user_name = u'manager' + manager.display_name = u'Example manager' + manager.email_address = u'manager@somedomain.com' + manager.password = u'managepass' + + model.DBSession.add(manager) + + group = model.Group() + group.group_name = u'managers' + group.display_name = u'Managers Group' + + group.users.append(manager) + + model.DBSession.add(group) + + permission = model.Permission() + permission.permission_name = u'manage' + permission.description = u'This permission give an administrative right to the bearer' + permission.groups.append(group) + + model.DBSession.add(permission) + + editor = model.User() + editor.user_name = u'editor' + editor.display_name = u'Example editor' + editor.email_address = u'editor@somedomain.com' + editor.password = u'editpass' + + model.DBSession.add(editor) + model.DBSession.flush() + + transaction.commit() + print "Successfully setup" diff --git a/Brie/check_mac_interface.py b/Brie/check_mac_interface.py new file mode 100644 index 0000000..012d6a6 --- /dev/null +++ b/Brie/check_mac_interface.py @@ -0,0 +1,63 @@ +#from paste.deploy import appconfig +#from pylons import config + +#from brie.config.environment import load_environment + +#conf = appconfig('config:development.ini', relative_to='.') +#load_environment(conf.global_conf, conf.local_conf) + +import os +import sys + +from brie.config import ldap_config +from brie.lib.ldap_helper import * +from brie.lib.camembert_helpers import * + +from brie.model import DBSession +from brie.model.camembert import * + +#interface_name = os.environ["NAS_PORT_ID"] +#switch_ip = os.environ["NAS_IP_ADDRESS"] +#mac = os.environ["USERNAME"] + +#bind = Ldap.connect("uid=roven.gabriel," + ldap_config.username_base_dn, "foobar") +bind = Ldap.connect("uid=admin,ou=Administrators,ou=TopologyManagement,o=netscaperoot", "t734DSSL61") + +rooms_base_dn = "ou=chambres,dc=pacaterie,dc=u-psud,dc=fr" + +interface_name = "FastEthernet0/43" +switch_ip = "172.17.24.2" +mac = "000f1f867189" + +rooms = bind.search(rooms_base_dn, "(&(&(objectClass=pacaterieRoom)(x-switchInterface=" + interface_name + ")(x-switch=" + switch_ip + ")))") + + +def roomOrNone(member): + if member.has("roomNumber"): + return member.roomNumber.first() + return None +#end def + + +def isOk(): + for room in rooms: + print room.get("x-switchInterface").first() + if room.has("x-memberIn"): + print room.get("x-memberIn").first() + associated_member_machine = bind.search_first(room.get("x-memberIn").first(), "(uid=" + mac + ")") + print associated_member_machine.uid.first() + return associated_member_machine is not None + #end if + #end for + + return False +#end def + +ok = isOk() + +if ok: + sys.exit(0) +else: + sys.exit(1) + + diff --git a/Brie/devdata.db b/Brie/devdata.db new file mode 100644 index 0000000..e69de29 diff --git a/Brie/development.ini b/Brie/development.ini new file mode 100644 index 0000000..9d75f67 --- /dev/null +++ b/Brie/development.ini @@ -0,0 +1,129 @@ +# +# Brie - Pylons development environment configuration +# +# The %(here)s variable will be replaced with the parent directory of this file +# +# This file is for deployment specific config options -- other configuration +# that is always required for the app is done in the config directory, +# and generally should not be modified by end users. + +[DEFAULT] +debug = true +# Uncomment and replace with the address which should receive any error reports +#email_to = you@yourdomain.com +smtp_server = localhost +error_email_from = paste@localhost + +[server:main] +use = egg:Paste#http +host = 0.0.0.0 +port = 9000 + +[app:main] +use = egg:Brie +full_stack = true +#lang = ru +cache_dir = %(here)s/data +beaker.session.key = brie +beaker.session.secret = somesecret + +# If you'd like to fine-tune the individual locations of the cache data dirs +# for the Cache data, or the Session saves, un-comment the desired settings +# here: +#beaker.cache.data_dir = %(here)s/data/cache +#beaker.session.data_dir = %(here)s/data/sessions + +# pick the form for your database +# %(here) may include a ':' character on Windows environments; this can +# invalidate the URI when specifying a SQLite db via path name +sqlalchemy.url=postgresql://camembert:CamembertDB%40Pacat@archange.pacaterie.u-psud.fr:5432/camembert +# sqlalchemy.url=mysql://username:password@hostname:port/databasename + + +# If you have sqlite, here's a simple default to get you started +# in development + +#sqlalchemy.url = sqlite:///%(here)s/devdata.db +#echo shouldn't be used together with the logging module. +#sqlalchemy.echo = false +#sqlalchemy.echo_pool = false +#sqlalchemy.pool_recycle = 3600 + +# if you are using Mako and want to be able to reload +# the mako template from disk during the development phase +# you should say 'true' here +# This option is only used for mako templating engine +# WARNING: if you want to deploy your application using a zipped egg +# (ie: if your application's setup.py defines zip-safe=True, then you +# MUST put "false" for the production environment because there will +# be no disk and real files to compare time with. +# On the contrary if your application defines zip-safe=False and is +# deployed in an unzipped manner, then you can leave this option to true +templating.mako.reloadfromdisk = true + +# the compiled template dir is a directory that must be readable by your +# webserver. It will be used to store the resulting templates once compiled +# by the TemplateLookup system. +# During development you generally don't need this option since paste's HTTP +# server will have access to you development directories, but in production +# you'll most certainly want to have apache or nginx to write in a directory +# that does not contain any source code in any form for obvious security reasons. +# +#templating.mako.compiled_templates_dir = /some/dir/where/webserver/has/access + +# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* +# Debug mode will enable the interactive debugging tool, allowing ANYONE to +# execute malicious code after an exception is raised. +#set debug = false + +# Logging configuration +# Add additional loggers, handlers, formatters here +# Uses python's logging config file format +# http://docs.python.org/lib/logging-config-fileformat.html + +[loggers] +keys = root, brie, sqlalchemy, auth + +[handlers] +keys = console + +[formatters] +keys = generic + +# If you create additional loggers, add them as a key to [loggers] +[logger_root] +level = INFO +handlers = console + +[logger_brie] +level = DEBUG +handlers = +qualname = brie + +[logger_sqlalchemy] +level = INFO +handlers = +qualname = sqlalchemy.engine +# "level = INFO" logs SQL queries. +# "level = DEBUG" logs SQL queries and results. +# "level = WARN" logs neither. (Recommended for production systems.) + + +# A logger for authentication, identification and authorization -- this is +# repoze.who and repoze.what: +[logger_auth] +level = WARN +handlers = +qualname = auth + +# If you create additional handlers, add them as a key to [handlers] +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +# If you create additional formatters, add them as a key to [formatters] +[formatter_generic] +format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/Brie/ez_setup/README.txt b/Brie/ez_setup/README.txt new file mode 100644 index 0000000..77c986d --- /dev/null +++ b/Brie/ez_setup/README.txt @@ -0,0 +1,14 @@ +This directory exists so that Subversion-based projects can share a single +copy of the ``ez_setup`` bootstrap module for ``setuptools``, and have it +automatically updated in their projects when ``setuptools`` is updated. + +For your convenience, you may use the following svn:externals definition:: + + ez_setup svn://svn.eby-sarna.com/svnroot/ez_setup + +You can set this by executing this command in your project directory:: + + svn propedit svn:externals . + +And then adding the line shown above to the file that comes up for editing. +Then, whenever you update your project, ``ez_setup`` will be updated as well. diff --git a/Brie/ez_setup/__init__.py b/Brie/ez_setup/__init__.py new file mode 100644 index 0000000..ba2c22d --- /dev/null +++ b/Brie/ez_setup/__init__.py @@ -0,0 +1,229 @@ +#!/usr/bin/python +"""Bootstrap setuptools installation + +If you want to use setuptools in your package's setup.py, just include this +file in the same directory with it, and add this to the top of your setup.py:: + + from ez_setup import use_setuptools + use_setuptools() + +If you want to require a specific version of setuptools, set a download +mirror, or use an alternate download directory, you can do so by supplying +the appropriate options to ``use_setuptools()``. + +This file can also be run as a script to install or upgrade setuptools. +""" +import sys +DEFAULT_VERSION = "0.6c7" +DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3] + +md5_data = { + 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca', + 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb', + 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b', + 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a', + 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618', + 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac', + 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5', + 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', + 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', + 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', + 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', + 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', + 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', + 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e', + 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e', + 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f', + 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2', + 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc', + 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167', + 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64', + 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d', + 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20', + 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab', + 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53', + 'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2', + 'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e', + 'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372', +} + +import sys, os + +def _validate_md5(egg_name, data): + if egg_name in md5_data: + from md5 import md5 + digest = md5(data).hexdigest() + if digest != md5_data[egg_name]: + print >>sys.stderr, ( + "md5 validation of %s failed! (Possible download problem?)" + % egg_name + ) + sys.exit(2) + return data + + +def use_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, + download_delay=15 +): + """Automatically find/download setuptools and make it available on sys.path + + `version` should be a valid setuptools version number that is available + as an egg for download under the `download_base` URL (which should end with + a '/'). `to_dir` is the directory where setuptools will be downloaded, if + it is not already available. If `download_delay` is specified, it should + be the number of seconds that will be paused before initiating a download, + should one be required. If an older version of setuptools is installed, + this routine will print a message to ``sys.stderr`` and raise SystemExit in + an attempt to abort the calling script. + """ + try: + import setuptools + if setuptools.__version__ == '0.0.1': + print >>sys.stderr, ( + "You have an obsolete version of setuptools installed. Please\n" + "remove it from your system entirely before rerunning this script." + ) + sys.exit(2) + except ImportError: + egg = download_setuptools(version, download_base, to_dir, download_delay) + sys.path.insert(0, egg) + import setuptools; setuptools.bootstrap_install_from = egg + + import pkg_resources + try: + pkg_resources.require("setuptools>="+version) + + except pkg_resources.VersionConflict, e: + # XXX could we install in a subprocess here? + print >>sys.stderr, ( + "The required version of setuptools (>=%s) is not available, and\n" + "can't be installed while this script is running. Please install\n" + " a more recent version first.\n\n(Currently using %r)" + ) % (version, e.args[0]) + sys.exit(2) + +def download_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, + delay = 15 +): + """Download setuptools from a specified location and return its filename + + `version` should be a valid setuptools version number that is available + as an egg for download under the `download_base` URL (which should end + with a '/'). `to_dir` is the directory where the egg will be downloaded. + `delay` is the number of seconds to pause before an actual download attempt. + """ + import urllib2, shutil + egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) + url = download_base + egg_name + saveto = os.path.join(to_dir, egg_name) + src = dst = None + if not os.path.exists(saveto): # Avoid repeated downloads + try: + from distutils import log + if delay: + log.warn(""" +--------------------------------------------------------------------------- +This script requires setuptools version %s to run (even to display +help). I will attempt to download it for you (from +%s), but +you may need to enable firewall access for this script first. +I will start the download in %d seconds. + +(Note: if this machine does not have network access, please obtain the file + + %s + +and place it in this directory before rerunning this script.) +---------------------------------------------------------------------------""", + version, download_base, delay, url + ); from time import sleep; sleep(delay) + log.warn("Downloading %s", url) + src = urllib2.urlopen(url) + # Read/write all in one block, so we don't create a corrupt file + # if the download is interrupted. + data = _validate_md5(egg_name, src.read()) + dst = open(saveto,"wb"); dst.write(data) + finally: + if src: src.close() + if dst: dst.close() + return os.path.realpath(saveto) + +def main(argv, version=DEFAULT_VERSION): + """Install or upgrade setuptools and EasyInstall""" + + try: + import setuptools + except ImportError: + egg = None + try: + egg = download_setuptools(version, delay=0) + sys.path.insert(0,egg) + from setuptools.command.easy_install import main + return main(list(argv)+[egg]) # we're done here + finally: + if egg and os.path.exists(egg): + os.unlink(egg) + else: + if setuptools.__version__ == '0.0.1': + # tell the user to uninstall obsolete version + use_setuptools(version) + + req = "setuptools>="+version + import pkg_resources + try: + pkg_resources.require(req) + except pkg_resources.VersionConflict: + try: + from setuptools.command.easy_install import main + except ImportError: + from easy_install import main + main(list(argv)+[download_setuptools(delay=0)]) + sys.exit(0) # try to force an exit + else: + if argv: + from setuptools.command.easy_install import main + main(argv) + else: + print "Setuptools version",version,"or greater has been installed." + print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' + + + +def update_md5(filenames): + """Update our built-in md5 registry""" + + import re + from md5 import md5 + + for name in filenames: + base = os.path.basename(name) + f = open(name,'rb') + md5_data[base] = md5(f.read()).hexdigest() + f.close() + + data = [" %r: %r,\n" % it for it in md5_data.items()] + data.sort() + repl = "".join(data) + + import inspect + srcfile = inspect.getsourcefile(sys.modules[__name__]) + f = open(srcfile, 'rb'); src = f.read(); f.close() + + match = re.search("\nmd5_data = {\n([^}]+)}", src) + if not match: + print >>sys.stderr, "Internal error!" + sys.exit(2) + + src = src[:match.start(1)] + repl + src[match.end(1):] + f = open(srcfile,'w') + f.write(src) + f.close() + + +if __name__=='__main__': + if len(sys.argv)>2 and sys.argv[1]=='--md5update': + update_md5(sys.argv[2:]) + else: + main(sys.argv[1:]) diff --git a/Brie/fo b/Brie/fo new file mode 100644 index 0000000..f5c67a0 --- /dev/null +++ b/Brie/fo @@ -0,0 +1,1168 @@ +Boubakar OUATTARA +boubakar.ouattara +chambre 456 etage 4 aile nord +Boubakar OUATTARA +Tocha ZAABAY +tocha.zaabay +chambre 465 etage 4 aile nord +Tocha ZAABAY +Claude ALGOURDIN +claude.algourdin +chambre 418 etage 4 aile sud +Claude ALGOURDIN +Rachid CHEDRA +rachid.chedra +chambre 217 etage 2 aile sud +Rachid CHEDRA +Guillaume LETOUPIN +guillaume.letoupin +chambre 232 etage 2 aile sud +Guillaume LETOUPIN +erica MINUZ +erica.minuz +chambre 374 etage 3 aile nord +Erica MINUZ +FLAVIA MACHADO DOMINGUES +flavia.machadodomingue +chambre 452 etage 4 aile nord +flavia.machadodomingue not found +SOPHIA ID SALAH +sophia.idsalah +chambre 360 etage 3 aile nord +Sophia ID SALAH +Marie-Thérèse DIèNE +marie-therese.diene +chambre 54 etage 0 aile nord +Marie-Thérèse DIENE +Paul COULEAUD +paul.couleaud +chambre 178 etage 1 aile nord +Paul COULEAUD +Kevin CHATELAIN +kevin.chatelain +chambre 222 etage 2 aile sud +Kevin CHATELAIN +Nicolas MORUZZI +nicolas.moruzzi +chambre 11 etage 0 aile sud +Nicolas MORUZZI +azeddine BENSABER +azeddine.bensaber +chambre 320 etage 3 aile sud +Azeddine BENSABER +mohammed KEBDANI +mohammed.kebdani +chambre 472 etage 4 aile nord +Mohammed KEBDANI +Diviya RAMAMURTHY +diviya.ramamurthy +chambre 102 etage 1 aile sud +Diviya RAMAMURTHY +Romain VAUTIER PHEMIUS +romain.vautierphemius +chambre 109 etage 1 aile sud +Romain VAUTIER PHEMIUS +nguyen DANG +nguyen.dang +chambre 224 etage 2 aile sud +Nguyen DANG +Julienne Rose DIENE +juliennerose.diene +chambre 52 etage 0 aile nord +juliennerose.diene not found +Sam SAN +sam.san +chambre 69 etage 0 aile nord +Sam SAN +Thi Bach Tuyet DANG +thibachtuyet.dang +chambre 226 etage 2 aile sud +thibachtuyet.dang not found +Oirdate NARIVELO +oirdate.narivelo +chambre 319 etage 3 aile sud +Oirdate NARIVELO +oussama DOUAK +oussama.douak +chambre 9 etage 0 aile sud +Oussama DOUAK +Alexandre RACIONERO +alexandre.racionero +chambre 501 etage 5 aile sud +alexandre.racionero not found +Carmen HUYNH +carmen.huynh +chambre 106 etage 1 aile sud +Carmen HUYNH +Jonas ALTNöDER +jonas.altnoder +chambre 220 etage 2 aile sud +jonas.altnoder not found +SARRA BENDIOURI +sarra.bendiouri +chambre 227 etage 2 aile sud +Sarra BENDIOURI +Stephen MELCZER +stephen.melczer +chambre 270 etage 2 aile nord +Stephen MELCZER +Soren RAVN +soren.ravn +chambre 325 etage 3 aile sud +Soren RAVN +nassim BACHIR BEY +nassim.bachirbey +chambre 26 etage 0 aile sud +Nassim BACHIR BEY +Dimitri TEIXEIRA PIRES +dimitri.teixeirapires +chambre 216 etage 2 aile sud +Dimitri TEIXEIRA PIRES +Christelle RECTON +christelle.recton +chambre 301 etage 3 aile sud +christelle.recton not found +Chevelle CINEAS +chevelle.cineas +chambre 164 etage 1 aile nord +Chevelle CINEAS +victor ILUTA +victor.iluta +chambre 377 etage 3 aile nord +Victor ILUTA +héloise GIRAUD +heloise.giraud +chambre 279 etage 2 aile nord +heloise.giraud not found +Alessandro VALLEE +alessandro.vallee +chambre 306 etage 3 aile sud +Alessandro VALLEE +Ioana Alexandra ROATIS +ioanaalexandra.roatis +chambre 203 etage 2 aile sud +ioanaalexandra.roatis not found +sophia SABOR +sophia.sabor +chambre 210 etage 2 aile sud +Sophia SABOR +Jing WANG +jing.wang +chambre 312 etage 3 aile sud +Jing WANG +badr BENNANIBAITI +badr.bennanibaiti +chambre 426 etage 4 aile sud +Badr BENNANIBAITI +Vincent YAHIA +vincent.yahia +chambre 104 etage 1 aile sud +Vincent YAHIA +Rolando Rafael LOZADA GARCIA +rolandorafael.lozadagarcia +chambre 307 etage 3 aile sud +Rolando Rafael LOZADA GARCIA +Van anh LE THI +vananh.lethi +chambre 313 etage 3 aile sud +Van Anh LE THI +Matilda ROUGIEUX +matilda.rougieux +chambre 372 etage 3 aile nord +Matilda ROUGIEUX +Margareta Cristina BALOGH +margaretacristi.balogh +chambre 110 etage 1 aile sud +Margareta Cristina BALOGH +agathe VATONNE +agathe.vatonne +chambre 315 etage 3 aile sud +Agathe VATONNE +Etienne CANTIN +etienne.cantin +chambre 7 etage 0 aile sud +Etienne CANTIN +Benjamin SEZNEC +benjamin.seznec +chambre 118 etage 1 aile sud +Benjamin SEZNEC +Brice AGNES +brice.agnes +chambre 209 etage 2 aile sud +Brice AGNES +David BINA +david.bina +chambre 221 etage 2 aile sud +David BINA +ADRIEN BENEZECH +adrien.benezech +chambre 317 etage 3 aile sud +Adrien BENEZECH +Anaïs PAUVERT +anais.pauvert +chambre 53 etage 0 aile nord +Ana��s PAUVERT +RAYHANA ZIARA +rayhana.ziara +chambre 121 etage 1 aile sud +Rayhana ZIARA +Alexandre BESNARD +alexandre.besnard +chambre 126 etage 1 aile sud +Alexandre BESNARD +Peter-Michaël RICHARD +peter-michael.richard +chambre 316 etage 3 aile sud +peter-michael.richard not found +Dimitri EBRARD +dimitri.ebrard +chambre 318 etage 3 aile sud +Dimitri EBRARD +mohammed BELKHIR +mohammed.belkhir +chambre 327 etage 3 aile sud +Mohammed BELKHIR +Gladys SOUCERADJOU +gladys.souceradjou +chambre 127 etage 1 aile sud +Gladys SOUCERADJOU +Elise BASSO-BLANDIN +elise.basso-blandin +chambre 153 etage 1 aile nord +elise.basso-blandin not found +Mehdi LANGLOIS +mehdi.langlois +chambre 368 etage 3 aile nord +Mehdi LANGLOIS +Abdou Rahmane DIAW +abdourahmane.diaw +chambre 167 etage 1 aile nord +Abdou Rahmane DIAW +Thomas SOHIER +thomas.sohier +chambre 128 etage 1 aile sud +Thomas SOHIER +Li CHEN +li.chen +chambre 223 etage 2 aile sud +Li CHEN +Sara HAFSA +sara.hafsa +chambre 401 etage 4 aile sud +Sara HAFSA +Nelson PEREIRA +nelson.pereira +chambre 10 etage 0 aile sud +Nelson PEREIRA +Roven GABRIEL +roven.gabriel +chambre 268 etage 2 aile nord +Roven GABRIEL +Francesca BERGAMASCHI +francesca.bergamaschi +chambre 430 etage 4 aile sud +Francesca BERGAMASCHI +GUILLAUME BONANNI +guillaume.bonanni +chambre 19 etage 0 aile sud +guillaume.bonanni not found +Benjamin SATURNIN +benjamin.saturnin +chambre 131 etage 1 aile sud +Benjamin SATURNIN +Aurore SIBRANT +aurore.sibrant +chambre 420 etage 4 aile sud +Aurore SIBRANT +Wafa REKIK +wafa.rekik +chambre 177 etage 1 aile nord +Wafa REKIK +xin LUO +xin.luo +chambre 204 etage 2 aile sud +Xin LUO +Imen GHOURABI +imen.ghourabi +chambre 205 etage 2 aile sud +Imen GHOURABI +Aziz DZIRI +aziz.dziri +chambre 305 etage 3 aile sud +Aziz DZIRI +Wassim BEN MAMOUDA +wassim.benmamouda +chambre 15 etage 0 aile sud +wassim.benmamouda not found +Huizi JIANG +huizi.jiang +chambre 70 etage 0 aile nord +Huizi JIANG +Javier GOMEZ +javier.gomez +chambre 56 etage 0 aile nord +Javier GOMEZ +thomas TROILO +thomas.troilo +chambre 252 etage 2 aile nord +Thomas TROILO +Rolando Raphaël LORADA GARCIA +rolandoraphael.loradagarcia +chambre 260 etage 2 aile nord +rolandoraphael.loradagarcia not found +tayyab RAMZAN +tayyab.ramzan +chambre 17 etage 0 aile sud +Tayyab RAMZAN +wojciech ZAREMBA +wojciech.zaremba +chambre 18 etage 0 aile sud +Wojciech ZAREMBA +Thanh Long NGUYEN +thanhlong.nguyen +chambre 20 etage 0 aile sud +thanhlong.nguyen not found +Krystelle EURANIE +krystelle.euranie +chambre 23 etage 0 aile sud +Krystelle EURANIE +Laure PEDECHES +laure.pedeches +chambre 27 etage 0 aile sud +Laure PEDECHES +Nicolas TRAN +nicolas.tran +chambre 101 etage 1 aile sud +Nicolas TRAN +Jean-Michel TRINH +jean-michel.trinh +chambre 103 etage 1 aile sud +Jean-michel TRINH +nicolas THELLYERE +nicolas.thellyere +chambre 111 etage 1 aile sud +Nicolas THELLYERE +Alexis TAINE +alexis.taine +chambre 129 etage 1 aile sud +Alexis TAINE +Svetlana PROKOPENKO +svetlana.prokopenko +chambre 365 etage 3 aile nord +Svetlana PROKOPENKO +Alexandre DESROCHES +alexandre.desroches +chambre 409 etage 4 aile sud +Alexandre DESROCHES +Younès TIERCE +younes.tierce +chambre 133 etage 1 aile sud +Youn��s TIERCE +carina STRITT +carina.stritt +chambre 132 etage 1 aile sud +Carina STRITT +Mustapha KHEDHIRI +mustapha.khedhiri +chambre 211 etage 2 aile sud +Mustapha KHEDHIRI +Jordan BOUAZIZ +jordan.bouaziz +chambre 228 etage 2 aile sud +Jordan BOUAZIZ +Anthony LARROQUE +anthony.larroque +chambre 231 etage 2 aile sud +Anthony LARROQUE +Loïc GOUSSEFF +loic.gousseff +chambre 304 etage 3 aile sud +Lo��c GOUSSEFF +Sophie VéRITé +sophie.verite +chambre 502 etage 5 aile sud +sophie.verite not found +Alexandre AUDIC +alexandre.audic +chambre 156 etage 1 aile nord +Alexandre AUDIC +José PEDROSA AGUILAR +jose.pedrosaaguilar +chambre 14 etage 0 aile sud +jose.pedrosaaguilar not found +Soulimane CHEVALIER +soulimane.chevalier +chambre 321 etage 3 aile sud +Soulimane CHEVALIER +Joaquin ARANCIBIA-NUESCH +joaquin.arancibia-nuesc +chambre 281 etage 2 aile nord +Joaquin ARANCIBIA-NUESCH +Mascitti GIADA REGINA ANASTASIA +mascitti.giadareginaanas +chambre 13 etage 0 aile sud +Mascitti GIADA REGINA ANASTASIA +Wasilij BARSUKOW +wasilij.barsukow +chambre 6 etage 0 aile sud +Wasilij BARSUKOW +Caroline HENEKA +caroline.heneka +chambre 166 etage 1 aile nord +Caroline HENEKA +dorine BRETON +dorine.breton +chambre 271 etage 2 aile nord +Dorine BRETON +Remy BREGAND +remy.bregand +chambre 273 etage 2 aile nord +Remy BREGAND +Gizem OKYAY +gizem.okyay +chambre 175 etage 1 aile nord +Gizem OKYAY +Florent BEILLONNET +florent.beillonnet +chambre 170 etage 1 aile nord +Florent BEILLONNET +Aurelien CHEUTON +aurelien.cheuton +chambre 264 etage 2 aile nord +Aurelien CHEUTON +Arnaud BAGUET +arnaud.baguet +chambre 259 etage 2 aile nord +Arnaud BAGUET +Charlène FEURJOUR +charlene.feurjour +chambre 71 etage 0 aile nord +charlene.feurjour not found +Jimmy PAROT +jimmy.parot +chambre 274 etage 2 aile nord +Jimmy PAROT +Christine LE GURUN +christine.legurun +chambre 261 etage 2 aile nord +Christine LE GURUN +Anthony AMISSE +anthony.amisse +chambre 159 etage 1 aile nord +Anthony AMISSE +Vijayakumar PANNIRSELVAME +vijayakumar.pannirselvame +chambre 471 etage 4 aile nord +Vijayakumar PANNIRSELVAME +Julien RENé +julien.rene +chambre 16 etage 0 aile sud +Julien REN�� +Hicham OUKROUM +hicham.oukroum +chambre 65 etage 0 aile nord +Hicham OUKROUM +Nils HAUG +nils.haug +chambre 66 etage 0 aile nord +Nils HAUG +Li SCHENGCHUN +li.schengchun +chambre 269 etage 2 aile nord +Li SCHENGCHUN +Nicolas FOURRIER +nicolas.fourrier +chambre 180 etage 1 aile nord +Nicolas FOURRIER +Yu SONG +yu.song +chambre 262 etage 2 aile nord +Yu SONG +Dominique LAFFITTE +dominique.laffitte +chambre 107 etage 1 aile sud +Dominique LAFFITTE +Thomas LEVASSEUR +thomas.levasseur +chambre 114 etage 1 aile sud +Thomas LEVASSEUR +Asma ASLAM +asma.aslam +chambre 258 etage 2 aile nord +Asma ASLAM +Maros HREBIK +maros.hrebik +chambre 432 etage 4 aile sud +Maros HREBIK +Maud GLANDIER +maud.glandier +chambre 117 etage 1 aile sud +Maud GLANDIER +Yolanda OHENE +yolanda.ohene +chambre 124 etage 1 aile sud +Yolanda OHENE +jessica SPAKE +jessica.spake +chambre 171 etage 1 aile nord +Jessica SPAKE +Anton ABYZOV +anton.abyzov +chambre 277 etage 2 aile nord +Anton ABYZOV +Tekkanat SEDA +tekkanat.seda +chambre 421 etage 4 aile sud +Tekkanat SEDA +Catriona ROWBURY +catriona.rowbury +chambre 130 etage 1 aile sud +Catriona ROWBURY +Sarah MARIANI +sarah.mariani +chambre 233 etage 2 aile sud +Sarah MARIANI +Yohan BATAILLE +yohan.bataille +chambre 58 etage 0 aile nord +Yohan BATAILLE +Huang GUAN +huang.guan +chambre 212 etage 2 aile sud +Huang GUAN +sandra LAGREULET +sandra.lagreulet +chambre 230 etage 2 aile sud +Sandra LAGREULET +Julien JOLIE +julien.jolie +chambre 369 etage 3 aile nord +Julien JOLIE +Robin LE PENGLAU +robin.lepenglau +chambre 302 etage 3 aile sud +Robin LE PENGLAU +Yakine BAHRI +yakine.bahri +chambre 303 etage 3 aile sud +Yakine BAHRI +Virginie DUQUESNEL +virginie.duquesnel +chambre 309 etage 3 aile sud +Virginie DUQUESNEL +Jessica MAMERI +jessica.mameri +chambre 310 etage 3 aile sud +Jessica MAMERI +Denis LAZARENKO +denis.lazarenko +chambre 311 etage 3 aile sud +Denis LAZARENKO +quentin GODIAU +quentin.godiau +chambre 256 etage 2 aile nord +Quentin GODIAU +Benjamin LELOUTRE +benjamin.leloutre +chambre 416 etage 4 aile sud +Benjamin LELOUTRE +Cassandre DI PASCALE +cassandre.dipascale +chambre 414 etage 4 aile sud +Cassandre DI PASCALE +Timothée KOOYMAN +timothee.kooyman +chambre 467 etage 4 aile nord +timothee.kooyman not found +Mathias LELOUTRE +mathias.leloutre +chambre 417 etage 4 aile sud +Mathias LELOUTRE +Claire PILOT +claire.pilot +chambre 461 etage 4 aile nord +Claire PILOT +Vincent ING +vincent.ing +chambre 371 etage 3 aile nord +Vincent ING +Corina PANDA +corina.panda +chambre 382 etage 3 aile nord +Corina PANDA +Florian JOLIVET +florian.jolivet +chambre 364 etage 3 aile nord +Florian JOLIVET +Romain DAUVERD +romain.dauverd +chambre 458 etage 4 aile nord +Romain DAUVERD +Aurelie DORVAL +aurelie.dorval +chambre 469 etage 4 aile nord +Aurelie DORVAL +Lucille FOSSIER +lucille.fossier +chambre 468 etage 4 aile nord +Lucille FOSSIER +Claude SANZ +claude.sanz +chambre 151 etage 1 aile nord +Claude SANZ +Ruben Duplex TIMNOU FANKEM +rubenduplex.timnoufankem +chambre 351 etage 3 aile nord +Ruben Duplex TIMNOU FANKEM +Guillermo GOMEZ BELLA +guillermo.gomezbella +chambre 470 etage 4 aile nord +Guillermo GOMEZ BELLA +Jean-Benoit JOUJOUTE +jean-benoit.joujoute +chambre 383 etage 3 aile nord +Jean-benoit JOUJOUTE +Yani DANIEL +yani.daniel +chambre 323 etage 3 aile sud +Yani DANIEL +Ophélie FOUCAULT-LORIEUX +ophelie.foucault-lorieu +chambre 352 etage 3 aile nord +ophelie.foucault-lorieu not found +Olivia DA CONCEICAO +olivia.daconceicao +chambre 366 etage 3 aile nord +Olivia DA CONCEICAO +Marylou MAURAS +marylou.mauras +chambre 428 etage 4 aile sud +Marylou MAURAS +Yi HUANG +yi.huang +chambre 168 etage 1 aile nord +Yi HUANG +Nadya MLIKI +nadya.mliki +chambre 62 etage 0 aile nord +Nadya MLIKI +THIERRY ALBERTIN +thierry.albertin +chambre 160 etage 1 aile nord +Thierry ALBERTIN +Leonard BOUVERET +leonard.bouveret +chambre 68 etage 0 aile nord +Leonard BOUVERET +Sebastien HENRY +sebastien.henry +chambre 157 etage 1 aile nord +Sebastien HENRY +Iurii TIMROV +iurii.timrov +chambre 410 etage 4 aile sud +Iurii TIMROV +Lamoth ORN +lamoth.orn +chambre 474 etage 4 aile nord +Lamoth ORN +Marine DUHAMEL +marine.duhamel +chambre 462 etage 4 aile nord +Marine DUHAMEL +gaetan HERMANT +gaetan.hermant +chambre 158 etage 1 aile nord +Gaetan HERMANT +Kenny BROGUY +kenny.broguy +chambre 354 etage 3 aile nord +Kenny BROGUY +Baher MAWLAWI +baher.mawlawi +chambre 402 etage 4 aile sud +Baher MAWLAWI +Hadrien THOMAS +hadrien.thomas +chambre 454 etage 4 aile nord +Hadrien THOMAS +Ronan JOUSSAIN +ronan.joussain +chambre 108 etage 1 aile sud +Ronan JOUSSAIN +Angelo ANDREAZZOLI +angelo.andreazzoli +chambre 115 etage 1 aile sud +Angelo ANDREAZZOLI +Sebastien FOUQUET +sebastien.fouquet +chambre 152 etage 1 aile nord +Sebastien FOUQUET +Marion BINDE +marion.binde +chambre 254 etage 2 aile nord +Marion BINDE +Vanessa RIFFET +vanessa.riffet +chambre 122 etage 1 aile sud +Vanessa RIFFET +Pierre MILLE +pierre.mille +chambre 201 etage 2 aile sud +Pierre MILLE +Benjamin GROUX +benjamin.groux +chambre 457 etage 4 aile nord +Benjamin GROUX +Tracy OBAM +tracy.obam +chambre 55 etage 0 aile nord +Tracy OBAM +Maxence DESCHEEMAECKER +maxence.descheemaecker +chambre 460 etage 4 aile nord +Maxence DESCHEEMAECKER +Bertrand MIROUX +bertrand.miroux +chambre 213 etage 2 aile sud +Bertrand MIROUX +hugues ASOFA ZEUFACK +hugues.asofazeufack +chambre 229 etage 2 aile sud +Hugues ASOFA ZEUFACK +Jean-Francois LEMAITRE +jean-francois.lemaitre +chambre 358 etage 3 aile nord +Jean-francois LEMAITRE +Leprince MBEMBA +leprince.mbemba +chambre 359 etage 3 aile nord +Leprince MBEMBA +Basile JUDE +basile.jude +chambre 63 etage 0 aile nord +Basile JUDE +Felaniaina RAKOTOVAO +felaniaina.rakotovao +chambre 415 etage 4 aile sud +Felaniaina RAKOTOVAO +Mickael VARLET +mickael.varlet +chambre 357 etage 3 aile nord +Mickael VARLET +Coralie MERLE +coralie.merle +chambre 480 etage 4 aile nord +Coralie MERLE +Perrine SOUDAIN +perrine.soudain +chambre 61 etage 0 aile nord +Perrine SOUDAIN +Isabelle ROUANET +isabelle.rouanet +chambre 263 etage 2 aile nord +Isabelle ROUANET +Nguyen LE +nguyen.le +chambre 251 etage 2 aile nord +Nguyen LE +Vincent VASSOUT +vincent.vassout +chambre 459 etage 4 aile nord +Vincent VASSOUT +Julien GRANET +julien.granet +chambre 425 etage 4 aile sud +Julien GRANET +Rannda CHEA +rannda.chea +chambre 267 etage 2 aile nord +Rannda CHEA +MATTHIEU KIEFFER +matthieu.kieffer +chambre 481 etage 4 aile nord +Matthieu KIEFFER +Lin SHUN-HUA +lin.shun-hua +chambre 253 etage 2 aile nord +Lin SHUN-HUA +Denis MIñAVORO +denis.minavoro +chambre 408 etage 4 aile sud +denis.minavoro not found +erwan CHEVALIER +erwan.chevalier +chambre 362 etage 3 aile nord +Erwan CHEVALIER +Rustom AL DIKA +rustom.aldika +chambre 422 etage 4 aile sud +Rustom AL DIKA +Guillaume MAGNIEZ +guillaume.magniez +chambre 22 etage 0 aile sud +Guillaume MAGNIEZ +Nicolas DEMOULIN +nicolas.demoulin +chambre 275 etage 2 aile nord +Nicolas DEMOULIN +Sivasangari NANDY +sivasangari.nandy +chambre 112 etage 1 aile sud +Sivasangari NANDY +Simon ANDRIEU +simon.andrieu +chambre 431 etage 4 aile sud +Simon ANDRIEU +Nolwenn GODEAU +nolwenn.godeau +chambre 64 etage 0 aile nord +Nolwenn GODEAU +Alexandre LOPES MEDA +alexandre.lopesmeda +chambre 113 etage 1 aile sud +Alexandre LOPES MEDA +Clémence SALOU +clemence.salou +chambre 119 etage 1 aile sud +clemence.salou not found +Cedic BEIX +cedic.beix +chambre 202 etage 2 aile sud +Cedic BEIX +alexandre DESTANNES +alexandre.destannes +chambre 1 etage 0 aile sud +Alexandre DESTANNES +JING RU +jing.ru +chambre 373 etage 3 aile nord +Jing RU +kenza LAHCENE +kenza.lahcene +chambre 206 etage 2 aile sud +Kenza LAHCENE +Chao SONG +chao.song +chambre 328 etage 3 aile sud +Chao SONG +Elodie LEFEBVRE-AGNES +elodie.lefebvre-agnes +chambre 207 etage 2 aile sud +Elodie LEFEBVRE-AGNES +cyrielle MOAL +cyrielle.moal +chambre 266 etage 2 aile nord +Cyrielle MOAL +Audrey ADAM +audrey.adam +chambre 208 etage 2 aile sud +Audrey ADAM +THANH BINH NGUYEN +thanhbinh.nguyen +chambre 214 etage 2 aile sud +Thanh Binh NGUYEN +Cyrille MVOUM MINAM +cyrille.mvoumminam +chambre 215 etage 2 aile sud +Cyrille MVOUM MINAM +NATHANAEL MASRI +nathanael.masri +chambre 179 etage 1 aile nord +Nathanael MASRI +marta PIEROPAN +marta.pieropan +chambre 161 etage 1 aile nord +Marta PIEROPAN +MAX GODARD +max.godard +chambre 218 etage 2 aile sud +Max GODARD +Djidi TRAORE +djidi.traore +chambre 429 etage 4 aile sud +Djidi TRAORE +Coraline HOSSEPIED +coraline.hossepied +chambre 219 etage 2 aile sud +Coraline HOSSEPIED +Ilja KEMPF +ilja.kempf +chambre 225 etage 2 aile sud +Ilja KEMPF +Bruno DUISIT +bruno.duisit +chambre 367 etage 3 aile nord +Bruno DUISIT +rachida EL MOUKTAFI +rachida.elmouktafi +chambre 463 etage 4 aile nord +Rachida EL MOUKTAFI +Loic DUPONT +loic.dupont +chambre 51 etage 0 aile nord +Loic DUPONT +Quoc Dat PHAM +quocdat.pham +chambre 283 etage 2 aile nord +Quoc Dat PHAM +Gwenaël NORMAND +gwenael.normand +chambre 314 etage 3 aile sud +Gwena��l NORMAND +Lydia DECHAUX +lydia.dechaux +chambre 381 etage 3 aile nord +Lydia DECHAUX +Aris TRITAS +aris.tritas +chambre 407 etage 4 aile sud +Aris TRITAS +Johan PAIOLA +johan.paiola +chambre 412 etage 4 aile sud +Johan PAIOLA +Benfattoum YOUGHOURTA +benfattoum.youghourta +chambre 172 etage 1 aile nord +Benfattoum YOUGHOURTA +adrian ZENTENO GUTIERREZ +adrian.zentenogutierre +chambre 479 etage 4 aile nord +Adrian ZENTENO GUTIERREZ +Xiaolu TAN +xiaolu.tan +chambre 376 etage 3 aile nord +Xiaolu TAN +Cecile TRAENDLIN +cecile.traendlin +chambre 406 etage 4 aile sud +Cecile TRAENDLIN +Justine SOUBRET +justine.soubret +chambre 162 etage 1 aile nord +Justine SOUBRET +ataulfo ANTON +ataulfo.anton +chambre 476 etage 4 aile nord +Ataulfo ANTON +Yanick Blaise Olivier ATEBA BETANDA +yanickblaiseoli.atebabetanda +chambre 370 etage 3 aile nord +Yanick Blaise Olivier ATEBA BETANDA +Christelle TCHALLA +christelle.tchalla +chambre 403 etage 4 aile sud +Christelle TCHALLA +Fabien BINI +fabien.bini +chambre 272 etage 2 aile nord +Fabien BINI +Olivier MAYHEW +olivier.mayhew +chambre 423 etage 4 aile sud +Olivier MAYHEW +Julie MARY +julie.mary +chambre 67 etage 0 aile nord +Julie MARY +Nassima NEKAA +nassima.nekaa +chambre 375 etage 3 aile nord +Nassima NEKAA +Sonny LION +sonny.lion +chambre 280 etage 2 aile nord +Sonny LION +Marwan GHRAB +marwan.ghrab +chambre 482 etage 4 aile nord +Marwan GHRAB +Audrey PORQUET +audrey.porquet +chambre 282 etage 2 aile nord +Audrey PORQUET +Fernando EZQUERRO +fernando.ezquerro +chambre 57 etage 0 aile nord +Fernando EZQUERRO +walid GHABBOUN +walid.ghabboun +chambre 473 etage 4 aile nord +Walid GHABBOUN +Ilias ARHOUN +ilias.arhoun +chambre 475 etage 4 aile nord +Ilias ARHOUN +Alexandre FORM +alexandre.form +chambre 12 etage 0 aile sud +Alexandre FORM +Myriam MONTIER +myriam.montier +chambre 163 etage 1 aile nord +Myriam MONTIER +zhihao CEN +zhihao.cen +chambre 379 etage 3 aile nord +Zhihao CEN +Alain THEVARAJAH +alain.thevarajah +chambre 326 etage 3 aile sud +Alain THEVARAJAH +Marie BOUYX +marie.bouyx +chambre 276 etage 2 aile nord +Marie BOUYX +Remy BESOGNET +remy.besognet +chambre 265 etage 2 aile nord +Remy BESOGNET +Andrei Ioath CHIRIAC +andreiioath.chiriac +chambre 3 etage 0 aile sud +Andrei Ioath CHIRIAC +lucas DA COSTA +lucas.dacosta +chambre 451 etage 4 aile nord +Lucas DA COSTA +marija VOSTINAR +marija.vostinar +chambre 154 etage 1 aile nord +Marija VOSTINAR +aleksandar GOSTOJIC +aleksandar.gostojic +chambre 155 etage 1 aile nord +Aleksandar GOSTOJIC +Arnaud GOLERET +arnaud.goleret +chambre 353 etage 3 aile nord +Arnaud GOLERET +STEVE SAVY +steve.savy +chambre 427 etage 4 aile sud +Steve SAVY +STEPHANIE HAJIW +stephanie.hajiw +chambre 478 etage 4 aile nord +Stephanie HAJIW +Felix LELIEVRE +felix.lelievre +chambre 330 etage 3 aile sud +Felix LELIEVRE +Louis GUERMONPREZ +louis.guermonprez +chambre 455 etage 4 aile nord +Louis GUERMONPREZ +Anthony PRUD HOMME +anthony.prudhomme +chambre 4 etage 0 aile sud +Anthony PRUD HOMME +benoit VARACHE +benoit.varache +chambre 322 etage 3 aile sud +Benoit VARACHE +Thibaut COLNE +thibaut.colne +chambre 363 etage 3 aile nord +Thibaut COLNE +Jong woo JIN +jongwoo.jin +chambre 329 etage 3 aile sud +Jong Woo JIN +Adeline RAUSCH +adeline.rausch +chambre 331 etage 3 aile sud +Adeline RAUSCH +xavier BLOT +xavier.blot +chambre 278 etage 2 aile nord +Xavier BLOT +Jonathan BICHEUX +jonathan.bicheux +chambre 332 etage 3 aile sud +Jonathan BICHEUX +Christophe RAIMBAULT +christophe.raimbault +chambre 466 etage 4 aile nord +Christophe RAIMBAULT +Sarah ALLOUCHE +sarah.allouche +chambre 60 etage 0 aile nord +Sarah ALLOUCHE +Bao LE MINH +bao.leminh +chambre 433 etage 4 aile sud +Bao LE MINH +Tristan SIMEON +tristan.simeon +chambre 176 etage 1 aile nord +Tristan SIMEON +anais RODRIGUES +anais.rodrigues +chambre 333 etage 3 aile sud +Anais RODRIGUES +Thibaut THEVENET +thibaut.thevenet +chambre 404 etage 4 aile sud +Thibaut THEVENET +TIEN HIEN NGUYEN +tienhien.nguyen +chambre 453 etage 4 aile nord +Tien Hien NGUYEN +Sebastien CLEUET +sebastien.cleuet +chambre 361 etage 3 aile nord +Sebastien CLEUET +jaime ARANCIBIA +jaime.arancibia +chambre 165 etage 1 aile nord +Jaime ARANCIBIA +BASTIEN CHASSARD +bastien.chassard +chambre 477 etage 4 aile nord +Bastien CHASSARD +rachid BOUDERKA +rachid.bouderka +chambre 483 etage 4 aile nord +Rachid BOUDERKA +HUANG XIAOGUANG +huang.xiaoguang +chambre 411 etage 4 aile sud +Huang XIAOGUANG +Aymen FAKHREDDINE +aymen.fakhreddine +chambre 257 etage 2 aile nord +Aymen FAKHREDDINE +Shaineze BENSALEM +shaineze.bensalem +chambre 380 etage 3 aile nord +Shaineze BENSALEM +Jonathan LE GOUESTRE +jonathan.legouestre +chambre 405 etage 4 aile sud +Jonathan LE GOUESTRE +soufiyan WAHAB +soufiyan.wahab +chambre 424 etage 4 aile sud +Soufiyan WAHAB +Marvin EUSTACHE +marvin.eustache +chambre 21 etage 0 aile sud +Marvin EUSTACHE +Fabrice PICARD +fabrice.picard +chambre 24 etage 0 aile sud +Fabrice PICARD +Abdul Aziz MOHAMAD +abdulaziz.mohamad +chambre 105 etage 1 aile sud +Abdul Aziz MOHAMAD +Melanie HOLBROOK +melanie.holbrook +chambre 116 etage 1 aile sud +Melanie HOLBROOK +Camille DELVAUX +camille.delvaux +chambre 123 etage 1 aile sud +Camille DELVAUX diff --git a/Brie/foo b/Brie/foo new file mode 100644 index 0000000..d92a68a --- /dev/null +++ b/Brie/foo @@ -0,0 +1,32 @@ +Boubakar OUATTARA +boubakar.ouattara +chambre 456 etage 4 aile nord +Boubakar OUATTARA +Tocha ZAABAY +tocha.zaabay +chambre 465 etage 4 aile nord +Tocha ZAABAY +Claude ALGOURDIN +claude.algourdin +chambre 418 etage 4 aile sud +Claude ALGOURDIN +Rachid CHEDRA +rachid.chedra +chambre 217 etage 2 aile sud +Rachid CHEDRA +Guillaume LETOUPIN +guillaume.letoupin +chambre 232 etage 2 aile sud +Guillaume LETOUPIN +erica MINUZ +erica.minuz +chambre 374 etage 3 aile nord +Erica MINUZ +FLAVIA MACHADO DOMINGUES +flavia.machadodomingue +chambre 452 etage 4 aile nord +flavia.machadodomingue not found +SOPHIA ID SALAH +sophia.idsalah +chambre 360 etage 3 aile nord +Sophia ID SALAH diff --git a/Brie/migrate_machines.py b/Brie/migrate_machines.py new file mode 100644 index 0000000..31d056f --- /dev/null +++ b/Brie/migrate_machines.py @@ -0,0 +1,130 @@ +from paste.deploy import appconfig +from pylons import config + +from brie.config.environment import load_environment + +conf = appconfig('config:development.ini', relative_to='.') +load_environment(conf.global_conf, conf.local_conf) + +from brie.config import ldap_config +from brie.lib.ldap_helper import * +from brie.lib.camembert_helpers import * + +from brie.model import DBSession +from brie.model.camembert import * + +#bind = Ldap.connect("uid=roven.gabriel," + ldap_config.username_base_dn, "foobar") +bind = Ldap.connect("uid=admin,ou=Administrators,ou=TopologyManagement,o=netscaperoot", "t734DSSL61") + +members = bind.search(ldap_config.username_base_dn, "(objectClass=pacatnetMember)") + +def roomOrNone(member): + if member.has("roomNumber"): + return member.roomNumber.first() + return None +#end def + +def first(items): + for item in items: + return item + + return None +#end def + +nextuid = 30000 + + +base_chambres_dn = "ou=chambres," + ldap_config.base_dn + + +results = DBSession.query(UserPacaterie) + +for user in results: + uid = Translations.to_uid(user.prenom, user.nom) + print uid + + member = bind.search_first(ldap_config.username_base_dn, "(uid=" + uid + ")") + + + print member.dn + + machines = DBSession.query(Computer).filter(Computer.iduser == user.iduser) + + machine_id = 1 + + for machine in machines: + print machine_id + print machine.name + print machine.mac + print machine.ip + + machine_dn = "cn=" + str(machine_id) + "," + member.dn + + existant = bind.search_first(machine_dn, "(objectClass=*)") + + if existant is not None: + bind.delete_entry_subtree(existant.dn) + print "deleted : " + existant.dn + + print machine_dn + + machine_attributes = { + "objectClass" : ["top", "organizationalRole"], + "cn" : str(machine_id) + } + + bind.add_entry(machine_dn, machine_attributes) + + dhcp_dn = "cn=" + str(machine.name) + "," + machine_dn + + print dhcp_dn + + dhcp_attributes = { + "objectClass" : ["top", "uidObject", "dhcpHost"], + "cn" : str(machine.name), + "uid" : "machine_membre", + "dhcpHWAddress" : str("ethernet " + machine.mac), + "dhcpStatements" : str("fixed-address " + machine.name) + } + + bind.add_entry(dhcp_dn, dhcp_attributes) + + mac_auth_dn = "cn=mac," + machine_dn + + print mac_auth_dn + + flat_mac = str(machine.mac).replace(":", "") + + print flat_mac + + mac_auth_attributes = { + "objectClass" : ["top", "organizationalRole", "simpleSecurityObject", "uidObject"], + "cn" : "mac", + "uid" : flat_mac, + "userPassword" : flat_mac + } + + bind.add_entry(mac_auth_dn, mac_auth_attributes) + + dns_dn = "dlzHostName=" + machine.name + "," + machine_dn + + print dns_dn + + dns_attributes = { + "objectClass" : ["top", "dlzAbstractRecord", "dlzGenericRecord"], + "dlzData" : str(machine.ip), + "dlzHostName" : str(machine.name), + "dlzRecordId" : "1", + "dlzTTL" : "3600", + "dlzType" : "A" + } + + bind.add_entry(dns_dn, dns_attributes) + + machine_id = 1 + machine_id + + #end for machine + + + +#end for diff --git a/Brie/migrate_names_values.py b/Brie/migrate_names_values.py new file mode 100644 index 0000000..8f22a70 --- /dev/null +++ b/Brie/migrate_names_values.py @@ -0,0 +1,107 @@ +from paste.deploy import appconfig +from pylons import config + +from brie.config.environment import load_environment + +conf = appconfig('config:development.ini', relative_to='.') +load_environment(conf.global_conf, conf.local_conf) + +from brie.config import ldap_config +from brie.lib.ldap_helper import * +from brie.lib.camembert_helpers import * + +from brie.model import DBSession +from brie.model.camembert import * + +#bind = Ldap.connect("uid=roven.gabriel," + ldap_config.username_base_dn, "foobar") +bind = Ldap.connect("uid=admin,ou=Administrators,ou=TopologyManagement,o=netscaperoot", "t734DSSL61") + +members = bind.search(ldap_config.username_base_dn, "(objectClass=pacatnetMember)") + +def roomOrNone(member): + if member.has("roomNumber"): + return member.roomNumber.first() + return None +#end def + +def first(items): + for item in items: + return item + + return None +#end def + +nextuid = 30000 + + +base_chambres_dn = "ou=chambres," + ldap_config.base_dn + + +results = DBSession.query(Room) + +for room in results: + ldap_room = bind.search_first(base_chambres_dn, "(cn=" + room.name + ")") + member_of = { + "x-memberIn" : None + } + + try: + bind.delete_attr(ldap_room.dn, member_of) + print "deleted " + ldap_room.dn + except: + pass + #end try + +#end for + + +results = DBSession.query(UserPacaterie, Room).filter(UserPacaterie.idroom == Room.idroom) + +for (user, room) in results: + uid = Translations.to_uid(user.prenom, user.nom) + print uid + + member = bind.search_first(ldap_config.username_base_dn, "(uid=" + uid + ")") + + print room.name + + member_dn = "" + + if member is None: + member_dn = "uid=" + uid + ",ou=2012," + ldap_config.username_base_dn + + mail = user.mail + if mail is None: + mail = "" + attributes = { + "objectClass" : ["top", "person", "organizationalPerson", "inetOrgPerson", "pacatnetMember", "pykotaAccount", "posixAccount"], + "uid" :(uid).encode("utf-8"), + "cn" : (user.prenom + " " + user.nom.upper()).encode("utf-8"), + "sn" : (user.nom.upper()).encode("utf-8"), + "givenName" : (user.prenom).encode("utf-8"), + "uidNumber" : str(-1), + "gidNumber" : "10000", + "homeDirectory" : ("/net/home/" + uid).encode("utf-8"), + "mail" : (mail).encode("utf-8"), + "loginShell" : "/usr/bin/zsh".encode("utf-8") + } + + bind.add_entry(member_dn, attributes) + + else: + member_dn = member.dn + #end if + + + + ldap_room = bind.search_first(base_chambres_dn, "(cn=" + room.name + ")") + + print ldap_room.dn + print member_dn + + new_member_of = { + "x-memberIn" : str(member_dn) + } + + bind.replace_attr(ldap_room.dn, new_member_of) +#end for diff --git a/Brie/migrate_remove_useless_values.py b/Brie/migrate_remove_useless_values.py new file mode 100644 index 0000000..d0c074d --- /dev/null +++ b/Brie/migrate_remove_useless_values.py @@ -0,0 +1,70 @@ +from paste.deploy import appconfig +from pylons import config + +from brie.config.environment import load_environment + +conf = appconfig('config:development.ini', relative_to='.') +load_environment(conf.global_conf, conf.local_conf) + +from brie.config import ldap_config +from brie.lib.ldap_helper import * +from brie.lib.camembert_helpers import * + +from brie.model import DBSession +from brie.model.camembert import * + +#bind = Ldap.connect("uid=roven.gabriel,ou=2011," + ldap_config.username_base_dn, "foobar") +bind = Ldap.connect("uid=admin,ou=Administrators,ou=TopologyManagement,o=netscaperoot", "t734DSSL61") + +members = bind.search(ldap_config.username_base_dn, "(&(ou:dn:=2011)(objectClass=pacatnetMember))") + +def roomOrNone(member): + if member.has("roomNumber"): + return member.roomNumber.first() + return None +#end def + +def first(items): + for item in items: + return item + + return None +#end def + +nextuid = 30000 + +def add(uid, user, room_dn, nextuid): + user_dn = "uid=" + uid + "," + ldap_config.username_base_dn + mail = user.mail + if mail is None: + mail = "" + attributes = { + "objectClass" : ["top", "person", "organizationalPerson", "inetOrgPerson", "pacatnetMember", "pykotaAccount", "posixAccount"], + "uid" :(uid).encode("utf-8"), + "cn" : (user.prenom + " " + user.nom.upper()).encode("utf-8"), + "sn" : (user.nom.upper()).encode("utf-8"), + "givenName" : (user.prenom).encode("utf-8"), + "uidNumber" : str(nextuid), + "gidNumber" : "10000", + "homeDirectory" : ("/net/home/" + uid).encode("utf-8"), + "mail" : (mail).encode("utf-8"), + "x-room" : (room_dn).encode("utf-8"), + "loginShell" : "/usr/bin/zsh".encode("utf-8") + } + + bind.add_entry(user_dn, attributes) + +#end def + +filestream = open("people_to_change.txt", "r") + +for line in filestream: + uid = line.strip() + print "++" + uid + "++" + print "ou=2010," + ldap_config.username_base_dn + result = bind.search_first(ldap_config.username_base_dn, "(uid=" + uid + ")") + bind.rename_entry(result.dn, "uid=" + result.uid.first(), "ou=2010," + ldap_config.username_base_dn) + +#end for + + diff --git a/Brie/migrate_rooms.py b/Brie/migrate_rooms.py new file mode 100644 index 0000000..d079b13 --- /dev/null +++ b/Brie/migrate_rooms.py @@ -0,0 +1,80 @@ +from paste.deploy import appconfig +from pylons import config + +from brie.config.environment import load_environment + +conf = appconfig('config:development.ini', relative_to='.') +load_environment(conf.global_conf, conf.local_conf) + +from brie.config import ldap_config +from brie.lib.ldap_helper import * + +from brie.model import DBSession +from brie.model.camembert import * + +import socket + +#bind = Ldap.connect("uid=roven.gabriel,ou=2010," + ldap_config.username_base_dn, "foobar") +bind = Ldap.connect("uid=admin,ou=Administrators,ou=TopologyManagement,o=netscaperoot", "t734DSSL61") + +members = bind.search(ldap_config.username_base_dn, "(objectClass=pacatnetMember)") + +def roomOrNone(member): + if member.has("roomNumber"): + return member.roomNumber.first() + return None +#end def + +def first(items): + for item in items: + return item + + return None +#end def + +def area(room_number): + floor_number = room_number % 100 + + if floor_number <= 33: + return "sud" + else: + return "nord" + #end if +#end def + +results = DBSession.query(Room, Materiel, Interface).filter(Room.idinterface == Interface.idinterface).filter(Interface.idmateriel == Materiel.idmateriel) + +for room, materiel, interface in results: + aile = area(room.idroom) + etage = str(room.idroom / 100) + + base_chambres_dn = "ou=chambres," + ldap_config.base_dn + + other_dn = "cn=" + etage + ",cn=" + aile + "," + base_chambres_dn + + full_dn = "cn=" + room.name + "," + other_dn + + print room + + switch_ip = socket.gethostbyname(str(materiel.hostname)) + + + attributes = { + "objectClass" : "pacaterieRoom", + "cn" : str(room.name), + "x-switch" : str(switch_ip), + "x-switchInterface" : str(interface.ifname) + } + + + print str(room.idinterface) + + print full_dn + try: + bind.replace_attr(full_dn, attributes) + except ldap.NO_SUCH_OBJECT: + bind.add_entry(full_dn, attributes) +# print attributes +#end for + + diff --git a/Brie/migrate_switch.py b/Brie/migrate_switch.py new file mode 100644 index 0000000..35749d6 --- /dev/null +++ b/Brie/migrate_switch.py @@ -0,0 +1,59 @@ +from paste.deploy import appconfig +from pylons import config + +from brie.config.environment import load_environment + +conf = appconfig('config:development.ini', relative_to='.') +load_environment(conf.global_conf, conf.local_conf) + +from brie.config import ldap_config +from brie.lib.ldap_helper import * +from brie.lib.camembert_helpers import * + +from brie.model import DBSession +from brie.model.camembert import * + +#bind = Ldap.connect("uid=roven.gabriel," + ldap_config.username_base_dn, "foobar") +bind = Ldap.connect("uid=admin,ou=Administrators,ou=TopologyManagement,o=netscaperoot", "t734DSSL61") + +members = bind.search(ldap_config.username_base_dn, "(objectClass=pacatnetMember)") + +def roomOrNone(member): + if member.has("roomNumber"): + return member.roomNumber.first() + return None +#end def + +def first(items): + for item in items: + return item + + return None +#end def + +nextuid = 30000 + + +base_chambres_dn = "ou=chambres," + ldap_config.base_dn + + +results = DBSession.query(Room, Interface).filter(Room.idinterface == Interface.idinterface).order_by(Room.name) + +for (room, interface) in results: + ldap_room = bind.search_first(base_chambres_dn, "(cn=" + room.name + ")") + print ldap_room.dn + + switch_id = { + "x-switchInterface" : str(interface.idinterface) + } + + bind.replace_attr(ldap_room.dn, switch_id) + + uid_attr = { + "objectClass" : "uidObject", + "uid" : str(room.idroom) + } + + bind.add_attr(ldap_room.dn, uid_attr) + +#end for diff --git a/Brie/setup.cfg b/Brie/setup.cfg new file mode 100644 index 0000000..269af8a --- /dev/null +++ b/Brie/setup.cfg @@ -0,0 +1,32 @@ +[egg_info] +tag_build = dev +tag_svn_revision = true + +[easy_install] +find_links = http://www.pylonshq.com/download/ + +[nosetests] +with-pylons=test.ini + +# Babel configuration +[compile_catalog] +domain = brie +directory = brie/i18n +statistics = true + +[extract_messages] +add_comments = TRANSLATORS: +output_file = brie/i18n/brie.pot +width = 80 +keywords = l_ + +[init_catalog] +domain = brie +input_file = brie/i18n/brie.pot +output_dir = brie/i18n + +[update_catalog] +domain = brie +input_file = brie/i18n/brie.pot +output_dir = brie/i18n +previous = true diff --git a/Brie/setup.py b/Brie/setup.py new file mode 100644 index 0000000..95f7ba7 --- /dev/null +++ b/Brie/setup.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +try: + from setuptools import setup, find_packages +except ImportError: + from ez_setup import use_setuptools + use_setuptools() + from setuptools import setup, find_packages + +setup( + name='Brie', + version='0.1', + description='', + author='', + author_email='', + #url='', + install_requires=[ + "TurboGears2 >= 2.0b7", + "Catwalk >= 2.0.2", + "Babel >=0.9.4", + #can be removed iif use_toscawidgets = False + "toscawidgets >= 0.9.7.1", + "zope.sqlalchemy >= 0.4 ", + "repoze.tm2 >= 1.0a4", + + "repoze.what-quickstart >= 1.0", + ], + setup_requires=["PasteScript >= 1.7"], + paster_plugins=['PasteScript', 'Pylons', 'TurboGears2', 'tg.devtools'], + packages=find_packages(exclude=['ez_setup']), + include_package_data=True, + test_suite='nose.collector', + tests_require=['WebTest', 'BeautifulSoup'], + package_data={'brie': ['i18n/*/LC_MESSAGES/*.mo', + 'templates/*/*', + 'public/*/*']}, + message_extractors={'brie': [ + ('**.py', 'python', None), + ('templates/**.mako', 'mako', None), + ('templates/**.html', 'genshi', None), + ('public/**', 'ignore', None)]}, + + entry_points=""" + [paste.app_factory] + main = brie.config.middleware:make_app + + [paste.app_install] + main = pylons.util:PylonsInstaller + """, +) diff --git a/Brie/test.ini b/Brie/test.ini new file mode 100644 index 0000000..ba3fd3b --- /dev/null +++ b/Brie/test.ini @@ -0,0 +1,26 @@ +# +# Brie - TurboGears 2 testing environment configuration +# +# The %(here)s variable will be replaced with the parent directory of this file +# +[DEFAULT] +debug = true +# Uncomment and replace with the address which should receive any error reports +# email_to = you@yourdomain.com +smtp_server = localhost +error_email_from = paste@localhost + +[server:main] +use = egg:Paste#http +host = 0.0.0.0 +port = 5000 + +[app:main] +sqlalchemy.url = sqlite:///:memory: +use = config:development.ini + +[app:main_without_authn] +use = main +skip_authentication = True + +# Add additional test specific configuration options as necessary.