1#------------------------------------------------------------------------------ 2# Copyright (c) 2008, Riverbank Computing Limited 3# All rights reserved. 4# 5# This software is provided without warranty under the terms of the BSD 6# license included in enthought/LICENSE.txt and may be redistributed only 7# under the conditions described in the aforementioned license. The license 8# is also available online at http://www.enthought.com/licenses/BSD.txt 9# Thanks for using Enthought open source! 10# 11# Author: Riverbank Computing Limited 12# Description: <Enthought permissions package component> 13#------------------------------------------------------------------------------ 14 15 16# Standard library imports. 17import errno 18import socket 19 20# Enthought library imports. 21from apptools.permissions.default.api import IUserStorage, UserStorageError 22from traits.api import HasTraits, provides, List, Str 23 24# Local imports. 25from proxy_server import ProxyServer 26 27 28@provides(IUserStorage) 29class UserStorage(HasTraits): 30 """This implements a user database accessed via XML RPC.""" 31 32 33 34 #### 'IUserStorage' interface ############################################# 35 36 capabilities = List(Str) 37 38 ########################################################################### 39 # 'IUserStorage' interface. 40 ########################################################################### 41 42 def add_user(self, name, description, password): 43 """Add a new user.""" 44 45 try: 46 ProxyServer.add_user(name, description, password, ProxyServer.key) 47 except Exception, e: 48 raise UserStorageError(ProxyServer.error(e)) 49 50 def authenticate_user(self, name, password): 51 """Return the tuple of the user name, description, and blob if the user 52 was successfully authenticated.""" 53 54 try: 55 key, name, description, blob = ProxyServer.authenticate_user(name, 56 password) 57 58 # We don't save the cache because we should be about to read the 59 # real permission ids and we do it then. 60 ProxyServer.cache = description, blob, [] 61 except Exception, e: 62 # See if we couldn't connect to the server. 63 if not isinstance(e, socket.error): 64 raise UserStorageError(ProxyServer.error(e)) 65 66 err, _ = e.args 67 68 if err != errno.ECONNREFUSED: 69 raise UserStorageError(ProxyServer.error(e)) 70 71 try: 72 ok = ProxyServer.read_cache() 73 except Exception, e: 74 raise UserStorageError(str(e)) 75 76 if not ok: 77 raise UserStorageError(ProxyServer.error(e)) 78 79 # We are in "disconnect" mode. 80 key = None 81 description, blob, _ = ProxyServer.cache 82 83 ProxyServer.key = key 84 85 return name, description, blob 86 87 def delete_user(self, name): 88 """Delete a new user.""" 89 90 try: 91 ProxyServer.delete_user(name, ProxyServer.key) 92 except Exception, e: 93 raise UserStorageError(ProxyServer.error(e)) 94 95 def is_empty(self): 96 """See if the database is empty.""" 97 98 # We leave it to the policy storage to answer this question. 99 return False 100 101 def matching_users(self, name): 102 """Return the full name and description of all the users that match the 103 given name.""" 104 105 try: 106 return ProxyServer.matching_users(name, ProxyServer.key) 107 except Exception, e: 108 raise UserStorageError(ProxyServer.error(e)) 109 110 def modify_user(self, name, description, password): 111 """Update the description and password for the given user.""" 112 113 try: 114 ProxyServer.modify_user(name, description, password, 115 ProxyServer.key) 116 except Exception, e: 117 raise UserStorageError(ProxyServer.error(e)) 118 119 def unauthenticate_user(self, user): 120 """Unauthenticate the given user.""" 121 122 if ProxyServer.key is None: 123 ok = True 124 else: 125 try: 126 ok = ProxyServer.unauthenticate_user(ProxyServer.key) 127 except Exception, e: 128 raise UserStorageError(ProxyServer.error(e)) 129 130 if ok: 131 ProxyServer.key = '' 132 ProxyServer.cache = None 133 134 return ok 135 136 def update_blob(self, name, blob): 137 """Update the blob for the given user.""" 138 139 # Update the cache. 140 description, _, perm_ids = ProxyServer.cache 141 ProxyServer.cache = description, blob, perm_ids 142 143 if ProxyServer.key is None: 144 # Write the cache and tell the user about any errors. 145 ProxyServer.write_cache() 146 else: 147 try: 148 ProxyServer.update_blob(name, blob, ProxyServer.key) 149 except Exception, e: 150 raise UserStorageError(ProxyServer.error(e)) 151 152 # Write the cache but ignore any errors. 153 try: 154 ProxyServer.write_cache() 155 except: 156 pass 157 158 def update_password(self, name, password): 159 """Update the password for the given user.""" 160 161 # If the remote server disappeared after the capabilities were read but 162 # before the user was authenticated then we could get here. 163 if ProxyServer.key is None: 164 raise UserStorageError("It is not possible to change password " 165 "when disconnected from the permissions server.") 166 167 try: 168 ProxyServer.update_password(name, password, ProxyServer.key) 169 except Exception, e: 170 raise UserStorageError(ProxyServer.error(e)) 171 172 ########################################################################### 173 # Trait handlers. 174 ########################################################################### 175 176 def _capabilities_default(self): 177 """Return the storage capabilities.""" 178 179 try: 180 caps = ProxyServer.capabilities() 181 except: 182 caps = [] 183 184 return caps 185