~landscape/zope3/newer-from-ztk

« back to all changes in this revision

Viewing changes to src/twisted/web/guard.py

  • Committer: Thomas Hervé
  • Date: 2009-07-08 13:52:04 UTC
  • Revision ID: thomas@canonical.com-20090708135204-df5eesrthifpylf8
Remove twisted copy

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
2
 
# See LICENSE for details.
3
 
 
4
 
 
5
 
"""DEPRECATED.
6
 
 
7
 
You probably should be using twisted.web.woven.guard instead.
8
 
"""
9
 
 
10
 
# System Imports
11
 
import string, traceback
12
 
from cStringIO import StringIO
13
 
 
14
 
from twisted.python import log
15
 
 
16
 
# Sibling Imports
17
 
import error
18
 
import html
19
 
import resource
20
 
import widgets
21
 
from server import NOT_DONE_YET
22
 
 
23
 
import warnings
24
 
warnings.warn("Please use twisted.web.woven.guard", DeprecationWarning, 2)
25
 
 
26
 
 
27
 
class _Detacher:
28
 
    """Detach a web session from an attached perspective.
29
 
 
30
 
    This will happen when the session expires.
31
 
    """
32
 
    
33
 
    def __init__(self, session, identity, perspective):
34
 
        self.session = session
35
 
        self.identity = identity
36
 
        self.perspective = perspective
37
 
        session.notifyOnExpire(self.detach)
38
 
    
39
 
    def detach(self):
40
 
        self.perspective.detached(self.session, self.identity)
41
 
        del self.session
42
 
        del self.identity
43
 
        del self.perspective
44
 
 
45
 
 
46
 
class AuthForm(widgets.Form):
47
 
    formFields = [
48
 
        ['string','Identity','username',''],
49
 
        ['password','Password','password',''],
50
 
        ['string','Perspective','perspective','']
51
 
        ]
52
 
 
53
 
    formAcceptExtraArgs = 1
54
 
    
55
 
    def __init__(self, reqauth, sessionIdentity=None, sessionPerspective=None):
56
 
        """Initialize, specifying various options.
57
 
        
58
 
        @param reqauth: a web.resource.Resource instance, indicating which
59
 
              resource a user will be logging into with this form; this must
60
 
              specify a serviceName attribute which indicates the name of the
61
 
              service from which perspectives will be requested.
62
 
 
63
 
        @param sessionIdentity: if specified, the name of the attribute on
64
 
              the user's session to set for the identity they get from logging
65
 
              in to this form.
66
 
            
67
 
        @param sessionPerspective: if specified, the name of the attribute on
68
 
              the user's session to set for the perspective they get from
69
 
              logging in to this form.
70
 
        """
71
 
        self.reqauth = reqauth
72
 
        self.sessionPerspective = sessionPerspective
73
 
        self.sessionIdentity = sessionIdentity
74
 
 
75
 
    def gotPerspective(self, perspective, request, ident):
76
 
        # TODO: fix this...
77
 
        resKey = string.join(['AUTH',self.reqauth.service.serviceName], '_')
78
 
        sess = request.getSession()
79
 
        setattr(sess, resKey, perspective)
80
 
        if self.sessionPerspective:
81
 
            setattr(sess, self.sessionPerspective, perspective)
82
 
            if self.sessionIdentity:
83
 
                setattr(sess, self.sessionIdentity, ident)
84
 
            p = perspective.attached(sess, ident)
85
 
            _Detacher(sess, ident, p)
86
 
        return self.reqauth.reallyRender(request)
87
 
    
88
 
    def didntGetPerspective(self, error, request):
89
 
        log.msg('Password not verified! Error: %s' % error)
90
 
        io = StringIO()
91
 
        io.write(self.formatError("Login incorrect."))
92
 
        self.format(self.getFormFields(request), io.write, request)
93
 
        return [io.getvalue()]
94
 
 
95
 
    def gotIdentity(self, ident, password, request, perspectiveName):
96
 
        pwrq = ident.verifyPlainPassword(password)
97
 
        pwrq.addCallback(self.passwordIsOk, ident, password,
98
 
                         request, perspectiveName)
99
 
        pwrq.addErrback(self.didntGetPerspective, request)
100
 
        pwrq.needsHeader = 1
101
 
        return [pwrq]
102
 
 
103
 
    def passwordIsOk(self, msg, ident, password, request, perspectiveName):
104
 
        ret = ident.requestPerspectiveForKey(self.reqauth.service.serviceName,
105
 
                                             perspectiveName).addCallbacks(
106
 
            self.gotPerspective, self.didntGetPerspective,
107
 
            callbackArgs=(request,ident),
108
 
            errbackArgs=(request,))
