def put(self, account): """ Create a new identity and map it to an account. .. :quickref: UserPass; add new userpass identity. :reqheader X-Rucio-Username: the desired username. :reqheader X-Rucio-Password: the desired password. :reqheader X-Rucio-Email: the desired email. :param account: the affected account. :status 201: Created. :status 400: Missing username or password. :status 401: Invalid Auth Token. :status 500: Internal Error. """ username = request.environ.get('HTTP_X_RUCIO_USERNAME') password = request.environ.get('HTTP_X_RUCIO_PASSWORD') email = request.environ.get('HTTP_X_RUCIO_EMAIL') if username is None or password is None: return 'Username and Password must be set.', 400 try: add_identity(username, 'userpass', email, password) except Exception as error: return error, 500 try: add_account_identity(username, 'userpass', account, email=email, password=password, issuer=request.environ.get('issuer')) except Exception as error: return error, 500 return "Created", 201
def put(self, account): """ Create a new identity and map it to an account. .. :quickref: GSS; add new GSS identity. :param account: the affected account. :reqheader X-Rucio-Email: the desired email. :status 201: Created. :status 401: Invalid Auth Token. :status 500: Internal Error. """ gsscred = request.environ.get('REMOTE_USER') email = request.environ.get('HTTP_X_RUCIO_EMAIL') try: add_identity(gsscred, 'gss', email=email) except Exception as error: return error, 500 try: add_account_identity(gsscred, 'gss', account, email=email, issuer=request.environ.get('issuer')) except Exception as error: return error, 500 return "Created", 201
def PUT(self, account): """ Create a new identity and map it to an account. HTTP Success: 201 Created HTTP Error: 400 Bad Request 401 Unauthorized 500 Internal Error :param Rucio-Auth-Token: as an 32 character hex string. :param SSLStdEnv: Apache mod_ssl SSL Standard Env Variables. :param Rucio-Email: the desired email. :param account: the affected account via URL. """ dn = ctx.env.get('SSL_CLIENT_S_DN') email = ctx.env.get('HTTP_X_RUCIO_EMAIL') try: add_identity(dn, 'x509', email=email) except Exception as error: raise InternalError(error) try: add_account_identity(dn, 'x509', account, email=email, issuer=ctx.env.get('issuer')) except Exception as error: raise InternalError(error) raise Created()
def put(self, account): """ Create a new identity and map it to an account. .. :quickref: GSS; add new GSS identity. :param account: the affected account. :reqheader X-Rucio-Email: the desired email. :status 201: Created. :status 401: Invalid Auth Token. """ gsscred = request.environ.get('REMOTE_USER') email = request.headers.get('X-Rucio-Email', default=None) add_identity(gsscred, 'gss', email=email) add_account_identity( identity_key=gsscred, id_type='gss', account=account, email=email, issuer=request.environ.get('issuer'), vo=request.environ.get('vo'), ) return 'Created', 201
def put(self, account): """ Create a new identity and map it to an account. .. :quickref: X509; add new x509 identity. :param account: the affected account. :reqheader X-Rucio-Email: the desired email. :status 201: Created. :status 401: Invalid Auth Token. :status 500: Internal Error. """ dn = request.environ.get('SSL_CLIENT_S_DN') email = request.headers.get('X-Rucio-Email') try: add_identity(dn, 'x509', email=email) except Exception as error: print(format_exc()) return str(error), 500 try: add_account_identity(dn, 'x509', account, email=email, issuer=request.environ.get('issuer'), vo=request.environ.get('vo')) except Exception as error: print(format_exc()) return str(error), 500 return 'Created', 201
def PUT(self, account): """ Create a new identity and map it to an account. HTTP Success: 201 Created HTTP Error: 400 Bad Request 401 Unauthorized 500 Internal Error :param Rucio-Auth-Token: as an 32 character hex string. :param SavedCredentials: Apache mod_auth_kerb SavedCredentials. :param Rucio-Email: the desired email. :param account: the affected account via URL. """ gsscred = ctx.env.get('REMOTE_USER') email = ctx.env.get('HTTP_X_RUCIO_EMAIL') try: add_identity(gsscred, 'gss', email=email) except Exception as error: raise InternalError(error) try: add_account_identity(gsscred, 'gss', account, email=email, issuer=ctx.env.get('issuer')) except Exception as error: raise InternalError(error) raise Created()
def put(self, account): """ Create a new identity and map it to an account. .. :quickref: X509; add new x509 identity. :param account: the affected account. :reqheader X-Rucio-Email: the desired email. :status 201: Created. :status 401: Invalid Auth Token. :status 500: Internal Error. """ dn = request.environ.get('SSL_CLIENT_S_DN') email = request.environ.get('HTTP_X_RUCIO_EMAIL') try: add_identity(dn, 'x509', email=email) except Exception as error: return error, 500 try: add_account_identity(dn, 'x509', account, email=email, issuer=request.environ.get('issuer')) except Exception as error: return error, 500 return "Created", 201
def put(self, account): """ Create a new identity and map it to an account. .. :quickref: GSS; add new GSS identity. :param account: the affected account. :reqheader X-Rucio-Email: the desired email. :status 201: Created. :status 401: Invalid Auth Token. :status 500: Internal Error. """ gsscred = request.environ.get('REMOTE_USER') email = request.headers.get('X-Rucio-Email', default=None) try: add_identity(gsscred, 'gss', email=email) except Exception as error: logging.exception("Internal Error") return str(error), 500 try: add_account_identity(gsscred, 'gss', account, email=email, issuer=request.environ.get('issuer'), vo=request.environ.get('vo')) except Exception as error: logging.exception("Internal Error") return str(error), 500 return 'Created', 201
def test_auth_saml(self): """ MULTI VO (REST): Test saml authentication to multiple VOs """ mw = [] try: add_account_identity('ddmlab', 'SAML', 'root', '*****@*****.**', 'root', **self.vo) add_account_identity('ddmlab', 'SAML', 'root', '*****@*****.**', 'root', **self.new_vo) except Duplicate: pass # Might already exist, can skip # Can't rely on `onelogin` module being present, so get tokens from API instead token_tst = get_auth_token_saml('root', 'ddmlab', 'unknown', None, **self.vo).token token_new = get_auth_token_saml('root', 'ddmlab', 'unknown', None, **self.new_vo).token headers_tst = {'X-Rucio-Auth-Token': str(token_tst)} res_tst = TestApp(account_app.wsgifunc(*mw)).get('/', headers=headers_tst, expect_errors=True) assert_equal(res_tst.status, 200) accounts_tst = [parse_response(a)['account'] for a in res_tst.body.decode().split('\n')[:-1]] assert_not_equal(len(accounts_tst), 0) assert_in(self.account_tst, accounts_tst) assert_not_in(self.account_new, accounts_tst) headers_new = {'X-Rucio-Auth-Token': str(token_new)} res_new = TestApp(account_app.wsgifunc(*mw)).get('/', headers=headers_new, expect_errors=True) assert_equal(res_new.status, 200) accounts_new = [parse_response(a)['account'] for a in res_new.body.decode().split('\n')[:-1]] assert_not_equal(len(accounts_new), 0) assert_in(self.account_new, accounts_new) assert_not_in(self.account_tst, accounts_new)
def put(self, account): """ Create a new identity and map it to an account. .. :quickref: X509; add new x509 identity. :param account: the affected account. :reqheader X-Rucio-Email: the desired email. :status 201: Created. :status 401: Invalid Auth Token. """ dn = request.environ.get('SSL_CLIENT_S_DN') email = request.headers.get('X-Rucio-Email', default=None) add_identity(dn, 'x509', email=email) add_account_identity( identity_key=dn, id_type='x509', account=account, email=email, issuer=request.environ.get('issuer'), vo=request.environ.get('vo'), ) return 'Created', 201
def put(self, account): """ Create a new identity and map it to an account. .. :quickref: UserPass; add new userpass identity. :reqheader X-Rucio-Username: the desired username. :reqheader X-Rucio-Password: the desired password. :reqheader X-Rucio-Email: the desired email. :param account: the affected account. :status 201: Created. :status 400: Missing username or password. :status 401: Invalid Auth Token. """ username = request.headers.get('X-Rucio-Username', default=None) password = request.headers.get('X-Rucio-Password', default=None) email = request.headers.get('X-Rucio-Email', default=None) if not username or not password: return 'Username and Password must be set.', 400 add_identity(username, 'userpass', email, password) add_account_identity( identity_key=username, id_type='userpass', account=account, email=email, password=password, issuer=request.environ.get('issuer'), vo=request.environ.get('vo'), ) return 'Created', 201
def post(self, account): """ Grant an identity access to an account. .. :quickref: Identities; Add identity to account. :param account: Account identifier. :<json string identity: The identity name. :<json string authtype: The auth type of the identity. :<json string email: The email address. :status 201: Successfully added. :status 400: Parameter missing. :status 401: Invalid auth token. :status 409: Already exists. :status 404: Account not found. :status 500: Database exception. """ json_data = request.data try: parameter = loads(json_data) except ValueError: return generate_http_error_flask( 400, 'ValueError', 'cannot decode json parameter dictionary') try: identity = parameter['identity'] authtype = parameter['authtype'] email = parameter['email'] password = parameter.get('password', None) default = parameter.get('default', False) except KeyError as error: if error.args[0] == 'authtype' or error.args[ 0] == 'identity' or error.args[0] == 'email': return generate_http_error_flask(400, 'KeyError', '%s not defined' % str(error)) except TypeError: return generate_http_error_flask(400, 'TypeError', 'body must be a json dictionary') try: add_account_identity(identity_key=identity, id_type=authtype, account=account, email=email, password=password, issuer=request.environ.get('issuer'), default=default) except AccessDenied as error: return generate_http_error_flask(401, 'AccessDenied', error.args[0]) except Duplicate as error: return generate_http_error_flask(409, 'Duplicate', error.args[0]) except AccountNotFound as error: return generate_http_error_flask(404, 'AccountNotFound', error.args[0]) except Exception as error: print(str(format_exc())) return error, 500 return "Created", 201
def POST(self, account): """ Grant an identity access to an account. HTTP Success: 201 Created HTTP Error: 400 Bad Reqeust 401 Unauthorized 409 Conflict 500 Internal Error :param account: Account identifier. """ json_data = data().decode() try: parameter = loads(json_data) except ValueError: raise generate_http_error( 400, 'ValueError', 'cannot decode json parameter dictionary') try: identity = parameter['identity'] authtype = parameter['authtype'] email = parameter['email'] password = parameter.get('password', None) default = parameter.get('default', False) except KeyError as error: if error.args[0] == 'authtype' or error.args[ 0] == 'identity' or error.args[0] == 'email': raise generate_http_error(400, 'KeyError', '%s not defined' % str(error)) except TypeError: raise generate_http_error(400, 'TypeError', 'body must be a json dictionary') try: add_account_identity(identity_key=identity, id_type=authtype, account=account, email=email, password=password, issuer=ctx.env.get('issuer'), default=default, vo=ctx.env.get('vo')) except AccessDenied as error: raise generate_http_error(401, 'AccessDenied', error.args[0]) except Duplicate as error: raise generate_http_error(409, 'Duplicate', error.args[0]) except AccountNotFound as error: raise generate_http_error(404, 'AccountNotFound', error.args[0]) except IdentityError as error: raise generate_http_error(400, 'IdentityError', error.args[0]) except Exception as error: print(str(format_exc())) raise InternalError(error) raise Created()
def test_api_identity(self): """ IDENTITY (API): Test external representation of identity accounts """ id_key = ''.join(random.choice(string.ascii_lowercase) for x in range(10)) add_account_identity(id_key, 'userpass', self.account_name, '*****@*****.**', 'root', default=True, password='******', **self.vo) out = list_accounts_for_identity(id_key, 'userpass') assert_in(self.account_name, out) if self.multi_vo: assert_not_in(self.account.internal, out)
class X509(MethodView): """ Manage an x509 identity for an account. """ def put(self, account): """ Create a new identity and map it to an account. .. :quickref: X509; add new x509 identity. :param account: the affected account. :status 201: Created. :status 401: Invalid Auth Token. :status 500: Internal Error. """ dn = request.environ.get('SSL_CLIENT_S_DN') try: add_identity(dn, 'x509', email=None) except Exception, error: return error, 500 try: add_account_identity(dn, 'x509', account, email=None, issuer=request.environ.get('issuer')) except Exception, error: return error, 500
class X509(RucioController): """ Manage an x509 identity for an account. """ def PUT(self, account): """ Create a new identity and map it to an account. HTTP Success: 201 Created HTTP Error: 400 Bad Request 401 Unauthorized 500 Internal Error :param Rucio-Auth-Token: as an 32 character hex string. :param SSLStdEnv: Apache mod_ssl SSL Standard Env Variables. :param account: the affected account via URL. """ dn = ctx.env.get('SSL_CLIENT_S_DN') try: add_identity(dn, 'x509', email=None) except Exception, error: raise InternalError(error) try: add_account_identity(dn, 'x509', account, email=None, issuer=ctx.env.get('issuer')) except Exception, error: raise InternalError(error)
class GSS(RucioController): """ Manage a GSS identity for an account. """ def PUT(self, account): """ Create a new identity and map it to an account. HTTP Success: 201 Created HTTP Error: 400 Bad Request 401 Unauthorized 500 Internal Error :param Rucio-Auth-Token: as an 32 character hex string. :param SavedCredentials: Apache mod_auth_kerb SavedCredentials. :param account: the affected account via URL. """ gsscred = ctx.env.get('REMOTE_USER') try: add_identity(gsscred, 'gss', email=None) except Exception, error: raise InternalError(error) try: add_account_identity(gsscred, 'gss', account, email=None, issuer=ctx.env.get('issuer')) except Exception, error: raise InternalError(error)
class GSS(MethodView): """ Manage a GSS identity for an account. """ def put(self, account): """ Create a new identity and map it to an account. .. :quickref: GSS; add new GSS identity. :param account: the affected account. :status 201: Created. :status 401: Invalid Auth Token. :status 500: Internal Error. """ gsscred = request.environ.get('REMOTE_USER') try: add_identity(gsscred, 'gss', email=None) except Exception, error: return error, 500 try: add_account_identity(gsscred, 'gss', account, email=None, issuer=request.environ.get('issuer')) except Exception, error: return error, 500
def put(self, account): """ --- summary: Create X509 identity description: Creates a new X509 identity and maps it to an account. tags: - Identity parameters: - name: account in: path description: The account for the identity. schema: type: string style: simple - name: X-Rucio-Email in: query description: The email for the identity. schema: type: string style: simple required: false responses: 201: description: OK content: application/json: schema: type: string enum: ['Created'] 401: description: Invalid Auth Token """ dn = request.environ.get('SSL_CLIENT_S_DN') email = request.headers.get('X-Rucio-Email', default=None) add_identity(dn, 'x509', email=email) add_account_identity( identity_key=dn, id_type='x509', account=account, email=email, issuer=request.environ.get('issuer'), vo=request.environ.get('vo'), ) return 'Created', 201
def test_auth_ssh(self): """ MULTI VO (REST): Test ssh authentication to multiple VOs """ mw = [] try: add_account_identity(PUBLIC_KEY, 'SSH', 'root', '*****@*****.**', 'root', **self.vo) add_account_identity(PUBLIC_KEY, 'SSH', 'root', '*****@*****.**', 'root', **self.new_vo) except Duplicate: pass # Might already exist, can skip headers_tst = {'X-Rucio-Account': 'root'} headers_tst.update(self.vo_header) res_tst = TestApp(auth_app.wsgifunc(*mw)).get('/ssh_challenge_token', headers=headers_tst, expect_errors=True) assert_equal(res_tst.status, 200) challenge_tst = str(res_tst.header('X-Rucio-SSH-Challenge-Token')) headers_tst.update({'X-Rucio-SSH-Signature': ssh_sign(PRIVATE_KEY, challenge_tst)}) res_tst = TestApp(auth_app.wsgifunc(*mw)).get('/ssh', headers=headers_tst, expect_errors=True) assert_equal(res_tst.status, 200) token_tst = str(res_tst.header('X-Rucio-Auth-Token')) headers_new = {'X-Rucio-Account': 'root'} headers_new.update(self.new_header) res_new = TestApp(auth_app.wsgifunc(*mw)).get('/ssh_challenge_token', headers=headers_new, expect_errors=True) assert_equal(res_new.status, 200) challenge_tst = str(res_new.header('X-Rucio-SSH-Challenge-Token')) headers_new.update({'X-Rucio-SSH-Signature': ssh_sign(PRIVATE_KEY, challenge_tst)}) res_new = TestApp(auth_app.wsgifunc(*mw)).get('/ssh', headers=headers_new, expect_errors=True) assert_equal(res_new.status, 200) token_new = str(res_new.header('X-Rucio-Auth-Token')) headers_tst = {'X-Rucio-Auth-Token': str(token_tst)} res_tst = TestApp(account_app.wsgifunc(*mw)).get('/', headers=headers_tst, expect_errors=True) assert_equal(res_tst.status, 200) accounts_tst = [parse_response(a)['account'] for a in res_tst.body.decode().split('\n')[:-1]] assert_not_equal(len(accounts_tst), 0) assert_in(self.account_tst, accounts_tst) assert_not_in(self.account_new, accounts_tst) headers_new = {'X-Rucio-Auth-Token': str(token_new)} res_new = TestApp(account_app.wsgifunc(*mw)).get('/', headers=headers_new, expect_errors=True) assert_equal(res_new.status, 200) accounts_new = [parse_response(a)['account'] for a in res_new.body.decode().split('\n')[:-1]] assert_not_equal(len(accounts_new), 0) assert_in(self.account_new, accounts_new) assert_not_in(self.account_tst, accounts_new)
def PUT(self, account): """ Create a new identity and map it to an account. HTTP Success: 201 Created HTTP Error: 400 Bad Request 401 Unauthorized 500 Internal Error :param Rucio-Auth-Token: as an 32 character hex string. :param Rucio-Username: the desired username. :param Rucio-Password: the desired password. :param Rucio-Email: the desired email. :param account: the affected account via URL. """ username = ctx.env.get('HTTP_X_RUCIO_USERNAME') password = ctx.env.get('HTTP_X_RUCIO_PASSWORD') email = ctx.env.get('HTTP_X_RUCIO_EMAIL') if username is None or password is None: raise BadRequest('Username and Password must be set.') try: add_identity(username, 'userpass', email, password) except Exception as error: raise InternalError(error) try: add_account_identity(username, 'userpass', account, email=email, password=password, issuer=ctx.env.get('issuer'), vo=ctx.env.get('vo')) except Exception as error: raise InternalError(error) raise Created()
def put(self, account): """ Create a new identity and map it to an account. .. :quickref: UserPass; add new userpass identity. :reqheader X-Rucio-Username: the desired username. :reqheader X-Rucio-Password: the desired password. :reqheader X-Rucio-Email: the desired email. :param account: the affected account. :status 201: Created. :status 400: Missing username or password. :status 401: Invalid Auth Token. :status 500: Internal Error. """ username = request.headers.get('X-Rucio-Username') password = request.headers.get('X-Rucio-Password') email = request.headers.get('X-Rucio-Email') if not username or not password: return 'Username and Password must be set.', 400 try: add_identity(username, 'userpass', email, password) except Exception as error: print(format_exc()) return str(error), 500 try: add_account_identity(username, 'userpass', account, email=email, password=password, issuer=request.environ.get('issuer'), vo=request.environ.get('vo')) except Exception as error: print(format_exc()) return str(error), 500 return 'Created', 201
def post(self, account): """ Grant an identity access to an account. .. :quickref: Identities; Add identity to account. :param account: Account identifier. :<json string identity: The identity name. :<json string authtype: The auth type of the identity. :<json string email: The email address. :status 201: Successfully added. :status 400: Parameter missing. :status 401: Invalid auth token. :status 409: Already exists. :status 404: Account not found. """ parameters = json_parameters() identity = param_get(parameters, 'identity') authtype = param_get(parameters, 'authtype') email = param_get(parameters, 'email') try: add_account_identity( identity_key=identity, id_type=authtype, account=account, email=email, password=param_get(parameters, 'password', default=None), issuer=request.environ.get('issuer'), default=param_get(parameters, 'default', default=False), vo=request.environ.get('vo'), ) except AccessDenied as error: return generate_http_error_flask(401, error) except Duplicate as error: return generate_http_error_flask(409, error) except AccountNotFound as error: return generate_http_error_flask(404, error) except IdentityError as error: return generate_http_error_flask(400, error) return 'Created', 201
identity = parameter['identity'] authtype = parameter['authtype'] email = parameter['email'] except KeyError, e: if e.args[0] == 'authtype' or e.args[0] == 'identity' or e.args[ 0] == 'email': raise generate_http_error(400, 'KeyError', '%s not defined' % str(e)) except TypeError: raise generate_http_error(400, 'TypeError', 'body must be a json dictionary') try: add_account_identity(identity_key=identity, id_type=authtype, account=account, email=email, issuer=ctx.env.get('issuer')) except AccessDenied, e: raise generate_http_error(401, 'AccessDenied', e.args[0][0]) except Duplicate as e: raise generate_http_error(409, 'Duplicate', e.args[0][0]) except AccountNotFound, e: raise generate_http_error(404, 'AccountNotFound', e.args[0][0]) except Exception, e: print str(format_exc()) raise InternalError(e) raise Created() def GET(self, account):
from rucio.api.account import add_account from rucio.api.identity import add_account_identity from rucio.api.scope import add_scope from rucio.api.did import add_did from rucio.api.rse import add_rse from rucio.db.sqla.util import build_database, create_root_account from rucio.core.account_limit import set_account_limit from rucio.core.rse import add_protocol, get_rse_id, add_rse_attribute if __name__ == '__main__': # Create the Database and the root account build_database() create_root_account() add_account_identity('/CN=docker client', 'x509', 'root', '*****@*****.**', issuer="root") # Create a user called jdoe add_account('jdoe', 'USER', 'test', 'root') # Add 2 scopes add_scope('user.jdoe', 'jdoe', 'root') add_scope('tests', 'root', 'root') # Create a test dataset for jdoe add_did('user.jdoe', 'test1', 'DATASET', 'root', account='jdoe') # Create 2 sites into the /tmp partition os.mkdir('/tmp/SITE2_DISK')
def post(self, account): """ --- summary: Create identity description: Grant an account identity access to an account. tags: - Account parameters: - name: account in: path description: The account identifier. schema: type: string style: simple requestBody: content: 'application/json': schema: type: object required: - identity - authtype - email properties: identity: description: The identity. type: string authtype: description: The authtype. type: string email: description: The email. type: string password: description: The password. type: string default: none default: description: Should this be the default account? type: string default: false responses: 201: description: OK content: application/json: schema: type: string enum: ["Created"] 401: description: Invalid Auth Token 404: description: Account not found 409: description: Already exists 400: description: Parameter missing """ parameters = json_parameters() identity = param_get(parameters, 'identity') authtype = param_get(parameters, 'authtype') email = param_get(parameters, 'email') try: add_account_identity( identity_key=identity, id_type=authtype, account=account, email=email, password=param_get(parameters, 'password', default=None), issuer=request.environ.get('issuer'), default=param_get(parameters, 'default', default=False), vo=request.environ.get('vo'), ) except AccessDenied as error: return generate_http_error_flask(401, error) except Duplicate as error: return generate_http_error_flask(409, error) except AccountNotFound as error: return generate_http_error_flask(404, error) except IdentityError as error: return generate_http_error_flask(400, error) return 'Created', 201
def put(self, account): """ --- summary: Create UserPass identity description: Creates a new UserPass identity and maps it to an account. tags: - Identity parameters: - name: account in: path description: The account for the identity. schema: type: string style: simple - name: X-Rucio-Username in: query description: Username for the identity. schema: type: string style: simple required: true - name: X-Rucio-Password in: query description: The password for the identity. schema: type: string style: simple required: true - name: X-Rucio-Email in: query description: The email for the identity. schema: type: string style: simple required: false responses: 201: description: OK content: application/json: schema: type: string enum: ['Created'] 401: description: Invalid Auth Token 400: description: Missing username or password. """ username = request.headers.get('X-Rucio-Username', default=None) password = request.headers.get('X-Rucio-Password', default=None) email = request.headers.get('X-Rucio-Email', default=None) if not username or not password: return 'Username and Password must be set.', 400 add_identity(username, 'userpass', email, password) add_account_identity( identity_key=username, id_type='userpass', account=account, email=email, password=password, issuer=request.environ.get('issuer'), vo=request.environ.get('vo'), ) return 'Created', 201
parameter = loads(json_data) except ValueError: raise generate_http_error(400, 'ValueError', 'cannot decode json parameter dictionary') try: identity = parameter['identity'] authtype = parameter['authtype'] email = parameter['email'] except KeyError, e: if e.args[0] == 'authtype' or e.args[0] == 'identity' or e.args[0] == 'email': raise generate_http_error(400, 'KeyError', '%s not defined' % str(e)) except TypeError: raise generate_http_error(400, 'TypeError', 'body must be a json dictionary') try: add_account_identity(identity_key=identity, type=authtype, account=account, email=email, issuer=ctx.env.get('issuer')) except AccessDenied, e: raise generate_http_error(401, 'AccessDenied', e.args[0][0]) except Duplicate as e: raise generate_http_error(409, 'Duplicate', e.args[0][0]) except AccountNotFound, e: raise generate_http_error(404, 'AccountNotFound', e.args[0][0]) except Exception, e: print str(format_exc()) raise InternalError(e) raise Created() def GET(self, account): header('Content-Type', 'application/x-json-stream') try: