Create UserProfile Model after User signed up using allauth Django - django

I have a django project in which there is a UserProfile having a OneToOne to the User model. It uses django-allauth for registration.
I am accepting registration via account and social account. Upon signing up, i want the user to be redirected to a page to create the UserProfile for that user account.
How could i do that ?
I have read, there is 1 signal called user_signed_up, can it be used to redirect the user to certain page ? I tried this code below, but it doesn't redirect me to the page i wanted.
#receiver(user_signed_up, dispatch_uid="some.unique.string.id.for.allauth.user_signed_up")
def do_stuff_after_sign_up(sender, **kwargs):
request = kwargs['request']
user = kwargs['user']
return redirect ('/test/')
any help will be greatly appreciated. thanks :)

I know its late but I hope future readers would find it helpful. :)
You need to raise an ImmediateHttpResponse like this:
from allauth.exceptions import ImmediateHttpResponse
from django.shortcuts import render
#receiver(user_signed_up, dispatch_uid="some.unique.string.id.for.allauth.user_signed_up")
def do_stuff_after_sign_up(sender, **kwargs):
request = kwargs['request']
user = kwargs['user']
raise ImmediateHttpResponse(render(request, 'you_custom_profile.html', {'user': user}))

Related

Django : How can we custom login_required decorator?

