Obtain auth token using email instead of username - django

I'm trying to obtain auth token using email instead of username, i have changed serialized to accept just email but i think that i have something wrong.
class AuthTokenSerializer(serializers.Serializer):
"""Serializer for user authentication object"""
email_or_username = serializers.CharField()
password = serializers.CharField(style = {'input_type' : 'password' }, trim_whitespace = False)
def validate(self, attrs):
"""Validate and authentiate the user"""
email_or_username = attrs.get('email')
password = attrs.get('password')
user = authenticate(request = self.context.get('request'), username = email, password = password)
if not user:
msg = _('Unable to authenticate with provided credentials.')
raise serializers.ValidationError(msd, code='authorization')
attrs['user'] = user
return attrs
And the View
class LoginViewSet(viewsets.ViewSet):
"""Check email and password and returns an auth token."""
serializer_class = serializers.AuthTokenSerializer
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
def create(self, request):
"""Use the ObtainAuthToken APIview to validate and create a token."""
return ObtainAuthToken().post(request)
when i make a test
def test_create_token_for_user(self):
"""Test that a token is created"""
parametrs = {'email' : 'test#noah-lc.com','email' : 'test#noah-lc.com', 'name' : 'test', 'password' : 'testPASS#123'}
create_user(**parametrs)
res = self.client.post(TOKEN_URL, parametrs)
print(res.data)
self.assertIn('token', res.data)
self.assertEqual(res.status_code, status.HTTP_200_OK)
I got this error
AssertionError: 'token' not found in {'username': [ErrorDetail(string='This field is required.', code='required')]}
Model of own user
class UserProfile(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True)
name = models.CharField(max_length=255)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
And Setting
AUTH_USER_MODEL = 'core.UserProfile'

DRF's ObtainAuthToken uses its AuthTokenSerializer which expects a username not an email. So if you want to use an email, I would advice you create your own ObtainAuthToken view or even better off put the logic of ObtainAuthToken directly into your LoginViewSet as it seems to serve the same purpose. You can them create a custom AuthTokenSerializer which accepts emails instead of username or both and use with it

I suppose you have an app named users, then define a new User model here,
class User(AbstractBaseUser, PermissionMixin):
first_name = models.CharField(max_length=100, blank=True, null=True)
last_name = models.CharField(max_length=100, blank=True, null=True)
email = models.EmailField(db_index=True, unique=True)
USERNAME_FIELD = 'email'
The important part is USERNAME_FIELD, that set email instead of username
then in settings.py add below line
AUTH_USER_MODEL = 'users.User'

Related

" Invalid or incomplete introspection result" error when i load the graphql endpoint for my django project

I have a Django project where I am using Graphql but after writing out only one mutation, the /graphql does not run properly, throwing the following error.
{
"message": "Invalid or incomplete introspection result. Ensure that you are passing \"data\" property of introspection response and no \"errors\" was returned alongside: null.",
"stack": "r#https://cdn.jsdelivr.net/npm/graphiql#1.0.3/graphiql.min.js:1:24583\nur#https://cdn.jsdelivr.net/npm/graphiql#1.0.3/graphiql.min.js:1:326896\nwindow.GraphiQL</</s/value/<#https://cdn.jsdelivr.net/npm/graphiql#1.0.3/graphiql.min.js:7:48325\n"
}
How can I fix this ???
Here is my main schema
import graphene
import accounts.schema
class Query(graphene.ObjectType):
pass
class Mutation(accounts.schema.Mutation, graphene.ObjectType):
pass
schema = graphene.Schema()
Here is my account schema file
import graphene
from graphene_django import DjangoObjectType
from .models import CustomUser
class CustomUserType(DjangoObjectType):
class Meta:
model = CustomUser
class CustomUserInput(graphene.InputObjectType):
full_legal_name = graphene.String(required=True)
title = graphene.String(required=True)
email = graphene.String(required=True)
phone_number = graphene.String(required=True)
physical_address = graphene.String(required=True)
password = graphene.String(required=True)
confirm_password = graphene.String(required=True)
role = graphene.String(required=True)
class CreateUser(graphene.Mutation):
user = graphene.Field(CustomUserType)
class Arguments:
user_data = CustomUserInput(required=True)
def mutate(self, info, user_data=None):
user = CustomUser(
email=user_data.email,
full_legal_name=user_data.full_legal_name,
title=user_data.title,
phone_number=user_data.phone_number,
physical_address=user_data.physical_address,
password=user_data.password,
confirm_password=user_data.confirm_password,
role=user_data.role
)
if user.password != user.confirm_password:
raise Exception("Passwords do not match!")
else:
user.set_password(user_data.password)
user.save()
return CreateUser(user=user)
class Mutation(graphene.ObjectType):
create_user = CreateUser.Field()
And my model.py file which I used to build out the schema.
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
TITLES = (
('Mr', 'Mr'),
('Mrs', 'Mrs')
)
ROLES = (
('school_admin', 'school_admin'),
('app_admin', 'app_admin'),
('school_staff', 'school_staff')
)
email = models.EmailField(blank=False, max_length=255, verbose_name='email address')
full_legal_name = models.CharField(max_length=255, verbose_name='full legal name')
title = models.CharField(max_length=10, verbose_name='title')
phone_number = models.CharField(max_length=20, verbose_name='phone number')
physical_address = models.CharField(max_length=50, verbose_name='physical address')
confirm_password = models.CharField(blank=False, max_length=100, verbose_name='confirmation')
role = models.CharField(max_length=50, choices=ROLES, verbose_name='role')
EMAIL_FIELD = "email"
How can I go about solving this problem?
Add a sample query and pass both the query and the mutation to graphene.Schema as shown below.
class Query(graphene.ObjectType):
hello = graphene.String(default_value="Hi!")
class Mutation(accounts.Mutation, graphene.ObjectType):
pass
schema = graphene.Schema(query=Query, mutation=Mutation)

