Package openid :: Package yadis :: Module manager
[frames] | no frames]

Source Code for Module openid.yadis.manager

1 -class YadisServiceManager(object):
2 """Holds the state of a list of selected Yadis services, managing 3 storing it in a session and iterating over the services in order.""" 4
5 - def __init__(self, starting_url, yadis_url, services, session_key):
6 # The URL that was used to initiate the Yadis protocol 7 self.starting_url = starting_url 8 9 # The URL after following redirects (the identifier) 10 self.yadis_url = yadis_url 11 12 # List of service elements 13 self.services = list(services) 14 15 self.session_key = session_key 16 17 # Reference to the current service object 18 self._current = None
19
20 - def __len__(self):
21 """How many untried services remain?""" 22 return len(self.services)
23
24 - def __iter__(self):
25 return self
26
27 - def next(self):
28 """Return the next service 29 30 self.current() will continue to return that service until the 31 next call to this method.""" 32 try: 33 self._current = self.services.pop(0) 34 except IndexError: 35 raise StopIteration 36 else: 37 return self._current
38
39 - def current(self):
40 """Return the current service. 41 42 Returns None if there are no services left. 43 """ 44 return self._current
45
46 - def forURL(self, url):
47 return url in [self.starting_url, self.yadis_url]
48
49 - def started(self):
50 """Has the first service been returned?""" 51 return self._current is not None
52
53 - def store(self, session):
54 """Store this object in the session, by its session key.""" 55 session[self.session_key] = self
56
57 -class Discovery(object):
58 """State management for discovery. 59 60 High-level usage pattern is to call .getNextService(discover) in 61 order to find the next available service for this user for this 62 session. Once a request completes, call .finish() to clean up the 63 session state. 64 65 @ivar session: a dict-like object that stores state unique to the 66 requesting user-agent. This object must be able to store 67 serializable objects. 68 69 @ivar url: the URL that is used to make the discovery request 70 71 @ivar session_key_suffix: The suffix that will be used to identify 72 this object in the session object. 73 """ 74 75 DEFAULT_SUFFIX = 'auth' 76 PREFIX = '_yadis_services_' 77
78 - def __init__(self, session, url, session_key_suffix=None):
79 """Initialize a discovery object""" 80 self.session = session 81 self.url = url 82 if session_key_suffix is None: 83 session_key_suffix = self.DEFAULT_SUFFIX 84 85 self.session_key_suffix = session_key_suffix
86
87 - def getNextService(self, discover):
88 """Return the next authentication service for the pair of 89 user_input and session. This function handles fallback. 90 91 92 @param discover: a callable that takes a URL and returns a 93 list of services 94 95 @type discover: str -> [service] 96 97 98 @return: the next available service 99 """ 100 manager = self.getManager() 101 if manager is not None and not manager: 102 self.destroyManager() 103 104 if not manager: 105 yadis_url, services = discover(self.url) 106 manager = self.createManager(services, yadis_url) 107 108 if manager: 109 service = manager.next() 110 manager.store(self.session) 111 else: 112 service = None 113 114 return service
115
116 - def cleanup(self, force=False):
117 """Clean up Yadis-related services in the session and return 118 the most-recently-attempted service from the manager, if one 119 exists. 120 121 @param force: True if the manager should be deleted regardless 122 of whether it's a manager for self.url. 123 124 @return: current service endpoint object or None if there is 125 no current service 126 """ 127 manager = self.getManager(force=force) 128 if manager is not None: 129 service = manager.current() 130 self.destroyManager(force=force) 131 else: 132 service = None 133 134 return service
135 136 ### Lower-level methods 137
138 - def getSessionKey(self):
139 """Get the session key for this starting URL and suffix 140 141 @return: The session key 142 @rtype: str 143 """ 144 return self.PREFIX + self.session_key_suffix
145
146 - def getManager(self, force=False):
147 """Extract the YadisServiceManager for this object's URL and 148 suffix from the session. 149 150 @param force: True if the manager should be returned 151 regardless of whether it's a manager for self.url. 152 153 @return: The current YadisServiceManager, if it's for this 154 URL, or else None 155 """ 156 manager = self.session.get(self.getSessionKey()) 157 if (manager is not None and (manager.forURL(self.url) or force)): 158 return manager 159 else: 160 return None
161
162 - def createManager(self, services, yadis_url=None):
163 """Create a new YadisService Manager for this starting URL and 164 suffix, and store it in the session. 165 166 @raises KeyError: When I already have a manager. 167 168 @return: A new YadisServiceManager or None 169 """ 170 key = self.getSessionKey() 171 if self.getManager(): 172 raise KeyError('There is already a %r manager for %r' % 173 (key, self.url)) 174 175 if not services: 176 return None 177 178 manager = YadisServiceManager(self.url, yadis_url, services, key) 179 manager.store(self.session) 180 return manager
181
182 - def destroyManager(self, force=False):
183 """Delete any YadisServiceManager with this starting URL and 184 suffix from the session. 185 186 If there is no service manager or the service manager is for a 187 different URL, it silently does nothing. 188 189 @param force: True if the manager should be deleted regardless 190 of whether it's a manager for self.url. 191 """ 192 if self.getManager(force=force) is not None: 193 key = self.getSessionKey() 194 del self.session[key]
195