Пример #1
0
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)
Пример #2
0
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
Пример #3
0
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
Пример #4
0
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
Пример #5
0
    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)
Пример #6
0
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>&trade;',
        "google": "Google&trade;",
        "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)
Пример #7
0
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)
Пример #8
0
def send_user_new_email_key(user):
    user.email_key = generate_random_key()
    user.save()
    send_email_key(user.email, user.email_key)
Пример #9
0
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)