]> ToastFreeware Gitweb - philipp/winterrodeln/wradmin.git/commitdiff
Added SQLAlchemy 0.5.3 support. Created "bericht" controller to view reports.
authorphilipp <philipp@7aebc617-e5e2-0310-91dc-80fb5f6d2477>
Wed, 18 Mar 2009 18:35:20 +0000 (18:35 +0000)
committerphilipp <philipp@7aebc617-e5e2-0310-91dc-80fb5f6d2477>
Wed, 18 Mar 2009 18:35:20 +0000 (18:35 +0000)
git-svn-id: http://www.winterrodeln.org/svn/servermediawiki/trunk/wradmin@427 7aebc617-e5e2-0310-91dc-80fb5f6d2477

14 files changed:
wradmin/development.ini
wradmin/wradmin/config/deployment.ini_tmpl
wradmin/wradmin/config/environment.py
wradmin/wradmin/config/middleware.py
wradmin/wradmin/controllers/bericht.py [new file with mode: 0644]
wradmin/wradmin/lib/mediawiki.py
wradmin/wradmin/model/__init__.py
wradmin/wradmin/model/meta.py [new file with mode: 0644]
wradmin/wradmin/templates/bericht_list.html [new file with mode: 0644]
wradmin/wradmin/templates/bericht_view.html [new file with mode: 0644]
wradmin/wradmin/templates/index.html
wradmin/wradmin/templates/master.html
wradmin/wradmin/tests/functional/test_bericht.py [new file with mode: 0644]
wradmin/wradmin/websetup.py

index 32f50380e6e41d426a0c0c398bd2230f76f9022a..cb4f9e2bdf1bee88b018d0e03b197e06cf89ec11 100644 (file)
@@ -41,6 +41,9 @@ authkit.basic.authenticate.user.data =
 #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.
@@ -52,13 +55,14 @@ authkit.basic.authenticate.user.data =
 keys = root, routes, wradmin
 
 [handlers]
-keys = console
+keys = console, file
 
 [formatters]
 keys = generic
 
 [logger_root]
 level = INFO
+# handlers = file
 handlers = console
 
 [logger_routes]
@@ -78,6 +82,12 @@ args = (sys.stderr,)
 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
index 67f38fc67f7cea81d126073970dd8c093bc55670..c071f3b9573bce9f3334da4958999d59f01e30d6 100644 (file)
@@ -41,6 +41,9 @@ authkit.basic.authenticate.user.data =
 #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.
index 01f34b93eabc63f84bf21d41af62f162e8af7852..843b198f861272e48444b3ce1ca4b6568e977de5 100644 (file)
@@ -3,10 +3,12 @@ import os
 
 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``
@@ -30,6 +32,10 @@ def load_environment(global_conf, app_conf):
     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
index 3ef24c305796b3f8cf7a89e8891a933f0dc94f11..4f8a31e494cf6c13a9f56c9589162023c1d52bfd 100644 (file)
@@ -53,10 +53,12 @@ def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
     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)
diff --git a/wradmin/wradmin/controllers/bericht.py b/wradmin/wradmin/controllers/bericht.py
new file mode 100644 (file)
index 0000000..2e6ec45
--- /dev/null
@@ -0,0 +1,48 @@
+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."
index 179211f67d3c5ac998424cf3bdc5c52020a5fc0f..838a58be995973df017b063b8b2acba7a1ac886d 100644 (file)
@@ -3,6 +3,9 @@
 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)
@@ -34,6 +37,7 @@ class MediaWikiUsers(UsersReadOnly):
             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):
@@ -51,4 +55,5 @@ class MediaWikiUsers(UsersReadOnly):
             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
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c8c3191b5c3b15a20bc64608734828b812d32591 100644 (file)
@@ -0,0 +1,53 @@
+"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
diff --git a/wradmin/wradmin/model/meta.py b/wradmin/wradmin/model/meta.py
new file mode 100644 (file)
index 0000000..1a20aa7
--- /dev/null
@@ -0,0 +1,15 @@
+"""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()
diff --git a/wradmin/wradmin/templates/bericht_list.html b/wradmin/wradmin/templates/bericht_list.html
new file mode 100644 (file)
index 0000000..0735034
--- /dev/null
@@ -0,0 +1,46 @@
+<?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>
diff --git a/wradmin/wradmin/templates/bericht_view.html b/wradmin/wradmin/templates/bericht_view.html
new file mode 100644 (file)
index 0000000..6e9ad5a
--- /dev/null
@@ -0,0 +1,99 @@
+<?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>
+
index 5dd8f8b238dd3a4d1c50fe1983da182752748152..9b32dc10b81504e326092bc3cf7c5007b4abcb12 100644 (file)
@@ -18,6 +18,7 @@
 <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>
index 50e13e3a5c3498289f0a29dd127d4f59f8618c46..5b90712de5bde8295edae20c037c2777c1d4dbe2 100644 (file)
@@ -25,6 +25,7 @@
        <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">
diff --git a/wradmin/wradmin/tests/functional/test_bericht.py b/wradmin/wradmin/tests/functional/test_bericht.py
new file mode 100644 (file)
index 0000000..e92cde6
--- /dev/null
@@ -0,0 +1,7 @@
+from wradmin.tests import *
+
+class TestBerichtController(TestController):
+
+    def test_index(self):
+        response = self.app.get(url(controller='bericht', action='index'))
+        # Test response...
index aec7cf0d19443e545c676007d79033b4484805de..923f7b0538b690c37fadd49c59c633300ba870b0 100644 (file)
@@ -2,9 +2,13 @@
 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