#beaker.cache.data_dir = %(here)s/data/cache
#beaker.session.data_dir = %(here)s/data/sessions
+# SQLAlchemy database URL
+sqlalchemy.url = mysql://philipp@localhost:3306/winterrodeln_wiki?charset=utf8
+
# 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.
keys = root, routes, wradmin
[handlers]
-keys = console
+keys = console, file
[formatters]
keys = generic
[logger_root]
level = INFO
+# handlers = file
handlers = console
[logger_routes]
level = NOTSET
formatter = generic
+[handler_file]
+class = FileHandler
+args = ('/tmp/pylons_application.log', 'a')
+level = INFO
+formatter = generic
+
[formatter_generic]
format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S
#beaker.cache.data_dir = %(here)s/data/cache
#beaker.session.data_dir = %(here)s/data/sessions
+# SQLAlchemy database URL
+sqlalchemy.url = mysql://user@localhost:3306/winterrodeln_wiki?charset=utf8
+
# 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.
from genshi.template import TemplateLoader
from pylons import config
+from sqlalchemy import engine_from_config
import wradmin.lib.app_globals as app_globals
import wradmin.lib.helpers
from wradmin.config.routing import make_map
+from wradmin.model import init_model
def load_environment(global_conf, app_conf):
"""Configure the Pylons environment via the ``pylons.config``
config['pylons.app_globals'].genshi_loader = TemplateLoader(
paths['templates'], auto_reload=True)
+ # Setup the SQLAlchemy database engine
+ engine = engine_from_config(config, 'sqlalchemy.')
+ init_model(engine)
+
# CONFIGURATION OPTIONS HERE (note: all config options will override
# any Pylons config options)
config['pylons.strict_c'] = True
\ No newline at end of file
if asbool(full_stack):
# Handle Python exceptions
app = ErrorHandler(app, global_conf, **config['pylons.errorware'])
-
- permission = ValidAuthKitUser()
- app = authkit.authorize.middleware(app, permission)
- app = authkit.authenticate.middleware(app, app_conf)
+
+ # Authorization (not in debug mode)
+ if not config['debug']:
+ permission = ValidAuthKitUser()
+ app = authkit.authorize.middleware(app, permission)
+ app = authkit.authenticate.middleware(app, app_conf)
# Display error documents for 401, 403, 404 status codes (and
# 500 when debug is disabled)
--- /dev/null
+import logging
+
+from pylons import request, response, session, tmpl_context as c
+from pylons.controllers.util import abort, redirect_to
+import webhelpers.paginate as paginate
+
+from wradmin.lib.base import BaseController, render
+import wradmin.model as model
+import sqlalchemy as sa
+
+log = logging.getLogger(__name__)
+
+class BerichtController(BaseController):
+ "Manages reports (table wrreport)"
+
+ def view(self, id):
+ "Displays a report"
+ wrreport_q = model.meta.Session.query(model.WrReport)
+ c.wrreport = wrreport_q.get(id)
+ if c.wrreport is None: abort(404)
+ return render('bericht_view.html')
+
+ def new(self, id):
+ "Displays a form to create a new page"
+ return u"Nicht implementiert."
+
+ def create(self):
+ "Saves the information submitted from new() and redirects to view()"
+ return u"Nicht implementiert."
+
+ def edit(self, id):
+ "Displays a form for editing the page id"
+ return u"Nicht implementiert."
+
+ def save(self, id):
+ "Saves the page id and redirects to view()"
+ return u"Nicht implementiert."
+
+ def list(self):
+ "Lists all pages"
+ records = model.meta.Session.query(model.WrReport)
+ records = records.order_by(sa.sql.expression.desc(model.WrReport.id))
+ c.paginator = paginate.Page(records, page=int(request.params.get('page', 1)), items_per_page = 25)
+ return render('bericht_list.html')
+
+ def delete(self, id):
+ "Deletes a page"
+ return u"Nicht implementiert."
from authkit.users import UsersReadOnly, md5
from wradmin.lib.wrdatabase import get_wiki_connection
+import logging
+log = logging.getLogger(__name__)
+
class MediaWikiUsers(UsersReadOnly):
def __init__(self, data=None, encrypt=None):
UsersReadOnly.__init__(self, data, encrypt)
self.user_ids[username] = user_id
self.real_names[username] = real_name
self.emails[username] = email
+ log.info("%d users loaded from the MediaWiki database" % len(self.usernames))
def user_has_password(self, username, password):
salt, pwd_md5 = tuple(pwd_parts[2:4]) # salt = 'd25b2886'; pwd_md5 = '41e46c952790b1b442aac4f24f7ea7a8'
else:
raise AuthKitError("Password in the MediaWiki database format has an unexpected format ('%s' instead of e.g. ':B:d25b2886:41e46c952790b1b442aac4f24f7ea7a8')" % pwd)
+ log.info("user: '%s'; md5 of salt+' '+entered_pwd: '%s'; md5-part of DB-pwd: %s" % (username, md5(salt + '-' + md5(password)), pwd_md5))
return md5(salt + '-' + md5(password)) == pwd_md5
+"Model of wradmin"
+import sqlalchemy as sa
+from sqlalchemy import orm, schema, types
+from wradmin.model import meta
+import datetime
+
+def init_model(engine):
+ """Call me before using any of the tables or classes in the model"""
+ ## Reflected tables must be defined and mapped here
+ #global reflected_table
+ #reflected_table = sa.Table("Reflected", meta.metadata, autoload=True,
+ # autoload_with=engine)
+ #orm.mapper(Reflected, reflected_table)
+ #
+ meta.Session.configure(bind=engine)
+ meta.engine = engine
+
+
+## Non-reflected tables may be defined and mapped at module level
+wrreport_table = sa.Table("wrreport", meta.metadata,
+ sa.Column("id", sa.types.Integer, primary_key=True),
+ sa.Column("page_id", sa.types.Integer, nullable=False),
+ sa.Column("page_title", sa.types.Unicode(255), nullable=False),
+ sa.Column("date_report", sa.types.Date),
+ sa.Column("date_entry", sa.types.DateTime, nullable=False),
+ sa.Column("date_invalid", sa.types.DateTime),
+ sa.Column("condition", sa.types.Integer),
+ sa.Column("description", sa.types.Unicode),
+ sa.Column("author_name", sa.types.Unicode(30)),
+ sa.Column("author_ip", sa.types.Unicode(15)),
+ sa.Column("author_userid", sa.types.Integer),
+ sa.Column("author_username", sa.types.Unicode(30)),
+ sa.Column("delete_date", sa.types.DateTime),
+ sa.Column("delete_person_name", sa.types.Unicode(30)),
+ sa.Column("delete_person_ip", sa.types.Unicode(15)),
+ sa.Column("delete_person_userid", sa.types.Integer),
+ sa.Column("delete_person_username", sa.types.Unicode(30)),
+ sa.Column("delete_reason_public", sa.types.Unicode),
+ )
+
+
+class WrReport(object):
+ pass
+
+orm.mapper(WrReport, wrreport_table)
+
+
+## Classes for reflected tables may be defined here, but the table and
+## mapping itself must be done in the init_model function
+#reflected_table = None
+#
+#class Reflected(object):
+# pass
--- /dev/null
+"""SQLAlchemy Metadata and Session object"""
+from sqlalchemy import MetaData
+from sqlalchemy.orm import scoped_session, sessionmaker
+
+__all__ = ['Session', 'engine', 'metadata']
+
+# SQLAlchemy database engine. Updated by model.init_model()
+engine = None
+
+# SQLAlchemy session manager. Updated by model.init_model()
+Session = scoped_session(sessionmaker())
+
+# Global metadata. If you have multiple databases with overlapping table
+# names, you'll need a metadata for each database
+metadata = MetaData()
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:py="http://genshi.edgewall.org/"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+<xi:include href="master.html" />
+
+<head>
+ <title>Rodelbahnberichte</title>
+</head>
+
+<body>
+<h2>Rodelbahnberichte</h2>
+
+<p>${c.paginator.pager('$link_first $link_previous $first_item to $last_item of $item_count $link_next $link_last', controller='bericht', action='list')}</p>
+
+<table>
+ <tr>
+ <th>ID</th>
+ <th>Seite</th>
+ <th>Datum Eintrag</th>
+ <th>Datum Ungültig</th>
+ <th>Datum für Bericht</th>
+ <th>Zustand (1 bis 5)</th>
+ <th>Beschreibung (WikiText)</th>
+ <th>Autor-Name</th>
+ <th>Gelöscht</th>
+ </tr>
+ <tr py:for="r in c.paginator">
+ <td><a href="${h.url_for(controller='bericht', action='view', id=r.id)}">${r.id}</a></td>
+ <td>${r.page_title}</td>
+ <td>${r.date_entry}</td>
+ <td>${r.date_invalid}</td>
+ <td>${r.date_report}</td>
+ <td>${r.condition}</td>
+ <td>${r.description}</td>
+ <td>${r.author_name}</td>
+ <td>${r.delete_date}</td>
+ </tr>
+</table>
+
+<p>${c.paginator.pager('~2~', controller='bericht', action='list')}</p>
+
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:py="http://genshi.edgewall.org/"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+<xi:include href="master.html" />
+
+<head>
+ <title>Rodelbahnbericht</title>
+</head>
+
+<body>
+<h2>Rodelbahnbericht #${c.wrreport.id}</h2>
+
+Der Bericht wurde am ${c.wrreport.date_report} abgegeben.
+
+<table>
+ <tr>
+ <th>Eintrag ID</th>
+ <td>${c.wrreport.id}</td>
+ </tr>
+ <tr>
+ <th>Seite (Rodelbahn)</th>
+ <td>${c.wrreport.page_title}</td>
+ </tr>
+ <tr>
+ <th>Datum für Bericht</th>
+ <td>${c.wrreport.date_report}</td>
+ </tr>
+ <tr>
+ <th>Datum Eintrag</th>
+ <td>${c.wrreport.date_entry}</td>
+ </tr>
+ <tr>
+ <th>Datum Ungültig</th>
+ <td>${c.wrreport.date_invalid}</td>
+ </tr>
+ <tr>
+ <th>Zustand (1 bis 5)</th>
+ <td>${c.wrreport.condition}</td>
+ </tr>
+ <tr>
+ <th>Beschreibung (WikiText)</th>
+ <td>${c.wrreport.description}</td>
+ </tr>
+ <tr>
+ <th>Autor-Name</th>
+ <td>${c.wrreport.author_name}</td>
+ </tr>
+ <tr>
+ <th>Autor-IP</th>
+ <td>${c.wrreport.author_ip}</td>
+ </tr>
+ <tr>
+ <th>Autor-Benutzer-ID</th>
+ <td>${c.wrreport.author_userid}</td>
+ </tr>
+ <tr>
+ <th>Autor-Benutzername</th>
+ <td>${c.wrreport.author_username}</td>
+ </tr>
+ <py:if test="c.wrreport.delete_date">
+ <tr>
+ <th>Gelöscht am</th>
+ <td>${c.wrreport.delete_date}</td>
+ </tr>
+ <tr>
+ <th>Gelöscht von</th>
+ <td>${c.wrreport.delete_person_name}</td>
+ </tr>
+ <tr>
+ <th>Gelöscht von IP</th>
+ <td>${c.wrreport.delete_person_ip}</td>
+ </tr>
+ <tr>
+ <th>Gelöscht von</th>
+ <td>${c.wrreport.delete_person_userid}</td>
+ </tr>
+ <tr>
+ <th>Gelöscht von</th>
+ <td>${c.wrreport.delete_person_username}</td>
+ </tr>
+ <tr>
+ <th>Löschgrund</th>
+ <td>${c.wrreport.delete_reason_public}</td>
+ </tr>
+ </py:if>
+ <py:if test="not c.wrreport.delete_date">
+ <tr>
+ <th>Gelöscht</th>
+ <td>Nein</td>
+ </tr>
+ </py:if>
+</table>
+
+</body>
+</html>
+
<ul>
<li><a href="${h.url_for(controller='wrcontroller', action='forumlink')}">Forum-Links auf Rodelbahnen</a></li>
<li><a href="${h.url_for(controller='wrcontroller', action='rodelbahnbox')}">Rodelbahn-Infoboxen</a> überprüfen und Koordinaten aktualisieren</li>
+ <li><a href="${h.url_for(controller='bericht', action='list')}">Rodelbahnberichte</a></li>
</ul>
<ul>
<li><a href="${h.url_for(controller='wrcontroller', action='index')}">Übersicht</a></li>
<li><a href="${h.url_for(controller='wrcontroller', action='rodelbahnbox')}">Rodelbahnboxen</a></li>
<li><a href="${h.url_for(controller='wrcontroller', action='forumlink')}">Forum-Links</a></li>
+ <li><a href="${h.url_for(controller='bericht', action='list')}">Berichte</a></li>
</ul>
<div id="content">
--- /dev/null
+from wradmin.tests import *
+
+class TestBerichtController(TestController):
+
+ def test_index(self):
+ response = self.app.get(url(controller='bericht', action='index'))
+ # Test response...
import logging
from wradmin.config.environment import load_environment
+from wradmin.model import meta
log = logging.getLogger(__name__)
def setup_app(command, conf, vars):
"""Place any commands to setup wradmin here"""
load_environment(conf.global_conf, conf.local_conf)
+
+ ## Create the tables if they don't already exist
+ # meta.metadata.create_all(bind=meta.engine)
\ No newline at end of file