from twisted.application import service, internet
from twisted.cred import portal, checkers
from twisted.web import resource, server, util
from twisted.cred.portal import Portal
from twisted.cred.checkers import AllowAnonymousAccess, InMemoryUsernamePasswordDatabaseDontUse
from twisted.web.woven.guard import UsernamePasswordWrapper, SessionWrapper
from twisted.cred.credentials import IAnonymous

from nevow import renderer, tags, appserver, guard


### Renderers

class NotLoggedIn(renderer.Renderer):
    """The resource that is returned when you are not logged in"""
    document = tags.html[
        tags.head[tags.title["Not Logged In"]],
        tags.body[
            tags.form(action=guard.LOGIN_AVATAR)[
                tags.table[
                    tags.tr[
                        tags.td[ "Username:" ],
                        tags.td[ tags.input(type='text',name='username') ],
                    ],
                    tags.tr[
                        tags.td[ "Password:" ],
                        tags.td[ tags.input(type='password',name='password') ],
                    ]
                ],
                tags.input(type='submit'),
                tags.p,
            ]
        ]
    ]

class LoggedIn(renderer.Renderer):
    """The resource that is returned when you login"""
    document = tags.html[
        tags.head[tags.title["Logged In"]],
        tags.body[
            tags.h3(renderer=tags.directive("welcome")),
            tags.a(href=guard.LOGOUT_AVATAR)["Logout"]
        ]
    ]

    def __init__(self, username, *args, **kw):
        self.username = username
        renderer.Renderer.__init__(self, *args, **kw)

    def render_welcome(self, context, data):
        return context.tag[ "Hello, %s!" % self.username]

    def logout(self):
        print "%s logged out!" % self.username


### Authentication

def noLogout():
    return None


class MyRealm:
    """A simple implementor of cred's IRealm.
       For web, this gives us the LoggedIn page.
    """
    __implements__ = portal.IRealm

    def requestAvatar(self, avatarId, mind, *interfaces):
        for iface in interfaces:
            if iface is resource.IResource:
                # do web stuff
                if avatarId is checkers.ANONYMOUS:
                    resc = NotLoggedIn()
                    resc.realm = self
                    return (resource.IResource, resc, noLogout)
                else:
                    resc = LoggedIn(avatarId)
                    resc.realm = self
                    return (resource.IResource, resc, resc.logout)

        raise NotImplementedError("Can't support that interface.")


realm = MyRealm()
portal = Portal(realm)
myChecker = InMemoryUsernamePasswordDatabaseDontUse()
myChecker.addUser("user","password")
# Allow anonymous access.  Needed for access to NotLoggedIn
portal.registerChecker(AllowAnonymousAccess(), IAnonymous)
# Allow users registered in the password file.
portal.registerChecker(myChecker)

site = appserver.NevowSite(
    resource=guard.SessionWrapper(
        guard.UsernamePasswordWrapper(portal)
    ),
)

application = service.Application("guarded")
internet.TCPServer(8080, site).setServiceParent(application)
