1
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
2
# See LICENSE for details.
7
You probably should be using twisted.web.woven.guard instead.
11
import string, traceback
12
from cStringIO import StringIO
14
from twisted.python import log
21
from server import NOT_DONE_YET
24
warnings.warn("Please use twisted.web.woven.guard", DeprecationWarning, 2)
28
"""Detach a web session from an attached perspective.
30
This will happen when the session expires.
33
def __init__(self, session, identity, perspective):
34
self.session = session
35
self.identity = identity
36
self.perspective = perspective
37
session.notifyOnExpire(self.detach)
40
self.perspective.detached(self.session, self.identity)
46
class AuthForm(widgets.Form):
48
['string','Identity','username',''],
49
['password','Password','password',''],
50
['string','Perspective','perspective','']
53
formAcceptExtraArgs = 1
55
def __init__(self, reqauth, sessionIdentity=None, sessionPerspective=None):
56
"""Initialize, specifying various options.
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.
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
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.
71
self.reqauth = reqauth
72
self.sessionPerspective = sessionPerspective
73
self.sessionIdentity = sessionIdentity
75
def gotPerspective(self, perspective, request, ident):
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)
88
def didntGetPerspective(self, error, request):
89
log.msg('Password not verified! Error: %s' % error)
91
io.write(self.formatError("Login incorrect."))
92
self.format(self.getFormFields(request), io.write, request)
93
return [io.getvalue()]
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)
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,))
112
def didntGetIdentity(self, unauth, request):
114
io.write(self.formatError("Login incorrect."))
115
self.format(self.getFormFields(request), io.write, request)
118
def process(self, write, request, submit, username, password, perspective):
119
"""Process the form results.
121
# must be done before page is displayed so cookie can get set!
123
# this site must be tagged with an application.
124
idrq = self.reqauth.service.authorizer.getIdentityRequest(username)
126
idrq.addCallbacks(self.gotIdentity, self.didntGetIdentity,
127
callbackArgs=(password,request,perspective or username),
128
errbackArgs=(request,))
131
class AuthPage(widgets.Page):
133
<html><head><title>Authorization Required</title></head>
142
def __init__(self, reqauth, sessionIdentity=None, sessionPerspective=None):
143
widgets.Page.__init__(self)
144
self.authForm = AuthForm(reqauth, sessionPerspective, sessionIdentity)
147
class WidgetGuard(widgets.Widget):
149
def __init__(self, wid, service,
150
sessionIdentity=None,
151
sessionPerspective=None):
153
self.service = service
154
self.sessionPerspective = sessionPerspective
155
self.sessionIdentity = sessionIdentity
157
def reallyRender(self, request):
158
return widgets.possiblyDeferWidget(self.wid, request)
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)
166
return AuthForm(self).display(request)
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.
176
class ResourceGuard(resource.Resource):
180
def __init__(self, res, service, sessionIdentity=None, sessionPerspective=None):
181
resource.Resource.__init__(self)
183
self.service = service
184
self.sessionPerspective = sessionPerspective
185
self.sessionIdentity = sessionIdentity
187
def __getattr__(self, k):
188
if not self.__dict__.has_key("res"):
189
raise AttributeError, k
190
return getattr(self.res, k)
192
def __getstate__(self):
193
return self.__dict__.copy()
196
return self.res.listNames()
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:
205
return widgets.FORGET_IT
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)
214
return AuthPage(self,
215
self.sessionPerspective,
216
self.sessionIdentity).render(request)