Skip to content

Commit

Permalink
adding serviceName argument to 'attach', and identity argument to 'at…
Browse files Browse the repository at this point in the history
…tached',

and return value to 'attached' which will allow for perspective redirection.


git-svn-id: svn://svn.twistedmatrix.com/svn/Twisted/trunk@282 bbbe8e31-12d6-0310-92fd-ac37d47ddeeb
  • Loading branch information
glyph committed Aug 19, 2001
1 parent 8970008 commit 783255b
Show file tree
Hide file tree
Showing 15 changed files with 205 additions and 110 deletions.
17 changes: 16 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
# Twisted, the Framework of Your Internet
# Copyright (C) 2001 Matthew W. Lefkowitz
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Twisted - Distutils distribution files
#
# Copyright (c) 2001 by Twisted Matrix Laboratories
# All rights reserved, see LICENSE for details.
#
# $Id: MANIFEST.in,v 1.4 2001/07/10 21:49:43 jh Exp $
# $Id: MANIFEST.in,v 1.5 2001/08/19 05:15:23 glyph Exp $

include CREDITS LICENSE README
include MANIFEST.in
Expand Down
3 changes: 1 addition & 2 deletions doc/examples/pbclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,10 @@ def connected(perspective):
perspective.echo("hello world",
pbcallback=success,
pberrback=failure)

print "connected."

def preConnected(identity):
identity.attach("pbecho", None,
identity.attach("pbecho", "any", None,
pbcallback=connected,
pberrback=failure)

Expand Down
42 changes: 21 additions & 21 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
Copyright (c) 2001 by Twisted Matrix Laboratories
All rights reserved, see LICENSE for details.
$Id: setup.py,v 1.6 2001/08/18 10:34:58 moshez Exp $
$Id: setup.py,v 1.7 2001/08/19 05:15:23 glyph Exp $
"""

import distutils, os, sys
Expand Down Expand Up @@ -51,26 +51,26 @@
your toaster.
""",
'packages': [
'twisted',
'twisted.internet',
'twisted.persisted',
'twisted.pim',
'twisted.protocols',
'twisted.python',
'twisted.reality',
'twisted.reality.ui',
'twisted.spread',
'twisted.spread.ui',
'twisted.words',
'twisted.words.ui',
'twisted.words.ui.gateways',
'twisted.test',
'twisted.web',
'twisted.tap',
'twisted.mail',
'twisted.enterprise',
'twisted.manhole',
'twisted.manhole.ui',
"twisted",
"twisted.enterprise",
"twisted.internet",
"twisted.mail",
"twisted.manhole",
"twisted.manhole.ui",
"twisted.persisted",
"twisted.pim",
"twisted.protocols",
"twisted.python",
"twisted.reality",
"twisted.reality.ui",
"twisted.spread",
"twisted.spread.ui",
"twisted.tap",
"twisted.test",
"twisted.web",
"twisted.words",
"twisted.words.ui",
"twisted.words.ui.gateways",
],
}

Expand Down
71 changes: 61 additions & 10 deletions twisted/internet/passport.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,19 @@ def __init__(self, service, perspective, identity):
self.identity = identity
self.perspective = perspective

def getService(self):
"""Get the service that I am a key to.
"""
svc = self.identity.application.getService(self.service)
return svc

def getPerspective(self):
"""Get the perspective that I am a key to.
This should only be done _after_ authentication! I retrieve
identity.application[service][perspective].
"""
app = self.identity.application
svc = app.getService(self.service)
svc = self.getService()
psp = svc.getPerspectiveNamed(self.perspective)
return psp

Expand Down Expand Up @@ -110,6 +115,11 @@ def getServiceName(self):
"""
return self.serviceName

def getServiceType(self):
"""Get a string describing the type of this service.
"""
return self.serviceType or str(self.__class__)


class Perspective:
"""I am an Identity's view onto a service.
Expand Down Expand Up @@ -156,6 +166,32 @@ def getIdentityRequest(self):
return (self.service.application.authorizer.
getIdentityRequest(self.identityName))

def attached(self, reference, identity):
"""Called when a remote reference is 'attached' to me.
After being authorized, a remote actor can attach to me
through its identity. This call will be made when that happens, and
the return value of this method will be used as the _actual_
perspective to which I am attached.
Note that the symmetric call, detached, will be made on whatever
this method returns, _not_ on me. Therefore, by default I return
'self'.
"""
log.msg('attached [%s]' % str(self.__class__))
return self

def detached(self, reference, identity):
"""Called when a broker is 'detached' from me.
See 'attached'.
When a remote actor disconnects (or times out, for example, with
HTTP), this is called in order to indicate that the reference
associated with that peer is no longer attached to this perspective.
"""
log.msg('detached [%s]' % str(self.__class__))


