def auto_register(request, backend=None, error_msgs=''): """ <Purpose> Part of the SOCIAL_AUTH_PIPELINE whose order is mapped in settings.py. If a user logs in with a OpenID/OAuth account and that account is not yet linked with a Clearinghouse account, he gets redirected here. If a valid username is entered then a new Seattle Clearinghouse user is created. <Arguments> request: An HTTP request object. backend: An OpenID/OAuth backend ex google,facebook etc. <Exceptions> <Side Effects> A new Seattle Clearinghouse user is created. <Returns> If a user passes in a valid username he continues the pipeline and moves forward in the auto register process. """ # Check if a username is provided username_form = forms.AutoRegisterForm() if request.method == 'POST' and request.POST.get('username'): name = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline') username_form = forms.AutoRegisterForm(request.POST) if username_form.is_valid(): username = username_form.cleaned_data['username'] try: interface.get_user_without_password(username) error_msgs = 'That username is already in use.' except DoesNotExistError: request.session['saved_username'] = request.POST['username'] backend = request.session[name]['backend'] return redirect('socialauth_complete', backend=backend) name = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline') backend = request.session[name]['backend'] return render_to_response( 'accounts/auto_register.html', { 'backend': backend, 'error_msgs': error_msgs, 'username_form': username_form }, RequestContext(request))
def auto_register(request,backend=None,error_msgs=''): """ <Purpose> Part of the SOCIAL_AUTH_PIPELINE whose order is mapped in settings.py. If a user logs in with a OpenID/OAuth account and that account is not yet linked with a Clearinghouse account, he gets redirected here. If a valid username is entered then a new Seattle Clearinghouse user is created. <Arguments> request: An HTTP request object. backend: An OpenID/OAuth backend ex google,facebook etc. <Exceptions> <Side Effects> A new Seattle Clearinghouse user is created. <Returns> If a user passes in a valid username he continues the pipeline and moves forward in the auto register process. """ # Check if a username is provided username_form = forms.AutoRegisterForm() if request.method == 'POST' and request.POST.get('username'): name = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline') username_form = forms.AutoRegisterForm(request.POST) if username_form.is_valid(): username = username_form.cleaned_data['username'] try: interface.get_user_without_password(username) error_msgs ='That username is already in use.' except DoesNotExistError: request.session['saved_username'] = request.POST['username'] backend = request.session[name]['backend'] return redirect('socialauth_complete', backend=backend) name = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline') backend=request.session[name]['backend'] return render_to_response('accounts/auto_register.html', {'backend' : backend, 'error_msgs' : error_msgs, 'username_form' : username_form}, RequestContext(request))
def get_encrypted_api_key(username): """ <Purpose> Retrieve the account's API key encrypted with the account's public key. This provides the holder of an account's private key a means of obtaining the SeattleGENI API key for the account. A side effect is that this also provide a means of determining whether an account exists on clearinghouse. However, we do not protect against such querying here because the same can be determined in a handful of other ways through the html interface. This approach of obtaining the encrypted api key can be removed later if we implement a way to sign requests. <Arguments> username The username of the account whose encrypted API key we want. <Exceptions> Raises xmlrpclib Fault objects with fault codes: FAULTCODE_INVALIDREQUEST if a the provided username is not a string specifying a valid (existing) account username. <Returns> An string that represents DATA encrypted by (seattlelib) rsa.r2py's rsa_encrypt() function. DATA is a string that is the concatenation of a random string of 0-9a-fA-F of fixed length, an exclamation mark, and the API key. For example, DATA may be the following string: l28yDKLQGqhqdfDquDq0433!AD98OF2308Q9RYFHDHKJAC where AD98OF2308Q9RYFHDHKJAC is the API key. Note that this random data being prepended is just a dirty workaround for the lack of random padding being used by the encryption format offered by rsa.r2py or other repy libraries. This should be changed after a repy implementation of PKCS#1 is available. """ try: assertions.assert_str(username) except AssertionError: raise xmlrpclib.Fault(FAULTCODE_INVALIDREQUEST, "Username must be a string.") try: geniuser = interface.get_user_without_password(username) except DoesNotExistError: raise xmlrpclib.Fault(FAULTCODE_INVALIDREQUEST, "Username does not exist.") # Don't change the number of bytes of random data without changing the API # spec and the xmlrpc client. randstring = ''.join(random.sample(string.letters + string.digits, ENCRYPTED_API_KEY_PADDING_BYTES)) data = randstring + "!" + geniuser.api_key data = str(data) # make sure it's type str, not unicode, as required by rsa_encrypt user_pubkey_dict = rsa.rsa_string_to_publickey(geniuser.user_pubkey) encrypted_data = rsa.rsa_encrypt(data, user_pubkey_dict) # rsa_encrypt returns returns a string with an extra space in the front. encrypted_data = encrypted_data.strip() # If the encrypted_data is more than one "block" long, something odd is # going on and there may be no padding applied to one or more encrypted # blocks. if ' ' in encrypted_data: raise InternalError("The encrypted_data to be returned by get_encrypted_api_key() " + "was more than one block long. user: "******" encrypted_data: "+ encrypted_data) return encrypted_data
def get_encrypted_api_key(username): """ <Purpose> Retrieve the account's API key encrypted with the account's public key. This provides the holder of an account's private key a means of obtaining the SeattleGENI API key for the account. A side effect is that this also provide a means of determining whether an account exists on clearinghouse. However, we do not protect against such querying here because the same can be determined in a handful of other ways through the html interface. This approach of obtaining the encrypted api key can be removed later if we implement a way to sign requests. <Arguments> username The username of the account whose encrypted API key we want. <Exceptions> Raises xmlrpclib Fault objects with fault codes: FAULTCODE_INVALIDREQUEST if a the provided username is not a string specifying a valid (existing) account username. <Returns> An string that represents DATA encrypted by (seattlelib) rsa.r2py's rsa_encrypt() function. DATA is a string that is the concatenation of a random string of 0-9a-fA-F of fixed length, an exclamation mark, and the API key. For example, DATA may be the following string: l28yDKLQGqhqdfDquDq0433!AD98OF2308Q9RYFHDHKJAC where AD98OF2308Q9RYFHDHKJAC is the API key. Note that this random data being prepended is just a dirty workaround for the lack of random padding being used by the encryption format offered by rsa.r2py or other repy libraries. This should be changed after a repy implementation of PKCS#1 is available. """ try: assertions.assert_str(username) except AssertionError: raise xmlrpclib.Fault(FAULTCODE_INVALIDREQUEST, "Username must be a string.") try: geniuser = interface.get_user_without_password(username) except DoesNotExistError: raise xmlrpclib.Fault(FAULTCODE_INVALIDREQUEST, "Username does not exist.") # Don't change the number of bytes of random data without changing the API # spec and the xmlrpc client. randstring = ''.join( random.sample(string.letters + string.digits, ENCRYPTED_API_KEY_PADDING_BYTES)) data = randstring + "!" + geniuser.api_key data = str( data ) # make sure it's type str, not unicode, as required by rsa_encrypt user_pubkey_dict = rsa.rsa_string_to_publickey(geniuser.user_pubkey) encrypted_data = rsa.rsa_encrypt(data, user_pubkey_dict) # rsa_encrypt returns returns a string with an extra space in the front. encrypted_data = encrypted_data.strip() # If the encrypted_data is more than one "block" long, something odd is # going on and there may be no padding applied to one or more encrypted # blocks. if ' ' in encrypted_data: raise InternalError( "The encrypted_data to be returned by get_encrypted_api_key() " + "was more than one block long. user: "******" encrypted_data: " + encrypted_data) return encrypted_data