Signup page stuck on loading (Waiting for Localhost...) after extending AbstractUser

I created a custom user model called Agent by extending AbstractUser. Now for some reason, my signup page is stuck and I can't figure out why (it was working fine before I created the custom user). When I click the Sign Up button, the page is stuck on Waiting for localhost...
There are 2 additional models on top of Agent that are created during registration - AgentBasicInfo and AgentPremiumInfo. AgentBasicInfo is displayed on the sign up page, while AgentPremiumInfo is created in the background, and not actually displayed during registration.
When I check my admin page, I see that an Agent model has been created, but no AgentBasicInfo and AgentPremiumInfo instances have been created. This leads me to believe something is getting stuck at or after agent_basic_info = basic_info_form.save(commit=False), but I can't figure out what it is.
Here is my code:
views.py
def signup(request):
if request.user.is_authenticated:
return HttpResponseRedirect('../dashboard/')
if request.method == 'POST':
signup_form = SignupForm(request.POST)
basic_info_form = AgentBasicInfoForm(request.POST)
if signup_form.is_valid() and basic_info_form.is_valid():
agent = signup_form.save(commit=False)
agent.is_active = False
agent.save()
# Creates a basic info form with user input
agent_basic_info = basic_info_form.save(commit=False)
agent_basic_info.agent = agent
agent_basic_info = agent_basic_info.save()
# Creates a profile model with the agent's premium information, empty except for 'agent' field. No actual form displayed on sign up page.
agent_premium_info = AgentPremiumInfo.objects.create(agent=agent)
agent_premium_info.save()
current_site = get_current_site(request)
message = render_to_string('acc_active_email.html', {
'agent':agent,
'domain':current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(agent.pk)),
'token': account_activation_token.make_token(agent),
})
mail_subject = 'Activate your blog account.'
to_email = signup_form.cleaned_data.get('email')
email = EmailMessage(mail_subject, message, to=[to_email])
email.send()
return HttpResponse('Please confirm your email address to complete the registration')
else:
signup_form = SignupForm()
basic_info_form = AgentBasicInfoForm()
return render(request, 'signup.html', {'signup_form': signup_form, 'basic_info_form': basic_info_form})
def activate(request, uidb64, token):
try:
uid = force_text(urlsafe_base64_decode(uidb64))
agent = Agent.objects.get(pk=uid)
except(TypeError, ValueError, OverflowError, Agent.DoesNotExist):
agent = None
if agent is not None and account_activation_token.check_token(agent, token):
agent.is_active = True
agent.save()
login(request, agent)
# return redirect('home')
return HttpResponse('Thank you for your email confirmation. Now you can login your account.')
else:
return HttpResponse('Activation link is invalid!')
models.py
class Agent(AbstractUser):
pass
class AgentBasicInfo(models.Model):
TITLE = (
('Salesperson', 'Salesperson'),
('Sales Representative', 'Sales Representative'),
('Broker', 'Broker'),
('Broker of Record', 'Broker of Record'),
)
agent = models.OneToOneField(Agent, on_delete=models.CASCADE)
agent_first_name = models.CharField(max_length=30)
agent_last_name = models.CharField(max_length=30)
agent_preferred_email = models.EmailField()
office_phone_number = models.CharField(max_length=10)
agent_brokerage = models.CharField(max_length=50)
agent_title = models.CharField(max_length=20, choices=TITLE)
class AgentPremiumInfo(models.Model):
agent = models.OneToOneField(Agent, on_delete=models.CASCADE)
agent_phone_number = models.CharField(max_length=10, blank=True, null=True)
agent_website = models.CharField(max_length=50, blank=True, null=True)
agent_biography = models.TextField(blank=True, null=True)
agent_address_street = models.CharField(max_length=50, blank=True, null=True)
agent_address_city = models.CharField(max_length=25, blank=True, null=True)
agent_address_province = models.CharField(max_length=2, choices=PROVINCE, blank=True, null=True) # Add province choices later
agent_address_postal_code = models.CharField(max_length=6, blank=True, null=True)
agent_picture = models.ImageField(height_field=200, width_field=100, blank=True, null=True)
forms.py
class SignupForm(UserCreationForm):
email = forms.EmailField(max_length=200, help_text='Required')
def clean_email(self):
data = self.cleaned_data['email']
if not data.endswith('#gmail.com'):
raise forms.ValidationError("You must use your #gmail.com Email")
return data
class Meta:
model = Agent
fields = ('username', 'email', 'password1', 'password2')
class AgentBasicInfoForm(forms.ModelForm):
class Meta:
model = AgentBasicInfo
fields = ['agent_first_name', 'agent_last_name', 'agent_preferred_email', 'office_phone_number', 'agent_brokerage', 'agent_title']
class AgentPremiumInfoForm(forms.ModelForm):
class Meta:
model = AgentPremiumInfo
fields = ['agent_phone_number', 'agent_website', 'agent_biography', 'agent_picture', 'agent_address_street', 'agent_address_city', 'agent_address_province', 'agent_address_postal_code']
It seems something was wrong in the database despite me doing a reset_db. I did another reset_db and it magically fixed the issue.