I want to write a decorator like the login_required decorator of Django to check the Azure AD authentication and the Django authentication at the same time. If one of the two is not true, it redirects to the login page.
For the authentication, I used the tutorial (https://learn.microsoft.com/en-us/graph/tutorials/python). I do not how to deal with groups and permissions since I use Azure AD authentication. So I take the username and surname from the token that comes from the Azure Authentication and with this two infos, I create an user in the User Django models. I know it is not the best idea, but I can start to play with groups and permissions.
The django authentication is automatic without that the user create it. It is done in the callback function.
def callback(request):
# Make the token request
result = get_token_from_code(request)
#Get the user's profile
user = get_user(result['access_token'])
# Store user
store_user(request, user)
# Get user info
# user attribute like displayName,surname,mail etc. are defined by the
# institute incase you are using single-tenant. You can get these
# attribute by exploring Microsoft graph-explorer.
username = user['displayName']
password = user['surname']
email = user['mail']
try:
# if use already exist
user = User.objects.get(username=username)
except User.DoesNotExist:
# if user does not exist then create a new user
user = User.objects.create_user(username,email,password)
user.save()
user = authenticate(username=username,password=password)
if user is not None:
login(request,user)
messages.success(request,"Success: You were successfully logged in.")
return redirect('home')
return redirect('home')
If I want to check if the user is authenticated by Azure AD. From the tutorial, I should do something like that :
if request.session.get('user').get('is_authenticated') :
But I do not know how to combine with the django authentication to check both. Anyone can help me
Thanks
simplest way would be to use the user_passes_test decorator to make your own function and apply that as a decorator to your views as per the docs
from django.contrib.auth.decorators import user_passes_test
def check_azure(user):
# so something here to check the azure login which should result in True/False
return #theResult of your check
#user_passes_test(check_azure)
def my_view(request):
...
Here is my solution :
from django.shortcuts import redirect
def authenticated_user(view_func) :
def wrapper_func(request, *args, **kwargs):
if request.user.is_authenticated and request.session.get('user').get('is_authenticated') :
return view_func(request, *args, **kwargs)
else :
return redirect('login')
return wrapper_func

In django, how to sign in using Oauth, if signed up using CustomForm

My Django app has an option for login/register using CustomForm (inherited from the UserCreationForm) as well as Outh. Now the problem is if a user has already signed up using the CustomForm and if the next time he tries to log in using google Oauth then instead of logging in, google Oauth is redirecting to some other signup form (not created by me) which looks like:
But as the user is already registered, if he enters the same username/email here then it displays says username taken. So how can I resolve this issue? I mean I want the user to be able to login using Oauth even if he has signed up using the CustomForm, how can I implement that? Or even if I ask the user to fill this form to be able to use OAuth login, the problem is that his email/username are already present in the db, so he won't be able to sign up using this form.
Edit:
If that's difficult to implement then instead how can I just show a message when the user tries to login using oauth after signing up with the CustomForm, something like "You signed up using username rather than google account", rather than taking him to the socialaccount signup form?
My register function in views.py:
def register(request):
if request.method == 'POST':
form = CustomForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('login')
else:
return redirect('register')
else:
return render(request, 'accounts/register.html')
forms.py looks something like this:
class CustomForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ("username", "email")
You can use pre_social_login signal
from allauth.exceptions import ImmediateHttpResponse
from allauth.socialaccount.signals import pre_social_login
from allauth.account.utils import perform_login
from allauth.utils import get_user_model
from django.dispatch import receiver
from django.shortcuts import redirect
from django.conf import settings
#receiver(pre_social_login)
def link_to_local_user(sender, request, sociallogin, **kwargs):
email_address = sociallogin.account.extra_data['email']
User = get_user_model()
users = User.objects.filter(email=email_address)
if users:
perform_login(request, users[0], email_verification=settings.EMAIL_VERIFICATION)
raise ImmediateHttpResponse(redirect(settings.LOGIN_REDIRECT_URL))
See https://github.com/pennersr/django-allauth/issues/215

How can I disallow the user to go to the register page when he is already logged in? Django 2.1.2

I made an admin panel in django. Which consists of login registration and dashboard for admin but i am facing a problem that:
If suppose a user is logged in to the system, and then the user goes to the url and go to register page using the url for ex. localhost/register when he is already logged in and no need of going to register page to register another user account. I don,t want this to happen.
How can I disallow the user to go to the register page when he is already logged in. How can we resolve this issue? Please help
You can try like this:
def register(request):
if request.user.is_authenticated:
return redirect('/') # or reverse('home_url_name')
else:
....
Update from comments:
You need to override LoginView for adding this functionality in login as well, for example:
from django.contrib.auth import views as auth_views
class CustomLoginView(auth_views.LoginView):
def get(self, request, *args, **kwargs):
if request.user.is_authenticated:
return redirect('/')
return super(CustomLogin, self).get(request, *args, **kwargs)
# URL
path('accounts/login/', CustomLoginView.as_view()),

Calling a method when the user login Django

On my Django site, I want to create an object when the user login the site. I searched it on the internet and I decided to write a method in a context_processors.py. so I wrote;
def check_online_status(request):
user_status = None
if request.user.is_authenticated():
user_status = UserStatus.objects.create(user_id=request.user.id)
user_status.status_type = "online"
user_status.save()
return {
'user_status': user_status,
}
Here it is the problem; my check_online_status() method is triggered in every request but I want to trigger my method at once, only when the user login.
Can you help me to do it?
I think what you're looking for is a signal, specifically an auth signal. These are already provided in django.
https://docs.djangoproject.com/en/dev/ref/contrib/auth/#module-django.contrib.auth.signals
from django.contrib.auth.signals import user_logged_in
def set_status_online(sender, user, request, **kwargs):
user_status = UserStatus.objects.create(user_id=request.user.id)
user_status.status_type = "online"
user_status.save()
user_logged_in.connect(set_status_online)

Creating user profile pages in Django

I'm a beginner in Django. I need to setup a website, where each user has a profile page. I've seen django admin. The profile page for users, should store some information which can be edited by the user only. Can anyone point me out how that is possible?. Any tutorial links would be really helpful. Also, are there any modules for django, which can be used for setting up user page.
You would just need to create a view that's available to an authenticated user and return a profile editing form if they're creating a GET request or update the user's profile data if they're creating a POST request.
Most of the work is already done for you because there are generic views for editing models, such as the UpdateView. What you need to expand that with is checking for authenticated users and providing it with the object that you want to provide editing for. That's the view component in the MTV triad that provides the behavior for editing a user's profile--the Profile model will define the user profile and the template will provide the presentation discretely.
So here's some behavior to throw at you as a simple solution:
from django.contrib.auth.decorators import login_required
from django.views.generic.detail import SingleObjectMixin
from django.views.generic import UpdateView
from django.utils.decorators import method_decorator
from myapp.models import Profile
class ProfileObjectMixin(SingleObjectMixin):
"""
Provides views with the current user's profile.
"""
model = Profile
def get_object(self):
"""Return's the current users profile."""
try:
return self.request.user.get_profile()
except Profile.DoesNotExist:
raise NotImplemented(
"What if the user doesn't have an associated profile?")
#method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
"""Ensures that only authenticated users can access the view."""
klass = ProfileObjectMixin
return super(klass, self).dispatch(request, *args, **kwargs)
class ProfileUpdateView(ProfileObjectMixin, UpdateView):
"""
A view that displays a form for editing a user's profile.
Uses a form dynamically created for the `Profile` model and
the default model's update template.
"""
pass # That's All Folks!
You can
create another Model for storing profile information about user
add AUTH_PROFILE_MODULE='yourprofileapp.ProfileModel' to settings.py
In profile editing view, allow only logged in users to edit their own profiles
example:
#login_required
def edit_profile(request):
'''
edit profile of logged in user i.e request.user
'''
You can also make sure that whenever new user is created the user's profile is also created using django's signals
Read about storing additional information about users from django documentation