Package flumotion :: Package twisted :: Module portal
[hide private]

Source Code for Module flumotion.twisted.portal

  1  # -*- Mode: Python -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3  # 
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007 Fluendo, S.L. (www.fluendo.com). 
  6  # All rights reserved. 
  7   
  8  # This file may be distributed and/or modified under the terms of 
  9  # the GNU General Public License version 2 as published by 
 10  # the Free Software Foundation. 
 11  # This file is distributed without any warranty; without even the implied 
 12  # warranty of merchantability or fitness for a particular purpose. 
 13  # See "LICENSE.GPL" in the source distribution for more information. 
 14   
 15  # Licensees having purchased or holding a valid Flumotion Advanced 
 16  # Streaming Server license may use this file in accordance with the 
 17  # Flumotion Advanced Streaming Server Commercial License Agreement. 
 18  # See "LICENSE.Flumotion" in the source distribution for more information. 
 19   
 20  # Headers in this file shall remain intact. 
 21   
 22  """ 
 23  portal-related functionality inspired by twisted.cred.portal 
 24  """ 
 25   
 26  from twisted.spread import flavors 
 27  from twisted.internet import defer 
 28  from twisted.cred import error 
 29  from twisted.cred.portal import Portal 
 30  from twisted.python import failure, reflect 
 31  from twisted.python.components import registerAdapter 
 32   
 33  from flumotion.common import keycards, log, interfaces 
 34  from flumotion.twisted.pb import _FPortalRoot 
 35   
36 -class BouncerPortal(log.Loggable):
37 """ 38 I am a portal for an FPB server using a bouncer to decide on FPB client 39 access. 40 """ 41 42 logCategory = "BouncerPortal" 43
44 - def __init__(self, realm, bouncer):
45 """ 46 Create a BouncerPortal to a L{twisted.cred.portal.IRealm}. 47 48 @param realm: an implementor of L{twisted.cred.portal.IRealm} 49 @param bouncer: a bouncer to use for authentication 50 @type bouncer: L{flumotion.component.bouncers.bouncer.Bouncer} 51 """ 52 self.realm = realm 53 self.bouncer = bouncer 54 self._adminCounter = 0
55
56 - def getKeycardClasses(self):
57 """ 58 Return the Keycard interfaces supported by this portal's bouncer. 59 60 @rtype: L{defer.Deferred} firing list of str 61 """ 62 if not self.bouncer: 63 self.error('No bouncer configured, no logins possible') 64 list = [reflect.qual(k) for k in self.bouncer.keycardClasses] 65 return defer.succeed(list)
66
67 - def login(self, keycard, mind, *ifaces):
68 """ 69 Log in the keycard to the portal using the bouncer. 70 71 @param keycard: the keycard used to login 72 @type keycard: L{flumotion.common.keycards.Keycard} 73 @param mind: a reference to the client-side requester 74 @type mind: L{twisted.spread.pb.RemoteReference} 75 @param ifaces: a list of interfaces for the perspective that the 76 mind wishes to attach to 77 78 @returns: a deferred, which will fire a tuple of 79 (interface, avatarAspect, logout) or None. 80 """ 81 self.debug("_login(keycard=%r, mind=%r, ifaces=%r)" % ( 82 keycard, mind, ifaces)) 83 if not self.bouncer: 84 self.warning("no bouncer, refusing login") 85 return defer.succeed(None) 86 else: 87 d = defer.maybeDeferred(self.bouncer.authenticate, keycard) 88 89 d.addCallback(self._authenticateCallback, mind, *ifaces) 90 return d
91
92 - def _authenticateCallback(self, result, mind, *ifaces):
93 # we either got a keycard as result, or None from the bouncer 94 if not result: 95 # just like a checker, we return a failure object 96 f = failure.Failure(error.UnauthorizedLogin()) 97 self.info("unauthorized login for interfaces %r", ifaces) 98 return f 99 100 keycard = result 101 if not keycard.state == keycards.AUTHENTICATED: 102 # challenge 103 self.log('returning keycard for further authentication') 104 return keycard 105 106 # this is where we request the Avatar and can influence naming 107 108 self.debug('authenticated login of %r into realm %r', keycard, 109 self.realm) 110 111 if interfaces.IAdminMedium in ifaces: 112 # we decide on a unique name for admin clients here 113 keycard.avatarId = "admin-%06x" % self._adminCounter 114 self._adminCounter += 1 115 116 self.log('calling %r.requestAvatar(keycard=%r, mind=%r, ifaces=%r)', 117 self.realm, keycard, mind, ifaces) 118 119 return self.realm.requestAvatar(keycard.avatarId, keycard, mind, *ifaces)
120 registerAdapter(_FPortalRoot, BouncerPortal, flavors.IPBRoot) 121