109
 
        ret.needsHeader = 1
110
 
        return [ret]
111
 
 
112
 
    def didntGetIdentity(self, unauth, request):
113
 
        io = StringIO()
114
 
        io.write(self.formatError("Login incorrect."))
115
 
        self.format(self.getFormFields(request), io.write, request)
116
 
        return io.getvalue()
117
 
 
118
 
    def process(self, write, request, submit, username, password, perspective):
119
 
        """Process the form results.
120
 
        """
121
 
        # must be done before page is displayed so cookie can get set!
122
 
        request.getSession()
123
 
        # this site must be tagged with an application.
124
 
        idrq = self.reqauth.service.authorizer.getIdentityRequest(username)
125
 
        idrq.needsHeader = 1
126
 
        idrq.addCallbacks(self.gotIdentity, self.didntGetIdentity,
127
 
                          callbackArgs=(password,request,perspective or username),
128
 
                          errbackArgs=(request,))
129
 
        return [idrq]
130
 
 
131
 
class AuthPage(widgets.Page):
132
 
    template = '''
133
 
    <html><head><title>Authorization Required</title></head>
134
 
    <body>
135
 
    <center>
136
 
    %%%%authForm%%%%
137
 
    </center>
138
 
    </body>
139
 
    </html>
140
 
    '''
141
 
    authForm = None
142
 
    def __init__(self, reqauth, sessionIdentity=None, sessionPerspective=None):
143
 
        widgets.Page.__init__(self)
144
 
        self.authForm = AuthForm(reqauth, sessionPerspective, sessionIdentity)
145
 
 
146
 
 
147
 
class WidgetGuard(widgets.Widget):
148
 
    
149
 
    def __init__(self, wid, service,
150
 
                 sessionIdentity=None,
151
 
                 sessionPerspective=None):
152
 
        self.wid = wid
153
 
        self.service = service
154
 
        self.sessionPerspective = sessionPerspective
155
 
        self.sessionIdentity = sessionIdentity
156
 
 
157
 
    def reallyRender(self, request):
158
 
        return widgets.possiblyDeferWidget(self.wid, request)
159
 
 
160
 
    def display(self, request):
161
 
        session = request.getSession()
162
 
        resKey = string.join(['AUTH',self.service.serviceName], '_')
163
 
        if hasattr(session, resKey):
164
 
            return self.wid.display(request)
165
 
        else:
166
 
            return AuthForm(self).display(request)
167
 
 
168
 
 
169
 
 
170
 
# TODO hiding forms behind a ResourceGuard sucks, because if
171
 
# ResourceGuard needs to authenticate the user, it will 1) complain
172
 
# about the form submitted, 2) throw the data away. This happens if
173
 
# you use "foo?a=b" -style URLs and the user hasn't authenticated yet,
174
 
# or with session expiry.
175
 
 
176
 
class ResourceGuard(resource.Resource):
177
 
 
178
 
    isLeaf = 1
179
 
 
180
 
    def __init__(self, res, service, sessionIdentity=None, sessionPerspective=None):
181
 
        resource.Resource.__init__(self)
182
 
        self.res = res
183
 
        self.service = service
184
 
        self.sessionPerspective = sessionPerspective
185
 
        self.sessionIdentity = sessionIdentity
186
 
 
187
 
    def __getattr__(self, k):
188
 
        if not self.__dict__.has_key("res"):
189
 
            raise AttributeError, k
190
 
        return getattr(self.res, k)
191
 
 
192
 
    def __getstate__(self):
193
 
        return self.__dict__.copy()
194
 
    
195
 
    def listNames(self):
196
 
        return self.res.listNames()
197
 
    
198
 
    def reallyRender(self, request):
199
 
        # it's authenticated already...
200
 
        res = resource.getChildForRequest(self.res, request)
201
 
        val = res.render(request)
202
 
        if val != NOT_DONE_YET:
203
 
            request.write(val)
204
 
            request.finish()
205
 
        return widgets.FORGET_IT
206
 
 
207
 
    def render(self, request):
208
 
        session = request.getSession()
209
 
        resKey = string.join(['AUTH',self.service.serviceName], '_')
210
 
        if hasattr(session, resKey):
211
 
            self.reallyRender(request)
212
 
            return NOT_DONE_YET
213
 
        else:
214
 
            return AuthPage(self,
215
 
                            self.sessionPerspective,
216
 
                            self.sessionIdentity).render(request)
217