Django 1.5 Custom User Model unknown column

I am using Django 1.5s Custom User Model. I want to let a user type their username in - and be logged in. NO PASSWORD (for testing anyway). My User Model doesnt have a password. But when i try to login to admin I get the following error:
OperationalError(1054, "Unknown column 'hrms.password' in 'field list'"
It seems to be trying to execute this query in the authenticate() method.
SELECT `myusers`.`password`, `myusers`.`last_login`, `myusers`.`id`, `myusers`.`user`, `myusers`.`name`, `myusers`.`firstname`, `myusers`.`lastname`, `myusers`.`organisation`, `myusers`.`unit`, `myusers`.`grade`, `myusers`.`email`, `myusers`.`position`, `myusers`.`manager` FROM `myusers` WHERE `myusers`.`user` = 'warrenm' "
I do not have the fields password, last_login - I dont know why its trying to get them.
Below is my code.
My Backend (auth.py)
from epmds.application.models import AuthUser
class MyBackend(object):
def get_user(self, user_id):
# get a user from the user_id
try:
return AuthUser.objects.get(pk=user_id)
except AuthUser.DoesNotExist:
return None
def authenticate(self, username=None, password=None):
# check the username/password and return a user
user = AuthUser.objects.get(user=username)
return user
MY Model
class AuthUser(AbstractBaseUser):
id = models.CharField(primary_key=True, max_length=15)
user = models.CharField('username', max_length=20, unique=True)
name = models.CharField(max_length=100)
firstname = models.CharField(max_length=100)
lastname = models.CharField(max_length=100)
organisation = models.CharField(max_length=100)
email = models.CharField(max_length=50, blank=True, null=True)
USERNAME_FIELD = 'user'
def get_full_name(self):
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
return self.first_name
class Meta:
ordering = ('lastname', 'firstname')
managed = False
db_table = 'myusers'
password is part of AbstractBaseUser so it should be added in your AuthUser model as well in table.
As you have managed=False for this model, you need to add that explicitly.

DjangoRestFramework serializing custom user models

I have defined a custom user model class as follows
class LabUserManager(BaseUserManager):
"""
A new user manager for both standard and administrative users
"""
def create_user(
self,
email,
first_name,
last_name,
university,
job_title,
bio,
password=None
):
"""
Creates a standard user with no administrative privledges
"""
if not email:
raise ValueError('Users must provide an email')
if not first_name:
raise ValueError('Users must provide a first name')
if not last_name:
raise ValueError('Users must provide a last name')
if not university:
raise ValueError('Users must provide an email address')
# Note: a biography and job_title are not required
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(
self,
email,
first_name,
last_name,
university,
job_title,
bio,
password=None
):
"""
Creates an administrative user
"""
user = self.create_user(
self,
email,
first_name,
last_name,
university,
job_title,
bio,
password=None
)
user.is_admin = True
user.save(using=self._db)
return user
class LabUser(AbstractBaseUser):
"""
Model for every user on the site
The only required fields are:
email,
first_name,
last_name,
university,
although, this will be discussed later
"""
email = models.EmailField(
verbose_name = 'email address',
max_length = 255,
unique = True,
db_index = True,
)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
university = models.CharField(max_length=150)
job_title = models.CharField(max_length = 50)
bio = models.TextField()
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
objects = LabUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = [
'first_name',
'last_name',
'university',
]
#property
def is_staff(self):
return self.is_admin
With the serializer
class NewUserSerializer(serializers.Serializer):
"""
Defines a new user serializer
"""
pk = serializers.Field()
email = serializers.EmailField()
first_name = serializers.CharField(max_length=50)
last_name = serializers.CharField(max_length=50)
university = serializers.CharField(max_length=150)
job_title = serializers.CharField(
max_length=50,
required=False
)
bio = serializers.CharField(
widget=widgets.Textarea,
required=False
)
password = serializers.CharField(
max_length=64,
widget=widgets.PasswordInput
)
def restore_object(self, attrs, instance=None):
if instance: # Update email university bio or job_title
user = instance
user.email = attrs['email']
user.university = attrs['university']
user.bio = attrs['bio']
user.job_title = attrs['job_title']
user.set_password(attrs.get('password'))
else:
user = LabUser(
email=attrs['email'],
first_name=attrs['first_name'],
last_name=attrs['last_name'],
university=attrs['university'],
job_title=attrs['job_title'],
bio=attrs['bio']
# Check custom user model page for other parameters
)
user.set_password(attrs.get('password'))
user.save()
return user
with the View
class NewUser(generics.CreateAPIView):
serializer_class = NewUserSerializer
But when I post a new user with a new email address, I receive the following error
IntegrityError at /users/new/
PRIMARY KEY must be unique
Request Method: POST
Request URL: http://127.0.0.1:8000/users/new/
Django Version: 1.5.1
Exception Type: IntegrityError
Exception Value:
PRIMARY KEY must be unique
At some point, you seem to submit and process a primary key value when creating new objects. It's only a guess, but I think this happens somewhere in your NewUserSerializer because you explicitly added a pk field, that is not read only and does not enforce a positive integer value. I would try using an IntegerField with read_only=True instead and see if that fixes the problem.
But I strongly recommend using ModelSerializer anyway. You could still have your custom widgets for each field, but it would also handle a few things a little more concise than your implementation does. And you'd have to write much less code.

How to take user id from the form or database in Django?

I have a simple form login.html in Django. I take username and password from the login form and use to validate in my Django view:
def login_upload(request):
if request.method == 'POST':
username = request.POST['username']
username1 = ''.join(username)
password = request.POST['password']
password = ''.join(password)
password1 = hashlib.sha1(password).hexdigest()
user = authenticate(username=username1, password=password1)
user_id = request.galaxyuser.id
if len(user) > 0:
return render_to_response('right.html', {'user_id':user_id}, context_instance=RequestContext(request))
else:
return render_to_response('wrong.html', context_instance=RequestContext(request))
else:
return render_to_response('login.html', context_instance=RequestContext(request))
I also want to get the id of the user which I have to use later. I tried using:
user_id = request.galaxyuser.id
But it returns None value. Here's my models.py:
class GalaxyUser(models.Model):
id = models.IntegerField(primary_key=True)
create_time = models.DateTimeField(null=True, blank=True)
update_time = models.DateTimeField(null=True, blank=True)
email = models.CharField(max_length=765)
password = models.CharField(max_length=120)
external = models.IntegerField(null=True, blank=True)
deleted = models.IntegerField(null=True, blank=True)
purged = models.IntegerField(null=True, blank=True)
username = models.CharField(max_length=765, blank=True)
form_values_id = models.IntegerField(null=True, blank=True)
disk_usage = models.DecimalField(null=True, max_digits=16, decimal_places=0, blank=True)
class Meta:
db_table = u'galaxy_user'
Edit:
My custom authentication function:
def authenticate(username='username', password='password'):
return GalaxyUser.objects.filter(username=username, password=password)
I have no idea what request.galaxyuser is supposed to be, but given a user object, the id is an attribute of that object. The authenticate function is supposed to return a User object if the credentials are valid.
user = authenticate(username=username1, password=password1)
user_id = request.galaxyuser.id # what are you doing here?
user_id = user.id # this is the user ID.
This question might have different answers depending on how you implemented your custom User class. I'm assuming it's the class returned by authenticate.
Update:
Your example shows you returning a QuerySet (a .filter) which is a list of rows.
You need to either return one object so that you can do look up the ID attribute, or you need to modify the view to account for this strange behavior. Authenticate is supposed to return the authenticated user object, so I woul ddo the former.
def authenticate(.....):
try:
return GalaxyUser.objects.get(username=username, password=password)
except GalaxyUser.DoesNotExist:
return None
user = authenticate(...)
user_id = user.id