twisted な trac の認証

自宅からも職場関連で微妙なやりとりをしつつ、写経。

とりあえず

htpasswd なコマンドが無い。てーかテキストには htpasswd2 とかって出てるんですが、スルーで。でびあんだと apache2-utils に格納。

# apt-get install -f apache2-utils

で、以下

# htpasswd -c htpasswd test
(ry

修正を盛り込んで、いくつかの typo を修正しつつ、ログイン画面は出たのですが、認証に失敗します。別場所で動作確認したいので以下に現時点での mytrac.py を貼っておく

import trac.web.main
import trac.web.standalone

from twisted.web2.wsgi import WSGIResource
from twisted.web2 import server
from twisted.web2.channel import http
from twisted.internet import reactor

import sha

class TwistedAuthenticator(trac.web.auth.BasicAuthentication):
    def __init__(self, htpasswd, realm):
        trac.web.auth.BasicAuthentication.__init__(self, htpasswd, realm)
        self.htpasswd = htpasswd

    def test(self, user, password):
        self.load(self.htpasswd)
        
        the_hash = self.hash.get(user)
        if the_hash is None:
            return False

        if sha.new(password).hexdigest() == the_hash:
            return True

        return trac.web.auth.BasicAuthentication.test(self, user, password)
    
class TracResource(WSGIResource):
    def __init__(self, path, htpasswd):
        self.path = path
        self.htpasswd = htpasswd
        self.auths = {"twisted": TwistedAuthenticator(self.htpasswd, 'trac'),
                      "*": TwistedAuthenticator(self.htpasswd, 'trac')}
        WSGIResource.__init__(self,
                              self.authTracApplication)
    
    def authTracApplication(self, environ, start_response):
        path_info = environ.get('PATH_INFO', '')
        path_parts = filter(None, path_info.split('/'))
        if path_parts and path_parts[0] == 'login':
            env_name = path_parts[0]
            if env_name:
                auth = self.auths.get(env_name, self.auths.get("*"))
                if auth:
                    remote_user = auth.do_auth(environ, start_response)
                if not remote_user:
                    return []
                environ['REMOTE_USER'] = remote_user
        return self.tracApplication(environ, start_response)
    
    def tracApplication(self, environ, start_response):
        environ['trac.env_path'] = self.path
#        environ['trac.base_url'] = 'http://localhost:1234/trac/'
        environ['trac.base_url'] = 'http://localhost:1234/'
        return trac.web.main.dispatch_request(environ, start_response)

reactor.listenTCP(1234,
                  http.HTTPFactory(server.Site(TracResource("mytrac", "./htpasswd"))))
reactor.run()

うーん ...