def get_sso_login_url(request, success_url): """Returns the redirect url for the discourse SSO login""" # Generate a random nonce. nonce = generate_random_key() # Save it temporarily so that you can verify it with returned nonce value discourse_login_data = { 'nonce': nonce, 'timestamp': time.time(), 'success_url': success_url } request.session['discourse_login'] = discourse_login_data # Create a new payload with nonce and return url # (where the Discourse will redirect user after verification). # Payload should look like: nonce=NONCE&return_sso_url=RETURN_URL return_url = site_url(reverse('user_complete_discourse_signin')) payload = 'nonce={}&return_sso_url={}'.format(nonce, return_url) # Base64 encode the above raw payload. -> BASE64_PAYLOAD base64_payload = base64.b64encode(payload) # URL encode the above BASE64_PAYLOAD. url_encoded_payload = urllib.quote(base64_payload) # Generate a HMAC-SHA256 signature from BASE64_PAYLOAD, lower case it -> HEX_SIGNATURE hex_signature = sign_payload(base64_payload) # Redirect the user to DISCOURSE_ROOT_URL/session/sso_provider?sso=URL_ENCODED_PAYLOAD&sig=HEX_SIGNATURE url_template = '{}/session/sso_provider?sso={}&sig={}' return url_template.format(askbot_settings.DISCOURSE_SITE_URL, url_encoded_payload, hex_signature)
def collect_missing_options(options_dict): options_dict['secret_key'] = generate_random_key() if options_dict['database_engine'] == '2':#sqlite while True: value = console.simple_dialog( 'Please enter database file name' ) database_file_name = None if os.path.isfile(value): message = 'file %s exists, use it anyway?' % value if console.get_yes_or_no(message) == 'yes': database_file_name = value elif os.path.isdir(value): print '%s is a directory, choose another name' % value elif value in path_utils.FILES_TO_CREATE: print 'name %s cannot be used for the database name' % value elif value == path_utils.LOG_DIR_NAME: print 'name %s cannot be used for the database name' % value else: database_file_name = value if database_file_name: options_dict['database_name'] = database_file_name return options_dict else:#others for key in ('database_name', 'database_user', 'database_password'): if options_dict[key] is None: key_name = key.replace('_', ' ') value = console.simple_dialog( '\nPlease enter %s' % key_name, required=True ) options_dict[key] = value return options_dict
def collect_missing_options(options_dict): options_dict['secret_key'] = '' if options_dict['no_secret_key'] else generate_random_key() if options_dict['database_engine'] == '2':#sqlite if options_dict['database_name']: return options_dict while True: value = console.simple_dialog( 'Please enter database file name' ) database_file_name = None if os.path.isfile(value): message = 'file %s exists, use it anyway?' % value if console.get_yes_or_no(message) == 'yes': database_file_name = value elif os.path.isdir(value): print('%s is a directory, choose another name' % value) elif value in path_utils.FILES_TO_CREATE: print('name %s cannot be used for the database name' % value) elif value == path_utils.LOG_DIR_NAME: print('name %s cannot be used for the database name' % value) else: database_file_name = value if database_file_name: options_dict['database_name'] = database_file_name return options_dict else:#others db_keys = OrderedDict([ ('database_name', True), ('database_user', True), ('database_password', True), ('database_host', False), ('database_port', False) ]) for key, required in list(db_keys.items()): if options_dict[key] is None: key_name = key.replace('_', ' ') fmt_string = '\nPlease enter %s' if not required: fmt_string += ' (press "Enter" to use the default value)' value = console.simple_dialog( fmt_string % key_name, required=db_keys[key] ) options_dict[key] = value return options_dict
def collect_missing_options(options_dict): options_dict['secret_key'] = generate_random_key() if options_dict['database_engine'] == '2':#sqlite if options_dict['database_name']: return options_dict while True: value = console.simple_dialog( 'Please enter database file name' ) database_file_name = None if os.path.isfile(value): message = 'file %s exists, use it anyway?' % value if console.get_yes_or_no(message) == 'yes': database_file_name = value elif os.path.isdir(value): print('%s is a directory, choose another name' % value) elif value in path_utils.FILES_TO_CREATE: print('name %s cannot be used for the database name' % value) elif value == path_utils.LOG_DIR_NAME: print('name %s cannot be used for the database name' % value) else: database_file_name = value if database_file_name: options_dict['database_name'] = database_file_name return options_dict else:#others db_keys = OrderedDict([ ('database_name', True), ('database_user', True), ('database_password', True), ('database_host', False), ('database_port', False) ]) for key, required in db_keys.items(): if options_dict[key] is None: key_name = key.replace('_', ' ') fmt_string = '\nPlease enter %s' if not required: fmt_string += ' (press "Enter" to use the default value)' value = console.simple_dialog( fmt_string % key_name, required=db_keys[key] ) options_dict[key] = value return options_dict
def __call__(self): # this is the main part of the original askbot_setup() try: # If necessary and if we are in the interactive mode, # will ask for the missing parameters. # Otherwise will use the default values. console = Console() validator = ParamsValidator(console, self.parser) params = validator.get_params() params['secret_key'] = generate_random_key(length=32) for key, val in params.items(): print(f'{key}={val}') # make the directories force = params['force'] deployers.makedir(params['root_dir'], force) deployers.makedir(params['proj_dir'], force) deployers.makedir(params['media_root_dir'], force) deployers.makedir(params['static_root_dir'], force) deployers.makedir(os.path.dirname(params['log_file_path']), force) deployers.ManagePy(params).deploy() deployers.UrlsPy(params).deploy() deployers.SettingsPy(params).deploy() # print next steps help #console.print_postamble(params) except ValidationError as error: if error.messages and len(error.messages) == 1: print(f'Error: {error.messages[0]}') sys.exit(1) print(f'\n\n{error}\nAborted') sys.exit(1) except DeploymentError as error: print(f'\n\n{error}') sys.exit(1) except KeyboardInterrupt: print("\n\nAborted.") sys.exit(1)
def register(request, login_provider_name=None, user_identifier=None): """ this function is used via it's own url with request.method=POST or as a simple function call from "finalize_generic_signin" in which case request.method must ge 'GET' and login_provider_name and user_identifier arguments must not be None user_identifier will be stored in the UserAssociation as openid_url login_provider_name - as provider_name this function may need to be refactored to simplify the usage pattern template : authopenid/complete.html """ logging.debug("") next_url = get_next_url(request) user = None username = request.session.get("username", "") email = request.session.get("email", "") logging.debug("request method is %s" % request.method) form_class = forms.get_registration_form_class() register_form = form_class( initial={ "next": next_url, "username": request.session.get("username", ""), "email": request.session.get("email", ""), } ) if request.method == "GET": assert login_provider_name is not None assert user_identifier is not None # store this data into the session # to persist for the post request request.session["login_provider_name"] = login_provider_name request.session["user_identifier"] = user_identifier elif request.method == "POST": if "login_provider_name" not in request.session or "user_identifier" not in request.session: logging.critical("illegal attempt to register") return HttpResponseRedirect(reverse("user_signin")) # load this data from the session user_identifier = request.session["user_identifier"] login_provider_name = request.session["login_provider_name"] logging.debug("trying to create new account associated with openid") form_class = forms.get_registration_form_class() register_form = form_class(request.POST) if not register_form.is_valid(): logging.debug("registration form is INVALID") else: username = register_form.cleaned_data["username"] email = register_form.cleaned_data["email"] if "ldap_user_info" in request.session: user_info = request.session["ldap_user_info"] # we take this info from the user input where # they can override the default provided by LDAP user_info["django_username"] = username user_info["email"] = email user = ldap_create_user(user_info).user user = authenticate(user_id=user.id, method="force") del request.session["ldap_user_info"] login(request, user) cleanup_post_register_session(request) return HttpResponseRedirect(next_url) elif askbot_settings.REQUIRE_VALID_EMAIL_FOR == "nothing": user = create_authenticated_user_account( username=username, email=email, user_identifier=user_identifier, login_provider_name=login_provider_name, ) login(request, user) cleanup_post_register_session(request) return HttpResponseRedirect(next_url) else: email_verifier = UserEmailVerifier(key=generate_random_key()) email_verifier.value = { "username": username, "email": email, "user_identifier": user_identifier, "login_provider_name": login_provider_name, } email_verifier.save() send_email_key(email, email_verifier.key, handler_url_name="verify_email_and_register") redirect_url = reverse("verify_email_and_register") + "?next=" + next_url return HttpResponseRedirect(redirect_url) providers = { "yahoo": '<font color="purple">Yahoo!</font>', "flickr": '<font color="#0063dc">flick</font><font color="#ff0084">r</font>™', "google": "Google™", "aol": '<font color="#31658e">AOL</font>', "myopenid": "MyOpenID", } if login_provider_name not in providers: provider_logo = login_provider_name else: provider_logo = providers[login_provider_name] logging.debug("printing authopenid/complete.html output") data = { "openid_register_form": register_form, "default_form_action": django_settings.LOGIN_URL, "provider": mark_safe(provider_logo), "username": username, "email": email, "login_type": "openid", "gravatar_faq_url": reverse("faq") + "#gravatar", } return render(request, "authopenid/complete.html", data)
def signin(request, template_name="authopenid/signin.html"): """ signin page. It manages the legacy authentification (user/password) and openid authentification url: /signin/ template : authopenid/signin.htm """ logging.debug("in signin view") on_failure = signin_failure # we need a special priority on where to redirect on successful login # here: # 1) url parameter "next" - if explicitly set # 2) url from django setting LOGIN_REDIRECT_URL # 3) home page of the forum login_redirect_url = getattr(django_settings, "LOGIN_REDIRECT_URL", None) next_url = get_next_url(request, default=login_redirect_url) logging.debug("next url is %s" % next_url) if askbot_settings.ALLOW_ADD_REMOVE_LOGIN_METHODS == False and request.user.is_authenticated(): return HttpResponseRedirect(next_url) if next_url == reverse("user_signin"): next_url = "%(next)s?next=%(next)s" % {"next": next_url} login_form = forms.LoginForm(initial={"next": next_url}) # todo: get next url make it sticky if next is 'user_signin' if request.method == "POST": login_form = forms.LoginForm(request.POST) if login_form.is_valid(): provider_name = login_form.cleaned_data["login_provider_name"] if login_form.cleaned_data["login_type"] == "password": password_action = login_form.cleaned_data["password_action"] if askbot_settings.USE_LDAP_FOR_PASSWORD_LOGIN: assert password_action == "login" username = login_form.cleaned_data["username"] password = login_form.cleaned_data["password"] user = authenticate(username=username, password=password, method="ldap") if user: login(request, user) return HttpResponseRedirect(next_url) else: # try to login again via LDAP user_info = ldap_authenticate(username, password) if user_info["success"]: if askbot_settings.LDAP_AUTOCREATE_USERS: # create new user or user = ldap_create_user(user_info).user user = authenticate(method="force", user_id=user.id) assert user is not None login(request, user) return HttpResponseRedirect(next_url) else: # continue with proper registration ldap_username = user_info["ldap_username"] request.session["email"] = user_info["email"] request.session["ldap_user_info"] = user_info if askbot_settings.AUTOFILL_USER_DATA: request.session["username"] = ldap_username request.session["first_name"] = user_info["first_name"] request.session["last_name"] = user_info["last_name"] return finalize_generic_signin( request, login_provider_name="ldap", user_identifier=ldap_username + "@ldap", redirect_url=next_url, ) else: auth_fail_func_path = getattr(django_settings, "LDAP_AUTHENTICATE_FAILURE_FUNCTION", None) if auth_fail_func_path: auth_fail_func = load_module(auth_fail_func_path) auth_fail_func(user_info, login_form) else: login_form.set_password_login_error() # return HttpResponseRedirect(request.path) else: if password_action == "login": user = authenticate( username=login_form.cleaned_data["username"], password=login_form.cleaned_data["password"], provider_name=provider_name, method="password", ) if user is None: login_form.set_password_login_error() else: login(request, user) # todo: here we might need to set cookies # for external login sites return HttpResponseRedirect(next_url) elif password_action == "change_password": if request.user.is_authenticated(): new_password = login_form.cleaned_data["new_password"] AuthBackend.set_password( user=request.user, password=new_password, provider_name=provider_name ) request.user.message_set.create(message=_("Your new password saved")) return HttpResponseRedirect(next_url) else: logging.critical("unknown password action %s" % password_action) raise Http404 elif login_form.cleaned_data["login_type"] == "openid": # initiate communication process logging.debug("processing signin with openid submission") # todo: make a simple-use wrapper for openid protocol sreg_req = sreg.SRegRequest(optional=["nickname", "email"]) redirect_to = "%s%s?%s" % ( get_url_host(request), reverse("user_complete_signin"), urllib.urlencode({"next": next_url}), ) return ask_openid( request, login_form.cleaned_data["openid_url"], redirect_to, on_failure=signin_failure, sreg_request=sreg_req, ) elif login_form.cleaned_data["login_type"] == "oauth": try: # this url may need to have "next" piggibacked onto connection = util.OAuthConnection(provider_name, callback_url=reverse("user_complete_oauth_signin")) connection.start() request.session["oauth_token"] = connection.get_token() request.session["oauth_provider_name"] = provider_name request.session["next_url"] = next_url # special case for oauth oauth_url = connection.get_auth_url(login_only=True) return HttpResponseRedirect(oauth_url) except util.OAuthError, e: logging.critical(unicode(e)) msg = _( "Unfortunately, there was some problem when " "connecting to %(provider)s, please try again " "or use another provider" ) % {"provider": provider_name} request.user.message_set.create(message=msg) elif login_form.cleaned_data["login_type"] == "oauth2": try: csrf_token = generate_random_key(length=32) redirect_url = util.get_oauth2_starter_url(provider_name, csrf_token) request.session["oauth2_csrf_token"] = csrf_token request.session["provider_name"] = provider_name return HttpResponseRedirect(redirect_url) except util.OAuthError, e: logging.critical(unicode(e)) msg = _( "Unfortunately, there was some problem when " "connecting to %(provider)s, please try again " "or use another provider" ) % {"provider": provider_name} request.user.message_set.create(message=msg) elif login_form.cleaned_data["login_type"] == "wordpress_site": # here wordpress_site means for a self hosted wordpress blog not a wordpress.com blog wp = Client( askbot_settings.WORDPRESS_SITE_URL, login_form.cleaned_data["username"], login_form.cleaned_data["password"], ) try: wp_user = wp.call(GetUserInfo()) custom_wp_openid_url = "%s?user_id=%s" % (wp.url, wp_user.user_id) user = authenticate(method="wordpress_site", wordpress_url=wp.url, wp_user_id=wp_user.user_id) return finalize_generic_signin( request=request, user=user, user_identifier=custom_wp_openid_url, login_provider_name=provider_name, redirect_url=next_url, ) except WpFault, e: logging.critical(unicode(e)) msg = _("The login password combination was not correct") request.user.message_set.create(message=msg)
def send_user_new_email_key(user): user.email_key = generate_random_key() user.save() send_email_key(user.email, user.email_key)
def signup_with_password(request): """Create a password-protected account template: authopenid/signup_with_password.html """ logging.debug(get_request_info(request)) login_form = forms.LoginForm(initial={"next": get_next_url(request)}) # this is safe because second decorator cleans this field provider_name = request.REQUEST["login_provider"] if askbot_settings.USE_RECAPTCHA: RegisterForm = forms.SafeClassicRegisterForm else: RegisterForm = forms.ClassicRegisterForm logging.debug("request method was %s" % request.method) if request.method == "POST": form = RegisterForm(request.POST) # validation outside if to remember form values logging.debug("validating classic register form") form1_is_valid = form.is_valid() if form1_is_valid: logging.debug("classic register form validated") else: logging.debug("classic register form is not valid") if form1_is_valid: logging.debug("both forms are valid") next = form.cleaned_data["next"] username = form.cleaned_data["username"] password = form.cleaned_data["password1"] email = form.cleaned_data["email"] if askbot_settings.REQUIRE_VALID_EMAIL_FOR == "nothing": user = create_authenticated_user_account(username=username, email=email, password=password) login(request, user) cleanup_post_register_session(request) return HttpResponseRedirect(get_next_url(request)) else: email_verifier = UserEmailVerifier(key=generate_random_key()) email_verifier.value = { "username": username, "login_provider_name": provider_name, "email": email, "password": password, } email_verifier.save() send_email_key(email, email_verifier.key, handler_url_name="verify_email_and_register") redirect_url = reverse("verify_email_and_register") + "?next=" + get_next_url(request) return HttpResponseRedirect(redirect_url) else: # todo: this can be solved with a decorator, maybe form.initial["login_provider"] = provider_name logging.debug("create classic account forms were invalid") else: # todo: here we have duplication of get_password_login_provider... form = RegisterForm(initial={"next": get_next_url(request), "login_provider": provider_name}) logging.debug("printing legacy signup form") major_login_providers = util.get_enabled_major_login_providers() minor_login_providers = util.get_enabled_minor_login_providers() context_data = { "form": form, "page_class": "openid-signin", "major_login_providers": major_login_providers.values(), "minor_login_providers": minor_login_providers.values(), "login_form": login_form, } return render(request, "authopenid/signup_with_password.html", context_data)