I have the following user flow:
1) user registers.
2) user has a 'getting_started' page where he fills out some basic info and adds a picture.
3) user activates his email and logs in
After a user has finished filling out his info on the getting started page, if he goes back to the page getting_started/, I want the user to be redirected to his home/. What would be the easiest way to accomplish this? (As a reference, similar to the LinkedIn or Facebook Sign Up flow).
The way that comes to mind for me is to set a global variable getting_started = 1 after the user fills out the getting_started page, and on the getting_started page, do --
if getting_started:
redirect to home/
else:
...(normal getting started view)...
Is it just the getting_started view/page that you want to redirect on? Don't think in terms of global variables, think in terms of database fields!
Once your user has signed up, they will be a registered user (if you are using djangos auth app) and they will have an entry in the database. Therefore you simply have to check to see if the user is registered already: if so, redirect, otherwise allow them to continue signing up.
You could simply put a check at the start of the getting_started view to see if the user has already signed up
from django.http import HttpResponseRedirect
def getting_started_view(request):
if request.user.is_authenticated():
return HttpResponseRedirect(reverse('home_view'))
where home_view is in your urls.py:
url("...","someapp.views.viewname", name="home_view"),
...
(or you could hard code the redirect)
If you are looking for more complex redirects (maybe numerous pages that require a redirect to the home page) you should look at writing some middleware. This will allow you to intercept every request coming in, see if it's to a certain page, and redirect.
https://docs.djangoproject.com/en/dev/topics/http/middleware/?from=olddocs
Related
I have created a form that lets you create a new site with Djangos built in Site module. I have setup a url, view and template for it. Everything is working as expected.
The user will go to the URL /welcome/ when successfully created a site. But then I realized that everyone that tries to go to that URL will see the welcome content. Including Google. That is not what I want.
I want to restrict this URL to the current session and give a 404 page when others trying to go to that URL also for logged in users. I have looked at Djangos view decorators but haven't found one for my particular need.
Is this possible?
EDIT
To clarify:
I would like to ONLY display /welcome/ after the actual creation of the site. The user that CREATED this site will ONLY have permission to display that page. To others that tries to display the page it will raise a 404 (not found) error.
I'm not entirely sure what you want, but if you want to restrict a view for a certain site, you could use get_current_site().
current_site = get_current_site(request)
if not current_site.domain == 'foo.bar.com':
raise Http404
Use request.user to access the current user.
You could implement this check in your own view decorator or perhaps in custom Django middleware.
I have my login and register on the main page, index. When the user logs in or registers successfully, everything's gravy.
However, when there's an error, Flask-Security redirects the user to a different page, /login and /register respectively. I don't see a need to include these separate pages. How do I have Flask-Security not redirect and instead show the errors right there on the index page?
I've tried setting SECURITY_{REGISTER,LOGIN}_USER_TEMPLATE='/index.html' but that did not work.
SECURITY_{REGISTER,LOGIN}_USER_TEMPLATE requires a template, you're specifying a URL. So if you change it to SECURITY_REGISTER_USER_TEMPLATE='index.html' it'll try and render the template you mention.
But what I think you really should do, is use JSON to manage your login features since you're squidging them into a single page.
Flask-Security's login and register views look out for JSON requests, and so if you send it some, it'll in turn respond with JSON, and in the case of a bad password/bad email etc, it'll include the errors in the JSON return data, so you could then handle your logins purely via Ajax.
You can see how the login watches for JSON in the source and how the returned data is rendered
I am getting my feet wet working with the Pyramid framework (great framework), and I've come to the point of user authorization. I want to take advantage of the ACL to block users who are already logged in from visiting the registration page. Obviously, I could do this other ways, but I was wondering if there was any way to do this using tools in pyramid.
I know that by adding permissions to a view, users who do not meet the criteria are shown a forbidden view. In my case, I simply want to re route users who are already members away from views that don't apply to them (registration, login, etc.).
I've tried __acl__ = [(Deny, Authenticated, 'guest')] to no avail, as it blocks the login page for all users.
Also, somewhat on another note, is there any way to dynamically change a route. I want the home page to be different for users who are logged in than it is for guests.
You'll want to investigate the principals that are being returned by your authentication policy to understand what's going on. It's easy to tell if you turn on pyramid.debug_authorization in your INI file. The authorization policy will compare the ACL found against the principals returned via pyramid.security.effective_principals(request). If these do not match up, it should be clear what is going on.
The way to implement a form-based login would be (assuming Pyramid 1.3a9+):
from pyramid.httpexceptions import HTTPSeeOther
from pyramid.security import authenticated_userid
from pyramid.view import forbidden_view_config
#forbidden_view_config()
def forbidden_view(request):
if authenticated_userid(request):
# user is already logged in, they are really forbidden
return request.context # the forbidden 403 response
url = request.route_url('login', _query={'came_from': request.path})
return HTTPSeeOther(url)
That will add the came_from parameter to the URL as request.GET['came_from'] in your login view. Of course if that isn't there you can just redirect them to the home screen after logging in.
From a very old blog post from FB:
As promised, we have changed the login procedure. This change should
improve your users experience and requires no modifications to
existing applications. Now, if a user was already using Facebook,
logging into an app happens transparently. Because of this, developers
might want to provide a way for users to logout by posting the word
"confirm" to http://www.facebook.com/logout.php. Alternatively,
developers can provide a link to switch the user via the login page’s
"skipcookie" parameter (as described in the authentication guide.
What if I don't want this to happen, but rather want the user to be redirected to FB and confirm his identity even if logged in to FB? I looked everywhere for this skipcookie directive but found nothing about it, in fact I think it has been discontinued.
For the record I'm using django in my app.
Thanks in advance for any help.
That is very old, and like you said, doesn't really apply anymore especially since everything moved from oauth over to oauth 2.
What if I don't want this to happen, but rather want the user to be redirected to FB and confirm his identity even if logged in to FB?
So here's what you do. If you want to force the user to re-login to facebook (confirming his identity and it's not some person who just walked up to an unlocked computer already logged into Facebook), call FB.logout() first, then call FB.login() to log the user in. Since you called logout() first, it will force the user to log into Facebook before authorizing your app.
If anybody is still curious as to how to implement this using Django, here's how I log the user out of facebook server-side:
next_url = 'http://your.app.url/return/from/fb/'
args = {
'next':next_url,
'access_token':access_token
}
redirect_to = "https://www.facebook.com/logout.php?" + urllib.urlencode(args)
return HttpResponseRedirect(redirect_to)
With this you can log the user out using the server side script (be it python/Django or any other language/framework, just use your language's url fetching API).
With this code the user will be redirected to the FB logout url and will then return to next_url
The Django framework easily handles redirecting when a user fails to log in properly. However, this redirection goes to a separate login page. I can set the template to be the same as the page I logged in on, but none of my other objects exist in the new page.
For example, I have a front page that shows a bunch of news articles. On the sidebar is a login form. When the user logs in, but fails to authenticate, I would like it to return to the front page and preserve all the news articles that show. As of current, none of the news articles show up.
How can I fix this problem? Any help is appreciated.
Edit: Remember that I have dynamic content that is being displayed, and I would like it to still display! Futhermore, the main page is not the only place a user can log in. The sidebar never changes, so the user can potentially log in from any page on the site, and all of the content on that page exactly as it was still needs to be displayed upon failure to log in.
Do you want to redirect to the referring page on failed login?
... authentication code above
if user.is_authenticated():
#show success view
else:
return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse('index'))
you might want to check that referring page url is set correctly, otherwise set it to default url (assuming that your default url is named "index").
Use an <IFRAME> in the sidebar to
call the login view -- all postbacks
will happen within the iframe, so
your page stays intact. If the
visitor logs in successfully, you
can use javascript to redirect the
parent page to some other URL
Use AJAX to post the login form --
acheives the same effect as (1), but
it means your visitors will need to
have javascript-enabled browsers
I personally prefer to have the login on a separate page. If you're only worried about your visitors losing their current page (and not say, bound by a fussy client), you can have the login show up in a lightbox. I've used all three approaches in the past, and I'd be happy to post some code samples if you're interested.
This is because redirecting to a view misses the original context you use to render the page in the first place.
You are missing just a simple logic here. You are trying to render the same template again, but with no news_article list.
I suppose (in the first place), you are rendering the template which shows you Articles as well as login form, by sending two things 1. Login Form, and 2. Articles List.
But secondly, when user fails to authenticate, you are not passing the same things again. Pass those variables again as context (you can also add error message if your form is not handling error messages).
if user.is_authenticated():
#show success view
else:
return render_to_response('same_template.html', {
'error_msg': 'Username or password you provided was incorrect',
'news_articles': NewsArticles.objects.all()[:3],
'login_form': LoginForm(request.POST);
})
Edit: The reality is that, a context is used to render a template, and it's the complete responsibility of that template, what it wants to pass in further navigation. And as I see, if you are not passing something further, you are not getting it further.
If you want some automated context, develop your own context processor, something like the auth-context-processor, which automatically adds like 'user', always available to the template.
And by the way, you are going to miss that kind of context anyway, even if login is authenticated. So if that particular context is really important, either try sending the primary keys of articles along with the login form submit, or store that in global (ugliest thing ever) or just reconsider and separate the flow (good thing, I feel).