def dispatch_to_register(): """Force user creation on login or register""" request = strategy.request data['terms_of_service'] = True data['honor_code'] = True data['password'] = make_random_password() # force name creation if it is empty in sso-profile data['name'] = ' '.join([data.get('firstname', ''), data.get('lastname', '')]).strip() or data['username'] data['provider'] = backend.name if request.session.get('ExternalAuthMap'): del request.session['ExternalAuthMap'] try: user = User.objects.get(email=data['email']) except User.DoesNotExist: create_account_with_params(request, data) user = request.user user.first_name = data.get('firstname') user.last_name = data.get('lastname') user.is_active = True user.save() return {'user': user}
def dispatch_to_register(): """Force user creation on login or register""" request = strategy.request data['terms_of_service'] = True data['honor_code'] = True data['password'] = make_random_password() # force name creation if it is empty in sso-profile data['name'] = ' '.join([data['firstname'], data['lastname'] ]).strip() or data['username'] data['provider'] = backend.name if request.session.get('ExternalAuthMap'): del request.session['ExternalAuthMap'] try: user = User.objects.get(email=data['email']) except User.DoesNotExist: try: create_account_with_params(request, data) except AccountValidationError: data['username'] = data['email'] create_account_with_params(request, data) user = request.user user.is_active = True user.set_unusable_password() user.save() del data['password'] return {'user': user}
def dispatch_to_register(): """Redirects to the registration page.""" request = strategy.request data = kwargs['response'] data['terms_of_service'] = True data['honor_code'] = True data['password'] = '******' data['name'] = ' '.join([data['firstname'], data['lastname']]) data['provider'] = backend.name if request.session.get('ExternalAuthMap'): del request.session['ExternalAuthMap'] if User.objects.filter(email=data['email']).exists(): return redirect(AUTH_DISPATCH_URLS[AUTH_ENTRY_LOGIN]) create_account_with_params(request, data) user = request.user user.is_active = True user.save() set_logged_in_cookies(request, JsonResponse({"success": True})) # add roles for User add_user_roles(user, data['permissions']) return redirect(AUTH_DISPATCH_URLS[AUTH_ENTRY_LOGIN])
def dispatch_to_register(): """Force user creation on login or register""" request = strategy.request data['terms_of_service'] = "True" data['honor_code'] = 'True' data['password'] = make_random_password() data['provider'] = backend.name if request.session.get('ExternalAuthMap'): del request.session['ExternalAuthMap'] try: user = User.objects.get(email=data['email']) except User.DoesNotExist: create_account_with_params(request, data) user = request.user user.first_name = data['first_name'] user.last_name = data['last_name'] user.is_active = True user.save() CourseCreator.objects.get_or_create( user=user, state=CourseCreator.UNREQUESTED ) return {'user': user}
def dispatch_to_register(): """Force user creation on login or register""" request = strategy.request data['terms_of_service'] = "True" data['honor_code'] = 'True' data['password'] = make_random_password() data['provider'] = backend.name if request.session.get('ExternalAuthMap'): del request.session['ExternalAuthMap'] try: user = User.objects.get(email=data['email']) except User.DoesNotExist: create_account_with_params(request, data) user = request.user user.first_name = data['first_name'] user.last_name = data['last_name'] user.is_active = True user.save() CourseCreator.objects.get_or_create( user=user, state=CourseCreator.UNREQUESTED) return {'user': user}
def create_user(self, *args, **kwargs): """ # Creates user using information provided by pipeline. This method is called in create_user pipeline step. # Unless the workflow is changed, create_user immediately terminates if the user already found/ # So far, user is either created in ensure_user_information via registration form or account needs to be # autoprovisioned. So, this method is only called when autoprovisioning account. """ from student.views import create_account_with_params from .pipeline import make_random_password user_fields = dict(kwargs) # needs to be >2 chars to pass validation name = self._ensure_passes_length_check( user_fields, 'fullname', self.setting("THIRD_PARTY_AUTH_FALLBACK_FULL_NAME") ) password = self._ensure_passes_length_check(user_fields, 'password', make_random_password()) user_fields['name'] = name user_fields['password'] = password user_fields['honor_code'] = True user_fields['terms_of_service'] = True if not user_fields.get('email'): user_fields['email'] = "{username}@{domain}".format( username=user_fields['username'], domain=self.setting("FAKE_EMAIL_DOMAIN") ) # when autoprovisioning we need to skip email activation, hence skip_email is True return create_account_with_params(self.request, user_fields, skip_email=True)
def dispatch_to_register(): """Redirects to the registration page.""" request = strategy.request data = kwargs['response'] data['terms_of_service'] = True data['honor_code'] = True data['password'] = '******' data['name'] = ' '.join([data['firstname'], data['lastname']]) data['provider'] = backend.name if request.session.get('ExternalAuthMap'): del request.session['ExternalAuthMap'] create_account_with_params(request, data) user = request.user user.is_active = True user.save() set_logged_in_cookies(request, JsonResponse({"success": True})) return redirect(AUTH_DISPATCH_URLS[AUTH_ENTRY_LOGIN])
def dispatch_to_register(): """Force user creation on login or register""" request = strategy.request data["terms_of_service"] = True data["honor_code"] = True data["password"] = make_random_password() # force name creation if it is empty in sso-profile data["name"] = " ".join([data.get("firstname", ""), data.get("lastname", "")]).strip() or data["username"] data["provider"] = backend.name if request.session.get("ExternalAuthMap"): del request.session["ExternalAuthMap"] try: user = User.objects.get(email=data["email"]) except User.DoesNotExist: create_account_with_params(request, data) user = request.user user.is_active = True user.save() return {"user": user}
def post(self, request): """Create the user's account. You must send all required form fields with the request. You can optionally send a "course_id" param to indicate in analytics events that the user registered while enrolling in a particular course. Arguments: request (HTTPRequest) Returns: HttpResponse: 200 on success HttpResponse: 400 if the request is not valid. HttpResponse: 409 if an account with the given username or email address already exists HttpResponse: 403 operation not allowed """ data = request.POST.copy() email = data.get('email') username = data.get('username') # Handle duplicate email/username conflicts = check_account_exists(email=email, username=username) if conflicts: conflict_messages = { "email": _( # Translators: This message is shown to users who attempt to create a new # account using an email address associated with an existing account. u"It looks like {email_address} belongs to an existing account. " u"Try again with a different email address.").format( email_address=email), "username": _( # Translators: This message is shown to users who attempt to create a new # account using a username associated with an existing account. u"It looks like {username} belongs to an existing account. " u"Try again with a different username.").format( username=username), } errors = { field: [{ "user_message": conflict_messages[field] }] for field in conflicts } return JsonResponse(errors, status=409) # Backwards compatibility: the student view expects both # terms of service and honor code values. Since we're combining # these into a single checkbox, the only value we may get # from the new view is "honor_code". # Longer term, we will need to make this more flexible to support # open source installations that may have separate checkboxes # for TOS, privacy policy, etc. if data.get("honor_code") and "terms_of_service" not in data: data["terms_of_service"] = data["honor_code"] try: user = create_account_with_params(request, data) except ValidationError as err: # Should only get non-field errors from this function assert NON_FIELD_ERRORS not in err.message_dict # Only return first error for each field errors = { field: [{ "user_message": error } for error in error_list] for field, error_list in err.message_dict.items() } return JsonResponse(errors, status=400) except PermissionDenied: return HttpResponseForbidden(_("Account creation not allowed.")) response = JsonResponse({"success": True}) set_logged_in_cookies(request, response, user) return response
def post(self, request): """Create the user's account. You must send all required form fields with the request. You can optionally send a "course_id" param to indicate in analytics events that the user registered while enrolling in a particular course. Arguments: request (HTTPRequest) Returns: HttpResponse: 200 on success HttpResponse: 400 if the request is not valid. HttpResponse: 409 if an account with the given username or email address already exists """ data = request.POST.copy() email = data.get('email') username = data.get('username') # Handle duplicate email/username conflicts = check_account_exists(email=email, username=username) if conflicts: conflict_messages = { "email": _( # Translators: This message is shown to users who attempt to create a new # account using an email address associated with an existing account. u"It looks like {email_address} belongs to an existing account. " u"Try again with a different email address." ).format(email_address=email), "username": _( # Translators: This message is shown to users who attempt to create a new # account using a username associated with an existing account. u"It looks like {username} belongs to an existing account. " u"Try again with a different username." ).format(username=username), } errors = { field: [{"user_message": conflict_messages[field]}] for field in conflicts } return JsonResponse(errors, status=409) # Backwards compatibility: the student view expects both # terms of service and honor code values. Since we're combining # these into a single checkbox, the only value we may get # from the new view is "honor_code". # Longer term, we will need to make this more flexible to support # open source installations that may have separate checkboxes # for TOS, privacy policy, etc. if data.get("honor_code") and "terms_of_service" not in data: data["terms_of_service"] = data["honor_code"] try: user = create_account_with_params(request, data) except ValidationError as err: # Should only get non-field errors from this function assert NON_FIELD_ERRORS not in err.message_dict # Only return first error for each field errors = { field: [{"user_message": error} for error in error_list] for field, error_list in err.message_dict.items() } return JsonResponse(errors, status=400) response = JsonResponse({"success": True}) set_logged_in_cookies(request, response, user) return response
def post(self, request): """Create the user's account. You must send all required form fields with the request. You can optionally send a "course_id" param to indicate in analytics events that the user registered while enrolling in a particular course. Arguments: request (HTTPRequest) Returns: HttpResponse: 200 on success HttpResponse: 400 if the request is not valid. HttpResponse: 409 if an account with the given username or email address already exists HttpResponse: 403 operation not allowed """ import logging import datetime LOGGER = logging.getLogger(__name__) start_time = datetime.datetime.now() data = request.POST.copy() email = data.get('email') username = data.get('username') LOGGER.info( "*************** Request received for registration Username = {username}. Start time {start_time}: **************" .format(username=username, start_time=start_time)) # Handle duplicate email/username conflicts = check_account_exists(email=email, username=username) if conflicts: conflict_messages = { "email": accounts.EMAIL_CONFLICT_MSG.format(email_address=email), "username": accounts.USERNAME_CONFLICT_MSG.format(username=username), } errors = { field: [{ "user_message": conflict_messages[field] }] for field in conflicts } LOGGER.info( "*************** Registration failed for Username. Error: Username and email conflicts **************" .format(username=username)) return JsonResponse(errors, status=409) # Backwards compatibility: the student view expects both # terms of service and honor code values. Since we're combining # these into a single checkbox, the only value we may get # from the new view is "honor_code". # Longer term, we will need to make this more flexible to support # open source installations that may have separate checkboxes # for TOS, privacy policy, etc. if data.get("honor_code") and "terms_of_service" not in data: data["terms_of_service"] = data["honor_code"] try: user = create_account_with_params(request, data) except AccountValidationError as err: errors = {err.field: [{"user_message": text_type(err)}]} LOGGER.info( "*************** Registration failed for Username = {username}. Error: {error} **************" .format(username=username, error=err)) return JsonResponse(errors, status=409) except ValidationError as err: # Should only get non-field errors from this function assert NON_FIELD_ERRORS not in err.message_dict # Only return first error for each field errors = { field: [{ "user_message": error } for error in error_list] for field, error_list in err.message_dict.items() } LOGGER.info( "*************** Registration failed for Username = {username}. Error: {error} **************" .format(username=username, error=err)) return JsonResponse(errors, status=400) except PermissionDenied: LOGGER.info( "*************** Registration failed for Username. Error: PermissionDenied **************" .format(username=username)) return HttpResponseForbidden(_("Account creation not allowed.")) except Exception as err: LOGGER.exception( "*************** Registration failed for Username = {username}. Error: {error}" .format(username=username, error=err)) response = JsonResponse({"success": True}) set_logged_in_cookies(request, response, user) end_time = datetime.datetime.now() LOGGER.info( "*************** Request completed for registration Username = {username}. End time: {end_time} **************" .format(username=username, end_time=end_time)) time_diff = end_time - start_time LOGGER.info( "*************** Time Difference for User = {username}: {time_diff} **************" .format(username=username, time_diff=time_diff)) return response
def post(self, request): """Create the user's account. You must send all required form fields with the request. You can optionally send a "course_id" param to indicate in analytics events that the user registered while enrolling in a particular course. Arguments: request (HTTPRequest) Returns: HttpResponse: 200 on success HttpResponse: 400 if the request is not valid. HttpResponse: 409 if an account with the given username or email address already exists HttpResponse: 403 operation not allowed """ data = request.POST.copy() email = data.get('email') username = data.get('username') # Handle duplicate email/username conflicts = check_account_exists(email=email, username=username) if conflicts: conflict_messages = { "email": accounts.EMAIL_CONFLICT_MSG.format(email_address=email), "username": accounts.USERNAME_CONFLICT_MSG.format(username=username), } errors = { field: [{"user_message": conflict_messages[field]}] for field in conflicts } return JsonResponse(errors, status=409) # Backwards compatibility: the student view expects both # terms of service and honor code values. Since we're combining # these into a single checkbox, the only value we may get # from the new view is "honor_code". # Longer term, we will need to make this more flexible to support # open source installations that may have separate checkboxes # for TOS, privacy policy, etc. if data.get("honor_code") and "terms_of_service" not in data: data["terms_of_service"] = data["honor_code"] try: user = create_account_with_params(request, data) except AccountValidationError as err: errors = { err.field: [{"user_message": text_type(err)}] } return JsonResponse(errors, status=409) except ValidationError as err: # Should only get non-field errors from this function assert NON_FIELD_ERRORS not in err.message_dict # Only return first error for each field errors = { field: [{"user_message": error} for error in error_list] for field, error_list in err.message_dict.items() } return JsonResponse(errors, status=400) except PermissionDenied: return HttpResponseForbidden(_("Account creation not allowed.")) response = JsonResponse({"success": True}) set_logged_in_cookies(request, response, user) return response
def ensure_user_information( strategy, auth_entry, backend=None, user=None, social=None, allow_inactive_user=False, *args, **kwargs ): """ Ensure that we have the necessary information about a user to proceed with the pipeline. Either an existing account or registration data. """ data = {} try: if 'data' in kwargs['response']: user_data = kwargs['response']['data'][0] else: user_data = kwargs['response'] log.info('Get user data: %s', str(user_data)) access_token = kwargs['response']['access_token'] country = user_data.get('country') if not country: log.info('No country in response.') # Received fields could be pretty different from the expected, mandatory are only 'username' and 'email' data['username'] = user_data.get('username', user_data.get('name')) data['first_name'] = user_data.get('firstName', user_data.get('first_name')) data['last_name'] = user_data.get('lastName', user_data.get('last_name')) data['email'] = user_data.get('email') data['country'] = country data['access_token'] = access_token if any((data['first_name'], data['last_name'])): data['name'] = '{} {}'.format(['first_name'], data['last_name']).strip() else: data['name'] = user_data.get('username') if not all((data['username'], data['email'])): raise AuthEntryError( backend, "One of the required parameters (username or email) is not received with the user data." ) except AuthEntryError as e: log.exception(e) raise except Exception as e: log.exception(e) raise AuthEntryError(backend, "Cannot receive user's data") if not user: request = strategy.request data['terms_of_service'] = "True" data['honor_code'] = 'True' data['password'] = make_random_password() data['provider'] = backend.name try: user = User.objects.get(email=data['email']) except User.DoesNotExist: create_account_with_params(request, data) user.is_active = True user.save() return {'user': user}
def create(self, request): """Creates a new user account for the site that calls this view To use, perform a token authenticated POST to the URL:: /tahoe/api/v1/registrations/ Required arguments (JSON data): "username" "email" "name" Optional arguments: "password" "send_activation_email" Returns: HttpResponse: 200 on success, {"user_id ": 9} HttpResponse: 400 if the request is not valid. HttpResponse: 409 if an account with the given username or email address already exists The code here is adapted from the LMS ``appsembler_api`` bulk registration code. See the ``appsembler/ginkgo/master`` branch """ data = request.data password_provided = 'password' in data # set the honor_code and honor_code like checked, # so we can use the already defined methods for creating an user data['honor_code'] = "True" data['terms_of_service'] = "True" if password_provided: if 'send_activation_email' in data and data[ 'send_activation_email'] == "False": data['send_activation_email'] = False else: data['send_activation_email'] = True else: data['password'] = create_password() data['send_activation_email'] = False email = request.data.get('email') username = request.data.get('username') # Handle duplicate email/username conflicts = check_account_exists(email=email, username=username) if conflicts: errors = {"user_message": "User already exists"} return Response(errors, status=409) try: user = create_account_with_params( request=request, params=data, send_activation_email_flag=data['send_activation_email']) # set the user as active if password is provided # meaning we don't have to send a password reset email user.is_active = password_provided user.save() user_id = user.id if not password_provided: success = send_password_reset_email(request) if not success: log.error('Tahoe Reg API: Error sending password reset ' 'email to user {}'.format(user.username)) except ValidationError as err: log.error('ValidationError. err={}'.format(err)) # Should only get non-field errors from this function assert NON_FIELD_ERRORS not in err.message_dict # Only return first error for each field # TODO: Let's give a clue as to which are the error causing fields errors = {"user_message": "Invalid parameters on user creation"} return Response(errors, status=400) return Response({'user_id ': user_id}, status=200)
def post(self, request): """Create the user's account. You must send all required form fields with the request. You can optionally send a "course_id" param to indicate in analytics events that the user registered while enrolling in a particular course. Arguments: request (HTTPRequest) Returns: HttpResponse: 200 on success HttpResponse: 400 if the request is not valid. HttpResponse: 409 if an account with the given username or email address already exists HttpResponse: 403 operation not allowed """ data = request.POST.copy() # Decrypt form data if it is encrypted if 'data_token' in request.POST: data_token = request.POST.get('data_token') try: decoded_data = jwt.decode( data_token, settings.EDRAAK_LOGISTRATION_SECRET_KEY, verify=False, algorithms=[ settings.EDRAAK_LOGISTRATION_SIGNING_ALGORITHM ]) data.update(decoded_data) except jwt.ExpiredSignatureError: err_msg = u"The provided data_token has been expired" log.warning(err_msg) return JsonResponse({ "success": False, "value": err_msg, }, status=400) except jwt.DecodeError: err_msg = u"Signature verification failed" log.warning(err_msg) return JsonResponse({ "success": False, "value": err_msg, }, status=400) except (jwt.InvalidTokenError, ValueError): err_msg = u"Invalid token" log.warning(err_msg) return JsonResponse({ "success": False, "value": err_msg, }, status=400) email = data.get('email') username = data.get('username') # Handle duplicate email/username conflicts = check_account_exists(email=email, username=username) if conflicts: conflict_messages = { "email": accounts.EMAIL_CONFLICT_MSG.format(email_address=email), "username": accounts.USERNAME_CONFLICT_MSG.format(username=username), } errors = { field: [{ "user_message": conflict_messages[field] }] for field in conflicts } return JsonResponse(errors, status=409) # Backwards compatibility: the student view expects both # terms of service and honor code values. Since we're combining # these into a single checkbox, the only value we may get # from the new view is "honor_code". # Longer term, we will need to make this more flexible to support # open source installations that may have separate checkboxes # for TOS, privacy policy, etc. if data.get("honor_code") and "terms_of_service" not in data: data["terms_of_service"] = data["honor_code"] try: user = create_account_with_params(request, data) except AccountValidationError as err: errors = {err.field: [{"user_message": text_type(err)}]} return JsonResponse(errors, status=409) except ValidationError as err: # Should only get non-field errors from this function assert NON_FIELD_ERRORS not in err.message_dict # Only return first error for each field errors = { field: [{ "user_message": error } for error in error_list] for field, error_list in err.message_dict.items() } return JsonResponse(errors, status=400) except PermissionDenied: return HttpResponseForbidden(_("Account creation not allowed.")) response = JsonResponse({"success": True}) set_logged_in_cookies(request, response, user) return response