My authentication doesn't seem to work. I got registration and everything, its just the log in and authenticate aspect that doesnt work. I'm not sure why.
I'm not sure as to why my django auth returns none.
I have this in my settings:
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'UniLinkedApp.auth.MyAuthBackEnd',
)
I have my models as:
class Register(models.Model):
username = models.CharField(max_length = 200)
email = models.EmailField(max_length = 200)
password = models.CharField(max_length = 200)
university = models.CharField(max_length=50)
major = models.CharField(max_length = 200)
def __str__(self):
return self.user
class MyAccountManager(BaseUserManager):
def create_user(self, username, email, password, university, major):
if not email:
raise ValueError("Users must have an email address")
if not username:
raise ValueError("Users must have an username")
user = self.model(
username=username,
email=self.normalize_email(email),
password = password,
university = university,
major = major,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password):
user = self.create_user(
username=username,
email=self.normalize_email(email),
password=password,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class Account(AbstractBaseUser):
username = models.CharField(max_length = 200)
email = models.EmailField(max_length = 200)
password = models.CharField(max_length = 200)
university = models.CharField(max_length=50)
major = models.CharField(max_length = 200)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
USERNAME_FIELD = 'username'
objects = MyAccountManager()
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
I have my forms like:
class RegisterForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
class Meta:
model = Account
fields = ['username', 'email', 'password', 'university', 'major']
class AccountAuthenticationForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
class Meta:
model = Account
fields = ('username', 'email','password', 'university', 'major')
def clean(self):
if self.is_valid():
email = self.cleaned_data['email']
password = self.cleaned_data['password']
if not authenticate(email=email, password=password):
raise forms.ValidationError("Invalid login")
My auth is:
class MyAuthBackEnd(ModelBackend):
def authenticate(self, **kwargs):
username = kwargs['username']
password = kwargs['password']
try:
account = Account.objects.get(username=username)
if account.check_password(password) is True:
return account
except Account.DoesNotExist:
pass
It doesn't matter what authentication method I use, it still returns none despite having correct username and password.
I tried all sorts of things but not sure how to fix it.
This is my login as method:
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = MyAuthBackEnd.authenticate(request, username=username, password = password)
#print(user)
#print(username, password)
if user is not None:
print('Test')
login(request, username)
return redirect('home')
else:
messages.info(request, 'Username or Password is incorrect')
Related
I'm learning Django and tried to write my own custom user model. I'm not using DRF and serializers and stuffs I have no idea about :)
I am using createView to create users but I can't login because "Invalid password."
I checked the user's password in admin and the user's password is "Invalid password format or unknown hashing algorithm." .
here are the codes:
Custome User and User Manager in models
class UserManager(UserManager):
def create_user(self, username, email, password, **extra_fields):
if not email:
raise ValueError('User must have email')
if not username:
raise ValueError('User must have username')
user = User.objects.create_user(
username=username,
email=self.normalize_email(email),
)
user.set_password(password)
user.save()
return user
def create_superuser(self, username, email, password, **extra_fields) :
user = self.create_user(username, email, password)
user.is_staff = True
user.is_superuser = True
user.is_admin = True
user.is_active = True
user.save()
return user
class User(AbstractBaseUser):
username = models.CharField(unique=True, max_length=200)
email = models.EmailField(unique=True)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
date_joined = models.DateTimeField(default=timezone.now)
modified_at = models.DateTimeField(auto_now=True)
objects = UserManager()
REQUIRED_FIELDS = ["username","email", "password"]
USERNAME_FIELD = "username"
def __str__(self):
return self.email
def has_perm(self, perm, object=None):
"Does the user have a specific permission?"
return self.is_admin
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
SignUp and login in views
class SignUp(CreateView):
model = User
form_class = CUForm
success_url = reverse_lazy('index')
def login(request):
if request.user.is_authenticated:
messages.warning(request, 'You are already logged in.')
return redirect('/list')
elif request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
return redirect('/list')
else:
try:
user = User.objects.get(username=username)
messages.error(request, 'Invalid password.')
except:
messages.error(request, 'Invalid username ')
return redirect('login')
return render(request, 'accounts/login.html')
and forms.py
class CUForm(forms.ModelForm):
username = forms.CharField(max_length=200)
email = forms.EmailField(widget=forms.EmailInput())
password = forms.CharField(widget=forms.PasswordInput())
confirm_password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ['email','username','password',]
def clean(self):
cleaned_data = super(CUForm, self).clean()
password = cleaned_data.get('password')
confirm_password = cleaned_data.get('confirm_password')
if password != confirm_password:
raise forms.ValidationError('Password does not match.')
and admin
class CostumeUserAdmin(UserAdmin):
list_display = ('email', 'username', 'is_active', 'is_admin')
filter_horizontal = ()
list_filter = ('is_staff',)
fieldsets = ()
admin.site.register(User, CostumeUserAdmin)
I have read some of the solutions and I changed
user = self.model(
username=username,
email=self.normalize_email(email)
)
to
user = User.objects.create_user(
username=username,
email=self.normalize_email(email),
)
Alrigh I have fixed the "Invalid password format or unknown hashing algorithm." issue by adding this to my createView:
def form_valid(self, form):
user = form.save(commit=False)
password = self.request.POST['password']
user.set_password(password)
user.save()
return super().form_valid(form)
and the password now saves correctly, not sure why but it does.
And then I realized I didn't add AUTH_USER_MODEL = 'accounts.User'
in my setting.py!
I still don't know why I need to use set_password in form_valid even tho I used it in UseManager but now It works!
I'm currently working on a django project and I have a custom user model in my django app. Custom user authentication is working perfectly, but the issue I'm facing is whenever I'm logging into admin account in the django admin site, it logs out the previous user(let say, user2) and admin being logged in.
How Can I separate their login, so that admin site logins don't interfere with my website login?
Here is my code attached:
Custom User model and its manager:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class CustomerManager(BaseUserManager):
def create_user(self, email, username, name, password=None):
if not email:
raise ValueError('Users must have an email address to register')
if not username:
raise ValueError('Users must have an username address to register')
if not name:
raise ValueError('Users must enter their name to register')
user = self.model(
email = self.normalize_email(email),
username = username,
name=name,
)
user.set_password(password)
user.save(using = self._db)
return user
def create_superuser(self, email, username, name, password=None):
user = self.create_user(
email = self.normalize_email(email),
username = username,
name=name,
password=password,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class Customer(AbstractBaseUser):
# user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)
email = models.EmailField(max_length=254, null=True, unique=True)
username = models.CharField(max_length=40, unique=True)
name = models.CharField(max_length=200)
phone = models.CharField(max_length=10, null=True)
address = models.CharField(max_length=500, null=True)
date_joined = models.DateTimeField(auto_now_add=True)
last_login = models.DateTimeField(auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username', 'name']
objects = CustomerManager()
def __str__(self):
return self.name
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
Login View:
def loginUser(request):
if request.user.is_authenticated:
return redirect('home')
else:
if request.method == 'POST':
email = request.POST.get('email')
password = request.POST.get('password')
user = authenticate(request, email=email, password=password)
if user is not None:
login(request, user)
return redirect('home')
else:
messages.info(request, 'Email or Password didn\'t match!')
context = {}
return render(request, 'accounts/login.html', context)
Logout View:
#login_required(login_url='login')
def logoutUser(request):
logout(request)
return redirect('login')
User Profile View:
#login_required(login_url='login')
def userProfile(request, email):
customer = Customer.objects.filter(email=email).first()
context = {'customer':customer}
return render(request, 'accounts/profile.html', context)
CreateUserForm and LoginForm:
class CreateUserForm(UserCreationForm):
class Meta:
model = Customer
fields = ['username', 'email', 'name', 'password1', 'password2']
# fields = '__all__'
class LoginForm(forms.ModelForm):
password = forms.CharField(label='password', widget=forms.PasswordInput)
class Meta:
model = Customer
fields = ['email', 'password']
def clean(self):
email = self.cleaned_data['email']
password = self.cleaned_data['password']
if not authenticate(email=email, password=password):
raise forms.ValidationError('Incorrect Login')
When User3 is logged in and admin is not logged in:
As soon as admin logged in:
User3 automatically logs out and admin logs in..
I've created custom user model, and i'm trying to filter data in views.py by that user.
The error i get is:
'SomeClassView' object has no attribute 'user'
My goal is to 'encapsulate' data for each user.
user model:
class CustomUserManger(BaseUserManager):
use_in_migrations = True
def create_user(self, email, username, password, **other_fields):
email = self.normalize_email(email)
user = self.model(email=email, username=username, **other_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password, **other_fields):
other_fields.setdefault('is_staff', True)
other_fields.setdefault('is_superuser', True)
other_fields.setdefault('is_active', True)
if other_fields.get('is_staff') is not True:
raise ValueError('Superuser must be assigned to staff')
if other_fields.get('is_superuser') is not True:
raise ValueError('Superuser must be assigned to superusers')
return self.create_user(email, username, password, **other_fields)
class User(AbstractUser, PermissionsMixin):
username = models.CharField(_('username'), max_length=20, unique=True)
email = models.EmailField(unique=True)
password = models.CharField(max_length=128)
is_staff = models.BooleanField(default=True)
is_active = models.BooleanField(default=True)
objects = CustomUserManger()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
def __str__(self):
return self.username
Views:
class SomeClassView(viewsets.ModelViewSet):
user = SomeClass.user
serializer_class = WagonSerializer
authentication_classes = (SessionAuthentication, )
#login_required
def get_queryset(self):
user = self.request.user
return SomeClass.objects.filter(user=user)
Ok, i forgot that my react app doesn't put user to json, so in database user was null, that's why table was blank.
Basically what I have done so far is create a registration page where the user makes their username and password, then that password is stored in as a hashed password (md5 hasher). The problem I am having is logging in. The user inputs their username and password then the password is authenticated by using authenticate() method in django. The problem is that authenticate() is returning None instead of matching the user and password in the database. I dont know if this affects anything but I am using PostgreSQL.
models.py
class MyAccountManager(BaseUserManager):
def create_user(self, email,username,first_name,password= None):
if not email:
raise ValueError('User must have an email address')
if not username:
raise ValueError('User must have a username')
if not first_name:
raise ValueError('User must have a first name')
user= self.model(
email=self.normalize_email(email),
username= username,
first_name= first_name
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, first_name, password):
user= self.create_user(
email= self.normalize_email(email),
username=username,
first_name= first_name,
password= password,
)
user.is_admin= True
user.is_staff= True
user.is_superuser= True
user.save(using=self._db)
return user
class User(AbstractBaseUser, models.Model):
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
date_joined = models.DateTimeField(auto_now_add=True, verbose_name='date joined')
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
USERNAME_FIELD= 'username'
REQUIRED_FIELDS= ['email','first_name']
objects= MyAccountManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
forms.py
class LoginForm(forms.Form):
username = forms.CharField(initial='' ,label='Username:',max_length=30)
password = forms.CharField(max_length=20, widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'password')
def clean(self):
cleaned_data = super(LoginForm, self).clean()
confirm_password = cleaned_data.get('password')
class SignUpForm(forms.ModelForm):
first_name = forms.CharField(required= True,initial='',max_length=20)
last_name = forms.CharField(required=True,max_length=30, initial='')
username = forms.CharField(max_length=30,initial='', required=True)
password = forms.CharField(max_length= 20, initial='', widget = forms.PasswordInput())
password2= forms.CharField(max_length=20, initial='',widget = forms.PasswordInput())
email = forms.EmailField(max_length=60, initial='',)
class Meta:
model = User
fields = ('first_name', 'last_name','username','password2','email')
def clean(self):
cleaned_data = super(SignUpForm,self).clean()
password = cleaned_data.get('password')
confirm_password = cleaned_data.get('password2')
if(password != confirm_password):
raise forms.ValidationError(
'Password and Confirm Password do not match.'
)
views.py
def signin_and_signup(request):
if request.method == 'POST':
logout(request)
sign_in = LoginForm(request.POST)
signup = SignUpForm(request.POST)
if 'sign-in-name' in request.POST:
if sign_in.is_valid():
username = request.POST.get('username')
password= request.POST.get('password')
user = authenticate(username= username, password= password)
if user:
return HttpResponse('success')
else:
return HttpResponse('fail')
elif 'sign-up-input-name' in request.POST:
if(signup.is_valid()):
user = signup.save(commit=False)
nonHashed = signup.cleaned_data['password']
varhash = make_password(nonHashed, None, 'md5')
user.set_password(varhash)
user.save()
else:
print("Ran3<------------")
signup = SignUpForm()
else:
sign_in = LoginForm()
signup = SignUpForm()
context = {'signin':sign_in, 'signup':signup}
return render(request, 'home.html', context)
Why are you substituting the user model that django provides if you have the same attributes?
This is done in case you want to extend or add new properties to the user, for example, license number, avatar, position.
Anyway, your authenticate() maybe doesn't work because you haven't registered your new model in settings.py.
AUTH_USER_MODEL = 'name_of_the_app.User'
I recommend that you take a look at the official documentation
https://docs.djangoproject.com/en/3.1/topics/auth/customizing/
Antoher thing it could be your authentication backend:
Try:
settings.py
AUTHENTICATION_BACKENDS = [
'name_of_the_app.admin.LoginBackend',
]
Where you want for example admin.py
from django.contrib.auth.backends import ModelBackend, UserModel
from django.db.models import Q
class LoginBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
try: # to allow authentication through phone number or any other field, modify the below statement
user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
except UserModel.DoesNotExist:
UserModel().set_password(password)
except MultipleObjectsReturned:
return models.User.objects.filter(email=username).order_by('id').first()
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
def get_user(self, user_id):
try:
user = UserModel.objects.get(pk=user_id)
except UserModel.DoesNotExist:
return None
return user if self.user_can_authenticate(user) else None
As you can see, you can also login with the email
I'm trying to build super user using a custom user model and a custom user manager. I did exactly the same thing than the django doc about the create_superuser method and in my shell, I'm able to create a superuser with an email and a password. But when I try to log in on the django admin page, I have this wierd error :
Please enter the correct email and password for a staff account. Note
that both fields may be case-sensitive.
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from django.db import models
from multiselectfield import MultiSelectField
class UserManager(BaseUserManager):
#custom create_user method
def create_user(self, email, password=None):
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email = self.normalize_email(email)
)
user.set_password = password
user.save(using=self._db)
return user
#Custom create_super_user method
def create_superuser(self, email, password=None):
user = self.create_user(
email = self.normalize_email(email),
password = password
)
user.admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
#setting up Choices for interest, Must add other fields ...
MATHS = 'mat'
PHYSICS = 'phy'
HISTORY = 'his'
BIOLOGIE = 'bio'
ECONOMICS = 'eco'
POLITICS = 'pol'
MUSIC = 'mus'
ENGLISH = 'eng'
FRENCH = 'fra'
SPANISH = 'spa'
LAW = 'law'
COMPUTER_SCIENCE = 'cs'
COMMUNICATION = 'com'
MARKETING = 'mar'
SPORT = 'spo'
INTERESTS_CHOICES = (
(MATHS, 'Maths'),
(PHYSICS, 'Physics'),
(HISTORY, 'History'),
(BIOLOGIE, 'Biologie'),
(ECONOMICS, 'Economics'),
(POLITICS, 'Politics'),
(MUSIC, 'Music'),
(ENGLISH, 'English'),
(FRENCH, 'French'),
(SPANISH, 'Spanish'),
(LAW, 'Law'),
(COMPUTER_SCIENCE, 'Computer Science'),
(COMMUNICATION, 'Communication'),
(MARKETING, 'Marketing'),
(SPORT, 'Sport')
)
interests = MultiSelectField(
max_length = 2,
choices = INTERESTS_CHOICES
)
#Setting up a Ranking System
RANKING_CHOICES = [
('silver', 'Silver'),
('gold', 'Gold'),
('platinium', 'Platinium'),
('diamond', 'Diamond')
]
email = models.EmailField(
max_length=50,
unique=True
)
username = models.CharField(
max_length=25,
unique=True,
null=True,
blank=True
)
date_joined = models.DateTimeField(auto_now_add=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=70)
birth_date = models.DateField(null=True, blank=True)
reputation = models.PositiveIntegerField(default=0)
active = models.BooleanField(default=True)
rank = models.CharField(choices=RANKING_CHOICES, max_length=1)
staff = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
bio = models.TextField(
max_length=300,
default="",
blank=True
)
objects = UserManager()
#Setting email to be the main source of authentication
USERNAME_FIELD = 'email'
#Super User Only
REQUIRED_FIELDS = ['password']
#def get_absolute_url(self):
#use reverse + nom de l'url de view
def __str__(self):
return self.email
def get_full_name(self):
return f"{self.first_name} {self.last_name}"
def get_short_name(self):
return self.first_name
def get_username(self):
return self.username
def set_user_league(self):
if 15 <= self.reputation < 40:
self.rank = "gold"
elif 40 <= self.reputation < 80:
self.rank = "platinium"
else:
self.rank = "diamond"
You set a password by calling .set_password(..), not assigning a new value:
class UserManager(BaseUserManager):
#custom create_user method
def create_user(self, email, password=None):
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email = self.normalize_email(email)
)
user.set_password(password)
user.save(using=self._db)
return user
The default create_superuser will set is_staff and is_superuser to True as well:
#Custom create_super_user method
def create_superuser(self, email, password=None):
user = self.create_user(
email = self.normalize_email(email),
password = password
)
user.admin = user.is_superuser = user.is_staff = True
user.save(using=self._db)
return user
We need to set the flag is_superuser to True, in order to make user a superuser in system. Please find the below code:
def create_superuser(self, email, password):
"""
create and save superuser
"""
user = self.create_user(
self.normalize_email(email), password=password)
user.is_staff = True
user.is_superuser = True
user.admin = True
user.save(using=self._db)
return user