| OLD | NEW |
| (Empty) |
| 1 # -*- test-case-name: twisted.test.test_newcred -*- | |
| 2 | |
| 3 # Copyright (c) 2001-2007 Twisted Matrix Laboratories. | |
| 4 # See LICENSE for details. | |
| 5 | |
| 6 """ | |
| 7 The point of integration of application and authentication. | |
| 8 """ | |
| 9 | |
| 10 | |
| 11 from twisted.internet import defer | |
| 12 from twisted.internet.defer import maybeDeferred | |
| 13 from twisted.python import failure, reflect | |
| 14 from twisted.cred import error | |
| 15 from zope.interface import providedBy, Interface | |
| 16 | |
| 17 | |
| 18 class IRealm(Interface): | |
| 19 """ | |
| 20 The realm connects application-specific objects to the | |
| 21 authentication system. | |
| 22 """ | |
| 23 def requestAvatar(avatarId, mind, *interfaces): | |
| 24 """ | |
| 25 Return avatar which provides one of the given interfaces. | |
| 26 | |
| 27 @param avatarId: a string that identifies an avatar, as returned by | |
| 28 L{ICredentialsChecker.requestAvatarId<twisted.cred.checkers.ICredent
ialsChecker.requestAvatarId>} | |
| 29 (via a Deferred). Alternatively, it may be | |
| 30 C{twisted.cred.checkers.ANONYMOUS}. | |
| 31 @param mind: usually None. See the description of mind in | |
| 32 L{Portal.login}. | |
| 33 @param interfaces: the interface(s) the returned avatar should | |
| 34 implement, e.g. C{IMailAccount}. See the description of | |
| 35 L{Portal.login}. | |
| 36 | |
| 37 @returns: a deferred which will fire a tuple of (interface, | |
| 38 avatarAspect, logout), or the tuple itself. The interface will be | |
| 39 one of the interfaces passed in the 'interfaces' argument. The | |
| 40 'avatarAspect' will implement that interface. The 'logout' object | |
| 41 is a callable which will detach the mind from the avatar. | |
| 42 """ | |
| 43 | |
| 44 | |
| 45 class Portal: | |
| 46 """ | |
| 47 A mediator between clients and a realm. | |
| 48 | |
| 49 A portal is associated with one Realm and zero or more credentials checkers. | |
| 50 When a login is attempted, the portal finds the appropriate credentials | |
| 51 checker for the credentials given, invokes it, and if the credentials are | |
| 52 valid, retrieves the appropriate avatar from the Realm. | |
| 53 | |
| 54 This class is not intended to be subclassed. Customization should be done | |
| 55 in the realm object and in the credentials checker objects. | |
| 56 """ | |
| 57 def __init__(self, realm, checkers=()): | |
| 58 """ | |
| 59 Create a Portal to a L{IRealm}. | |
| 60 """ | |
| 61 self.realm = realm | |
| 62 self.checkers = {} | |
| 63 for checker in checkers: | |
| 64 self.registerChecker(checker) | |
| 65 | |
| 66 def listCredentialsInterfaces(self): | |
| 67 """ | |
| 68 Return list of credentials interfaces that can be used to login. | |
| 69 """ | |
| 70 return self.checkers.keys() | |
| 71 | |
| 72 def registerChecker(self, checker, *credentialInterfaces): | |
| 73 if not credentialInterfaces: | |
| 74 credentialInterfaces = checker.credentialInterfaces | |
| 75 for credentialInterface in credentialInterfaces: | |
| 76 self.checkers[credentialInterface] = checker | |
| 77 | |
| 78 def login(self, credentials, mind, *interfaces): | |
| 79 """ | |
| 80 @param credentials: an implementor of | |
| 81 L{twisted.cred.credentials.ICredentials} | |
| 82 | |
| 83 @param mind: an object which implements a client-side interface for | |
| 84 your particular realm. In many cases, this may be None, so if the | |
| 85 word 'mind' confuses you, just ignore it. | |
| 86 | |
| 87 @param interfaces: list of interfaces for the perspective that the mind | |
| 88 wishes to attach to. Usually, this will be only one interface, for | |
| 89 example IMailAccount. For highly dynamic protocols, however, this | |
| 90 may be a list like (IMailAccount, IUserChooser, IServiceInfo). To | |
| 91 expand: if we are speaking to the system over IMAP, any information | |
| 92 that will be relayed to the user MUST be returned as an | |
| 93 IMailAccount implementor; IMAP clients would not be able to | |
| 94 understand anything else. Any information about unusual status | |
| 95 would have to be relayed as a single mail message in an | |
| 96 otherwise-empty mailbox. However, in a web-based mail system, or a | |
| 97 PB-based client, the ``mind'' object inside the web server | |
| 98 (implemented with a dynamic page-viewing mechanism such as woven) | |
| 99 or on the user's client program may be intelligent enough to | |
| 100 respond to several ``server''-side interfaces. | |
| 101 | |
| 102 @return: A deferred which will fire a tuple of (interface, | |
| 103 avatarAspect, logout). The interface will be one of the interfaces | |
| 104 passed in the 'interfaces' argument. The 'avatarAspect' will | |
| 105 implement that interface. The 'logout' object is a callable which | |
| 106 will detach the mind from the avatar. It must be called when the | |
| 107 user has conceptually disconnected from the service. Although in | |
| 108 some cases this will not be in connectionLost (such as in a | |
| 109 web-based session), it will always be at the end of a user's | |
| 110 interactive session. | |
| 111 """ | |
| 112 for i in self.checkers: | |
| 113 if i.providedBy(credentials): | |
| 114 return maybeDeferred(self.checkers[i].requestAvatarId, credentia
ls | |
| 115 ).addCallback(self.realm.requestAvatar, mind, *interfaces | |
| 116 ) | |
| 117 ifac = providedBy(credentials) | |
| 118 return defer.fail(failure.Failure(error.UnhandledCredentials( | |
| 119 "No checker for %s" % ', '.join(map(reflect.qual, ifac))))) | |
| 120 | |
| OLD | NEW |