def respond(challenge, password):
"""Respond to a challenge.
Expand All @@ -173,7 +209,11 @@ def respond(challenge, password):

class Identity:
"""An identity, with different methods for verification.
An identity represents a user's permissions with a particular
application. It is a username, a password, and a collection of
Perspective/Service name pairs, each of which is a perspective that this
identity is allowed to access.
"""
hashedPassword = None

Expand All @@ -187,31 +227,40 @@ def __init__(self, name, application):
self.application = application
self.keyring = {}

def getKey(self, serviceName):
def getKey(self, serviceName, perspectiveName):
"""Get a key from my keyring.
If that key does not exist, raise Unauthorized. This will return an
instance of a Key.
"""
if not self.keyring.has_key(serviceName):
raise Unauthorized("You have no key for %s." % serviceName)
return self.keyring[serviceName]
k = (serviceName, perspectiveName)
if not self.keyring.has_key(k):
raise Unauthorized("You have no key for %s." % k)
return self.keyring[k]

def addKeyFor(self, perspective):
"""Add a key for the given perspective.
"""
perspectiveName = perspective.getPerspectiveName()
serviceName = perspective.service.getServiceName()
self.setKey(serviceName, perspectiveName)

def setKey(self, serviceName, perspectiveName):
"""Set a key on my keyring.
This key will give me a token to access to some service in the future.
"""
self.keyring[serviceName] = Key(serviceName, perspectiveName, self)
self.keyring[(serviceName, perspectiveName)] = Key(
serviceName, perspectiveName, self)

def getAllKeys(self):
"""Returns a list of all services and perspectives this identity can connect to.
def removeKey(self, serviceName):
This returns a sequence of keys.
"""
return self.keyring.values()

def removeKey(self, serviceName, perspectiveName):
"""Remove a key from my keyring.
If this key is not present, raise Unauthorized.
Expand Down Expand Up @@ -265,6 +314,8 @@ def verifyPlainPassword(self, plaintext):
userPass = md.digest()
return (userPass == self.hashedPassword)

# TODO: service discovery through listing of self.keyring.



class Authorizer:
Expand Down
14 changes: 10 additions & 4 deletions twisted/internet/tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,16 @@ def __init__(self, host, port, protocol):
"""
if host == 'unix':
# "port" in this case is really a filename
mode = os.stat(port)[0]
assert (mode & stat.S_IFSOCK), "that's not a socket"
assert (mode & stat.S_IROTH), "that's not readable"
assert (mode & stat.S_IWOTH), "that's not writable"
try:
mode = os.stat(port)[0]
except OSError, ose:
protocol.connectionFailed() # no such file or directory
return
if not (mode & (stat.S_IFSOCK | # that's not a socket
stat.S_IROTH | # that's not readable
stat.S_IWOTH )):# that's not writable
protocol.connectionFailed()
return
# success.
self.addr = port
# we are using unix sockets
Expand Down
15 changes: 13 additions & 2 deletions twisted/reality/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,26 @@ def containedPhrase(self, observer, held):
def perspective_execute(self, st):
self.execute(st)

def attached(self, i):
def attached(self, remoteIntelligence, identity):
"""A user-interface has been attached to this player.
This equates to a message saying that they're logged in. It takes one
argument, the interface. This will be signature-compatible with
RemoteIntelligence. This is an implementation of::
twisted.internet.passport.Perspective.attached(reference, identity)
and therefore follows those rules.
"""
if hasattr(self, 'intelligence'):
log.msg("player duplicate: [%s]" % self.name)
raise authenticator.Unauthorized("Already logged in from another location.")
log.msg("player login: [%s]" % self.name)
if hasattr(self, 'oldlocation'):
self.location = self.oldlocation
del self.oldlocation
self.intelligence = LocalIntelligence(i)
self.intelligence = LocalIntelligence(remoteIntelligence)
return self

def detached(self, i):
log.msg("player logout: [%s]" % self.name)
Expand Down
22 changes: 19 additions & 3 deletions twisted/reality/plumbing.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,26 @@ def processPassword(self, password):
return "Pending"

def loggedIn(self, identity):
"""The player's identity has been retrieved. Now, check their password.
"""
if identity.verifyPlainPassword(self.pw):
k = identity.getKey(self.factory.reality.getServiceName())
p = k.getPerspective()
p.attached(self)
# The identity checks out.
characters = []
# XXX REFACTOR: Hmm. Is this next bit common behavior?
for k in identity.getAllKeys():
svc = k.getService()
if svc is self.factory.reality:
characters.append(k.getPerspective())
lc = len(characters)
if lc == 1:
p = characters[0]
elif lc > 1:
p = characters[0]
self.transport.write("TODO: character selection menu\r\n")
else:
raise passport.Unauthorized("that identity has no TR characters")

p.attached(self, identity)
self.player = p
self.transport.write("Hello "+self.player.name+", welcome to Reality!\r\n"+
telnet.IAC+telnet.WONT+telnet.ECHO)
Expand Down
5 changes: 2 additions & 3 deletions twisted/reality/reality.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,9 @@ def getPerspectiveNamed(self, playerName):
"""Get a perspective from a named player.
This will dispatch to an appropriate player by locating the named
player and calling their 'login' method. (This is to facilitate guest
logins.)
player.
"""
return self[playerName].login()
return self[playerName]

def _addThing(self,thing):
"""(internal) add a thing to this reality
Expand Down
9 changes: 0 additions & 9 deletions twisted/reality/thing.py
Original file line number Diff line number Diff line change
Expand Up @@ -726,15 +726,6 @@ def userInput(self, sentencestring):
return None


def login(self):
"""Thing.login() -> self
This returns the object that the user will actually log in to; override
this to implement a 'factory' login object, to produce guests and
suchlike.
"""
return self

ambient_ = None

def getVerb(self, verbstring, preposition):
Expand Down
2 changes: 1 addition & 1 deletion twisted/reality/ui/tkfaucet.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def doLogin(self, *ev):
broker = pb.Broker()
self.m = MainWindow()
self.m.withdraw()
# he's a hack, he's a hack
# he's a hack, he's a hack
broker.requestIdentity(username, password,
callback=self.gotIdentity,
errback=self.m.tryAgain)
Expand Down
Loading

0 comments on commit 783255b

Please sign in to comment.