JWT token mismatch while OTP verification - python

I'm generating token while user verified OTP. but while i verify the token in header then I'm getting Invalid payload.
if any help for why i'm getting this error then would be much appreciated.
serializers.py :
class OTPVerifyForResetPasswordAPIView(APIView):
permission_classes = (AllowAny,)
def post(self,request,*args,**kwargs):
data = request.data
user = request.user
print(user)
phone_number = request.data['phone_number']
country_code = request.data['country_code']
verification_code = request.data['verification_code']
if phone_number and country_code and verification_code:
obj_qs = User.objects.filter(phone_number__iexact = phone_number,country_code__iexact = country_code)
obj = ''
if obj_qs.exists() and obj_qs.count() ==1:
user_obj = obj_qs.first()
#Development
if verification_code == '1234':
payload = jwt_payload_handler(user_obj)
token = jwt_encode_handler(payload)
token = 'JWT '+str(token)
return Response({
'success' : 'True',
'message' : 'Your mobile number verified successfully',
'data' : {
'phone_number' : user_obj.phone_number,
'country_code' : user_obj.country_code,
'token' : token,
}
},status=HTTP_200_OK)
else:
##some logic....
else:
## some logic...

I see an open issue in django-rest-framework-jwt about a similar problem: https://github.com/jpadilla/django-rest-framework-jwt/issues/284
It looks like this library isn't maintained for a few years already, I'd probably suggest you switching to some alternative, they suggest using this one: https://github.com/SimpleJWT/django-rest-framework-simplejwt

Edit the line with user_obj = obj_qs.first() to be like
user_obj = {
'username': obj_qs.first().username,
...
}

Related

How to customize the in_active user error message for rest_framework_simplejwt in Django

I have set my multiple user model in Django rest framework and I am using dj_rest_auth, allauth and djangosimplejwt for my user Authentication and Authorisation workflow
my serialisers.py look like this
class LoginSerializer(Serializer):
email = EmailField(required=False, allow_blank=True)
password = CharField(style={'input_type': 'password'})
class Meta:
model = Users
fields = ['email', 'password']
extra_kwargs = {
'password': {'write_only': True},
'style': {'input_type': 'password'},
}
def authenticate(self, **kwargs):
return authenticate(self.context['request'], **kwargs)
def _validate_email(self, email, password):
if email and password:
user = self.authenticate(email=email, password=password)
else:
msg = {'error': _('Did you forget to include an email or password?')}
raise ValidationError(msg)
return user
def get_auth_user_using_allauth(self, email, password):
from allauth.account import app_settings
# Authentication through email
if (
app_settings.AUTHENTICATION_METHOD
== app_settings.AuthenticationMethod.EMAIL
):
return self._validate_email(email, password)
def get_auth_user(self, email, password):
"""
Retrieve the auth user from given POST payload by using
either `allauth` auth scheme or bare Django auth scheme.
Returns the authenticated user instance if credentials are correct,
else `None` will be returned
"""
if 'allauth' in settings.INSTALLED_APPS:
# When `is_active` of a user is set to False, allauth tries to return template html
# which does not exist. This is the solution for it. See issue #264.
try:
return self.get_auth_user_using_allauth(email, password)
except url_exceptions.NoReverseMatch:
msg = {'error': _('Unable to log in with provided credentials.')}
# msg = 'Unable to log in with provided credentials.'
raise exceptions.ValidationError(msg)
return self.get_auth_user_using_orm(email, password)
#staticmethod
def validate_auth_user_status(user):
if not user.is_active:
msg = _('User account is disabled.')
raise exceptions.ValidationError(msg)
#staticmethod
def validate_email_verification_status(user):
from allauth.account import app_settings
if (
app_settings.EMAIL_VERIFICATION
== app_settings.EmailVerificationMethod.MANDATORY
):
email_address = user.emailaddress_set.get(email=user.email)
if not email_address.verified:
raise exceptions.ValidationError(
{'error': _('E-mail is not verified.')}
)
def validate(self, data):
email = data.get('email')
password = data.get('password')
user = self.get_auth_user(email, password)
if not user:
msg = {'error': _('Unable to log in with provided credentials.')}
raise exceptions.ValidationError(msg)
# Did we get back an active user?
self.validate_auth_user_status(user)
# If required, is the email verified?
if 'dj_rest_auth.registration' in settings.INSTALLED_APPS:
self.validate_email_verification_status(user)
data['user'] = user
return data
and my views.py looks like this
class Login(LoginView):
"""
Check the credentials and return the REST Token
if the credentials are valid and authenticated.
Calls Django Auth login method to register User ID
in Django session framework
Accept the following POST parameters: username, password
Return the REST Framework Token Object's key.
"""
serializer_class = LoginSerializer
def post(self, request, *args, **kwargs):
self.request = request
self.serializer = self.get_serializer(data=self.request.data)
self.serializer.is_valid(raise_exception=True)
self.login()
return self.get_response()
def get_all_clients(self):
"""
Using related objects, get all clients of the business
"""
business = self.request.user
business_client = ClientProfile.objects.filter(business=business)
client_list = business_client.values(
'client__id',
'client__email',
'client__fullname',
'logo',
)
# rename the keys in clean_names
for client in client_list:
client['id'] = client.pop('client__id')
client['email'] = client.pop('client__email')
client['fullname'] = client.pop('client__fullname')
client['logo'] = (
f"{self.request.META['HTTP_HOST']}{business.profile_image.url}"
if client['logo']
else None
)
return client_list
# display user profile information based on type of user
def get_response(self):
response = super().get_response()
user = self.request.user
if user.type.name == "Business":
profile = {
'profile': {
'business_logo': f"{self.request.META['HTTP_HOST']}{user.businessprofile.logo.url}"
if user.businessprofile.logo
else None,
'business_name': user.businessprofile.business_name,
'user_type': user.type.name,
'client_list': self.get_all_clients(),
}
}
response.data.update(profile)
return response
elif user.type.name == 'Client':
profile = {
'profile': {
'logo': (
f"{self.request.META['HTTP_HOST']}{user.clientprofile.logo.url}"
)
if user.clientprofile.logo
else None,
'name': user.clientprofile.client_business_name,
'type': user.type.name,
'full_name': user.fullname,
'country': user.country.name,
}
}
response.data.update(profile)
return response
first thing I notice is when a user has an inactive account i.e user.is_active I want to write a more meaningful message to make it easy for the frontend but when I use the browsable api I get
{
"error": [
"Unable to log in with provided credentials."
]
}
and when I use postman I get a 401 error dictionary
{
"detail": "User is inactive",
"code": "user_inactive"
}
the above error comes when I use the dj_rest_auth documentation that says I should add
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'dj_rest_auth.jwt_auth.JWTCookieAuthentication',
),
}
But if I follow Django simplejwt documentation it says
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
I only get this both on postman and browsable api endpoint
{
"error": [
"Unable to log in with provided credentials."
]
}
I will appreciate if I can get a valid way to get the proper error message that I want and a little explanation on why there are different error codes and documentation for using this

Staying login problem about CallbackURL after payment

my view is like :
def get_user_pending_order(request):
user_profile = get_object_or_404(Profile, user=request.user)
order = Order.objects.filter(owner=user_profile, is_ordered=False)
if order.exists():
return order[0]
return 0
MERCHANT = 'xxx...xxx'
ZP_API_REQUEST = "https://api.zarinpal.com/pg/v4/payment/request.json"
ZP_API_VERIFY = "https://api.zarinpal.com/pg/v4/payment/verify.json"
ZP_API_STARTPAY = "https://www.zarinpal.com/pg/StartPay/{authority}"
amount = ''
description = "text" # Required
email = 'example#email.com' # Optional
mobile = '09999999999' # Optional
# Important: need to edit for realy server.
CallbackURL = 'https://example.com/payment/verify/'
def send_request(request):
print(get_user_pending_order(request).owner.phone_number)
req_data = {
"merchant_id": MERCHANT,
"amount": int(get_user_pending_order(request).get_total()),
"callback_url": CallbackURL,
"description": description,
"metadata": {"mobile": mobile,
"email": email}
}
req_header = {"accept": "application/json",
"content-type": "application/json'"}
req = requests.post(url=ZP_API_REQUEST, data=json.dumps(
req_data), headers=req_header)
authority = req.json()['data']['authority']
if len(req.json()['errors']) == 0:
return redirect(ZP_API_STARTPAY.format(authority=authority))
else:
e_code = req.json()['errors']['code']
e_message = req.json()['errors']['message']
return HttpResponse(f"Error code: {e_code}, Error Message: {e_message}")
def verify(request):
t_status = request.GET.get('Status')
t_authority = request.GET['Authority']
if request.GET.get('Status') == 'OK':
req_header = {"accept": "application/json",
"content-type": "application/json'"}
req_data = {
"merchant_id": MERCHANT,
"amount": int(get_user_pending_order(request).get_total()),
"authority": t_authority
}
req = requests.post(url=ZP_API_VERIFY, data=json.dumps(req_data), headers=req_header)
if len(req.json()['errors']) == 0:
t_status = req.json()['data']['code']
if t_status == 100:
user = request.user
order_to_purchase = get_user_pending_order(request)
order_to_purchase.is_ordered = True
order_to_purchase.date_ordered=datetime.datetime.now()
order_to_purchase.created_on_time=datetime.datetime.now()
order_to_purchase.save()
order_items = order_to_purchase.items.all()
for order_item in order_items:
order_item.product.quantity = order_item.product.quantity - 1
order_item.product.save()
order_items.update(is_ordered=True, date_ordered=datetime.datetime.now())
subject = 'successful'
c = {
"refid":str(req.json()['data']['ref_id']),
"ref_code":order_to_purchase.ref_code,
"owner":order_to_purchase.owner,
}
email_template_name = "pay/after_pay_confirm_email.html"
email_html = render_to_string(email_template_name, c)
email_from = settings.EMAIL_HOST_USER
send_mail(subject, email_html, email_from, [user.email], html_message=email_html)
ctx = {'message_good':'good'}
return render(request, 'pay/verify.html', ctx)
elif t_status == 101:
...
else:
....
else:
...
else:
...
At first about user, is logged. and about send_request function it work totally fine...so it pass user into Payment gateway and after successful payment it come back to verify function by CallbackURL. to show success page and do order_to_purchase.is_ordered = True ...
for me with my pc, phone, other android phones, ios, windows, linux. and about browsers like chrome Firefox it work correctly and everything is fine.
but some clients tell me they face to 'AnonymousUser' object is not iterable after successful payment and when they back to verify. its kinda like that they logged out by pushing request to payment gateway.
also i made purchase by that account exactly same way and i didn't face to that error. it show is that phone or browser problem that half of my clients faced to that. i have no idea what should i do!!!

Django Access Token Matching Query Does Not Exist

I have the following code I am trying to test:
def customer_add_order(request):
"""
params:
access_token
restaurant_id
address
order_details(json format), example:
[{"meal_id": 1, "quantity":2}, {"meal_id": 2, "quantity":3}]
stripe_token
return:
{"status": "success"}
"""
if request.method == "POST":
#Get token
access_token = AccessToken.objects.get(token = request.POST.get("access_token"),
expires__gt = timezone.now())
#Get profile
customer = access_token.user.customer
# Check if customer has a order that is not delivered
if Order.objects.filter(customer = customer).exclude(status = Order.DELIVERED):
return JsonResponse({"status": "fail", "error": "Your Last Order must be completed"})
# Check Address
if not request.POST("address"):
return JsonResponse({"status": "failed", "error": "Address is required."})
# Ger Order Details
order_details = json.load(request.POST["order_details"])
order_total = 0
for meal in order_details:
order_total += Meal.objects.get(id = meal["meal_id"]).price * meal[quantity]
if len(order_details)>0:
# Step 1 - Create an Order
order = Order.objects.create(
customer = customer,
restaurant_id = request.POST["restaurant_id"],
total = order_total,
status = Order.PENDING,
address = request.POST["address"]
)
# Step 2 - Create Order details
for meal in order_details:
OrderDetails.objects.create(
order = order,
meal_id = meal["meal_id"],
quantity = meal["quantity"],
sub_total = Meal.objects.get(id = meal["meal_id"]).price * meal["quantity"]
)
return JsonResponse({"status": "success"})
I enter the params in Postman, and use an access token that shows valid in django, and it hasn't expired. I am using the rest framework and the function is for API.
I use the following function for creating Access Token:
def create_user_by_type(backend, user, response, *args, **kwargs):
request = backend.strategy.request_data()
if backend.name == 'facebook':
avatar = 'https://graph.facebook.com/%s/picture?type=large' % response['id']
if request.get("user_type") == "driver" and not Driver.objects.filter(user_id=user.id):
Driver.objects.create(user_id=user.id, avatar = avatar)
elif not Customer.objects.filter(user_id=user.id):
Customer.objects.create(user_id=user.id, avatar = avatar)
Also, the line if request.get("user_type") == "driver" and not Driver.objects.filter(user_id=user.id): previously had an error because I had it in an outdated format request["user_type"]. Not sure if this is correct syntax for what I want to do, but I can create Access Tokens through Postman.
The issue was I was using the params in Postman to enter the Access Token and other information, instead it should in in 'body' with form-data selected.

Django REST Framework received JPEG file as a String to ImageField

I have a model in Django like:
from django.db import models
from django.contrib.auth.models import User
from datetime import datetime
# Create your models here.
class UserDetails(models.Model):
def getFileName(self, filename):
return 'profile_pics/'+str(self.user.id)+'/'+filename
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
profile_picture = models.ImageField(upload_to=getFileName, blank = True)
country = models.CharField(max_length = 50, default='UK')
gender = models.CharField(max_length=10, default='NA')
birthday = models.DateField(default=datetime.now())
phone = models.CharField(max_length=15)
verified = models.BooleanField(default=False)
def __str__(self):
try:
return self.user.username
except:
return 'Deleted User - '+str(self.phone)
Then, I created a REST API that accepts Multipart requests to create a new user as well as save the user_details for the user. I am making the multipart POST request from my app in Flutter with the Image for the profile picture. The image is coming in the body of the request as a String instead of coming in as a file, where I could have read it with request.FILES['profile_picture']. The body of the request that I am getting by doing a print(request.data) is as follows:
Data: <QueryDict: {
'username': ['jonsnow'],
'first_name': ['Jon'],
'last_name': ['Snow'],
'email': ['jonsnow#got.com'],
'password': ['jonsnow'],
'country': ['UK'],
'gender': ['Male'],
'birthday': ['2020-4-28'],
'phone': ['5198189849'],
'profile_picture': ['����\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00��\x00�\x00\t\x06\x07\x08\x07\x06\t\x08\x07\x08\n\n\t\x0b\r\x16\x0f\r\x0c\x0c\r\x1b\x14\x15\x10\x16 \x1d"" \x1d\x1f\x1f$(4,$&1\'\x1f\x1f-=-157:::#+?D?8C49:7\x01\n\n\n\r\x0c\r\x1a\x0f\x0f\x1a7%\x1f%77777777777777777777777777777777777777777777777777��\x00\x11\x08\x019\x01�\x03\x01"\x00\x02\x11\x01\x03\x11\x01��\x00\x1c\x00\x00\x02\x03\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x04\x02\x05\x06\x01\x07\x00\x08��\x00Q\x10\x00\x02\x01\x03\x02\x03\x05\x04\x06\x06\x07\x07\x03\x03\x01\t\x01\x02\x03\x00\x04\x11\x12!\x051A\x06\x13"Qa2q��\x14B����\x07#3Rr�\x154Sbs��\x16$C����5��%c�DtEFd����\x17��\x00\x1a\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06��\x00(\x11\x01\x01\x00\x02\x01\x04\x02\x02\x02\x02\x03\x01\x00\x00\x00\x00\x00\x01\x02\x11\x03\x12!1A\x04\x13\x14Q\x05"aqBR�\x15��\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00�Cl�0ɵX��¸�iB�k; ...\uebe8?��']
}>
And print(request.FILES) is coming as: Files: <MultiValueDict: {}>
So, I made the Multipart REST API to handle this request like:
class SignUp(APIView):
parser_classes = [MultiPartParser,]
authentication_classes = [CsrfExemptSessionAuthentication]
permission_classes = [AllowAny]
def post(self, request, format=None):
data = request.data
print('\n\nFiles: '+str(request.FILES)+'\n\n');
print('\n\nData: '+str(data)+'\n\n');
print('\n\nData: '+str(request.META)+'\n\n');
## Creating a basic user
user = User.objects.create_user(username=data['username'], first_name = data['first_name'], last_name = data['last_name'], email = data['email'], password = data['password'])
user.save()
user_details = UserDetails()
user_details.user = user
rec_img_str = data['profile_picture']
rec_img_bytes = rec_img_str.encode('utf-8')
rec_img_writer = BytesIO(rec_img_bytes)
uploaded_img = InMemoryUploadedFile(rec_img_writer, None, 'sample.jpg', 'image/jpeg', None, 'utf-8')
user_details.profile_picture = uploaded_img
user_details.country = data['country']
user_details.gender = data['gender']
user_details.birthday = datetime.strptime(data['birthday'], '%Y-%m-%d').date()
user_details.phone = data['phone']
user_details.verified = False
user_details.save()
return Response({'Message': 'Profile Created Successfully'})
Here, I read the JPG image that comes as a string in the field profile_picture, converted it to Byte form, put it into BytesIO(), and then stored it in user_details.profile_picture as an InMemoryUploadedFile. It saves as sample.jpg in my MEDIA directory, but when I try to open it, it comes as a blank image.
So, how do I save the JPEG image that is coming in as a string to a ImageField in Django?
Here's my Flutter code, if it is needed for reference:
void submit() async {
MultipartRequest request = MultipartRequest("POST",
Uri.parse("http://10.0.2.2:8000/services/authentication/signup/"));
request.fields['username'] = this.username.text;
request.fields['first_name'] = this.first_name.text;
request.fields['last_name'] = this.last_name.text;
request.fields['email'] = this.email.text;
request.fields['password'] = this.password.text;
request.fields['country'] = "UK";
request.fields['gender'] = this.gender;
String birthdayStr = "${birthday.year}-${birthday.month}-${birthday.day}";
request.fields['birthday'] = birthdayStr;
request.fields['phone'] = this.phone_no.text;
if (this.profilePicture != null) {
print('Profile picture available');
print(this.profilePicture.path);
request.files.add(
await MultipartFile.fromBytes(
'profile_picture',
await this.profilePicture.readAsBytes(), //this.profilePicture is a File
contentType: MediaType('image', 'jpeg'),
),
);
}
StreamedResponse resp = await request.send();
if (resp.statusCode < 200 || resp.statusCode >= 400) {
print('There was an error in making the SignUp Request');
print('Status code: ${resp.statusCode}');
} else {
Navigator.pop(context);
}
}

How do I get the google username and email when someone logins to my site? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
the next is mysite1\django_openid\registration.py:
from django.http import HttpResponseRedirect
from django.core.mail import send_mail
from django.conf import settings
from django_openid.auth import AuthConsumer
from django_openid.utils import OpenID, int_to_hex, hex_to_int
from django_openid import signed
from django_openid import forms
from openid.consumer import consumer
import urlparse
class RegistrationConsumer(AuthConsumer):
already_signed_in_message = 'You are already signed in to this site'
unknown_openid_message = \
'That OpenID is not recognised. Would you like to create an account?'
c_already_confirmed_message = 'Your account is already confirmed'
register_template = 'django_openid/register.html'
set_password_template = 'django_openid/set_password.html'
confirm_email_template = 'django_openid/register_confirm_email.txt'
register_email_sent_template = 'django_openid/register_email_sent.html'
register_complete_template = 'django_openid/register_complete.html'
after_registration_url = None # None means "show a message instead"
unconfirmed_group = 'Unconfirmed users'
# Registration options
reserved_usernames = ['security', 'info', 'admin']
no_duplicate_emails = True
confirm_email_addresses = True
confirm_email_from = None # If None, uses settings.DEFAULT_FROM_EMAIL
confirm_email_subject = 'Confirm your e-mail address'
confirm_link_secret = None
confirm_link_salt = 'confirm-link-salt'
# sreg
sreg = ['nickname', 'email', 'fullname']
RegistrationForm = forms.RegistrationFormPasswordConfirm
ChangePasswordForm = forms.ChangePasswordForm
def user_is_confirmed(self, user):
return not self.user_is_unconfirmed(user)
def user_is_unconfirmed(self, user):
return user.groups.filter(name = self.unconfirmed_group).count()
def mark_user_unconfirmed(self, user):
from django.contrib.auth.models import Group
user.is_active = False
user.save()
group, _ = Group.objects.get_or_create(name = self.unconfirmed_group)
user.groups.add(group)
def mark_user_confirmed(self, user):
user.groups.filter(name = self.unconfirmed_group).delete()
def get_registration_form_class(self, request):
return self.RegistrationForm
def get_change_password_form_class(self, request):
return self.ChangePasswordForm
def show_i_have_logged_you_in(self, request):
return self.show_message(
request, 'You are logged in',
'You already have an account for that OpenID. ' +
'You are now logged in.'
)
def do_register_complete(self, request):
def on_success(request, identity_url, openid_response):
# We need to behave differently from the default AuthConsumer
# success behaviour. For simplicity, we do the following:
# 1. "Log them in" as that OpenID i.e. stash it in the session
# 2. If it's already associated with an account, log them in as
# that account and show a message.
# 2. If NOT already associated, redirect back to /register/ again
openid_object = OpenID.from_openid_response(openid_response)
matches = self.lookup_openid(request, identity_url)
if matches:
# Log them in and show the message
self.log_in_user(request, matches[0])
response = self.show_i_have_logged_you_in(request)
else:
response = HttpResponseRedirect(urlparse.urljoin(
request.path, '../register/'
))
self.persist_openid(request, response, openid_object)
return response
return self.dispatch_openid_complete(request, {
consumer.SUCCESS: on_success,
consumer.CANCEL:
lambda request, openid_response: self.do_register(request,
message = self.request_cancelled_message
),
consumer.FAILURE:
lambda request, openid_response: self.do_register(request,
message = self.failure_message % openid_response.message
),
consumer.SETUP_NEEDED:
lambda request, openid_response: self.do_register(request,
message = self.setup_needed_message
),
})
def on_registration_complete(self, request):
if self.after_registration_url:
return HttpResponseRedirect(self.after_registration_url)
else:
return self.render(request, self.register_complete_template)
def do_register(self, request, message=None):
# Show a registration / signup form, provided the user is not
# already logged in
if not request.user.is_anonymous():
return self.show_already_signed_in(request)
# Spot incoming openid_url authentication requests
if request.POST.get('openid_url', None):
return self.start_openid_process(request,
user_url = request.POST.get('openid_url'),
on_complete_url = urlparse.urljoin(
request.path, '../register_complete/'
),
trust_root = urlparse.urljoin(request.path, '..')
)
RegistrationForm = self.get_registration_form_class(request)
try:
openid = request.openid and request.openid.openid or None
except AttributeError:
return self.show_error(
request, 'Add CookieConsumer or similar to your middleware'
)
if request.method == 'POST':
# TODO: The user might have entered an OpenID as a starting point,
# or they might have decided to sign up normally
form = RegistrationForm(
request.POST,
openid = openid,
reserved_usernames = self.reserved_usernames,
no_duplicate_emails = self.no_duplicate_emails
)
if form.is_valid():
user = self.create_user(request, form.cleaned_data, openid)
if self.confirm_email_addresses:
return self.confirm_email_step(request, user)
else:
self.log_in_user(request, user)
return self.on_registration_complete(request)
else:
form = RegistrationForm(
initial = request.openid and self.initial_from_sreg(
request.openid.sreg
) or {},
openid = openid,
reserved_usernames = self.reserved_usernames,
no_duplicate_emails = self.no_duplicate_emails
)
return self.render(request, self.register_template, {
'form': form,
'message': message,
'openid': request.openid,
'logo': self.logo_path or (urlparse.urljoin(
request.path, '../logo/'
)),
'no_thanks': self.sign_next(request.path),
'action': request.path,
})
def confirm_email_step(self, request, user):
self.mark_user_unconfirmed(user)
self.send_confirm_email(request, user)
return self.render(request, self.register_email_sent_template, {
'email': user.email,
})
def generate_confirm_code(self, user):
return signed.sign(int_to_hex(user.id), key = (
self.confirm_link_secret or settings.SECRET_KEY
) + self.confirm_link_salt)
def send_confirm_email(self, request, user):
from_email = self.confirm_email_from or settings.DEFAULT_FROM_EMAIL
code = self.generate_confirm_code(user)
path = urlparse.urljoin(request.path, '../c/%s/' % code)
url = request.build_absolute_uri(path)
send_mail(
subject = self.confirm_email_subject,
message = self.render(request, self.confirm_email_template, {
'url': url,
'code': code,
'user': user,
}).content,
from_email = from_email,
recipient_list = [user.email]
)
def do_c(self, request, token = ''):
if not token:
# TODO: show a form where they can paste in their token?
raise Http404
token = token.rstrip('/').encode('utf8')
try:
value = signed.unsign(token, key = (
self.confirm_link_secret or settings.SECRET_KEY
) + self.confirm_link_salt)
except signed.BadSignature:
return self.show_message(
request, self.invalid_token_message,
self.invalid_token_message + ': ' + token
)
user_id = hex_to_int(value)
user = self.lookup_user_by_id(user_id)
if not user: # Maybe the user was deleted?
return self.show_error(request, r_user_not_found_message)
# Check user is NOT active but IS in the correct group
if self.user_is_unconfirmed(user):
# Confirm them
user.is_active = True
user.save()
self.mark_user_confirmed(user)
self.log_in_user(request, user)
return self.on_registration_complete(request)
else:
return self.show_error(request, self.c_already_confirmed_message)
do_c.urlregex = '^c/([^/]+)/$'
def create_user(self, request, data, openid=None):
from django.contrib.auth.models import User
user = User.objects.create(
username = data['username'],
first_name = data.get('first_name', ''),
last_name = data.get('last_name', ''),
email = data.get('email', ''),
)
# Set OpenID, if one has been associated
if openid:
user.openids.create(openid = openid)
# Set password, if one has been specified
password = data.get('password')
if password:
user.set_password(password)
else:
user.set_unusable_password()
user.save()
return user
def do_password(self, request):
"Allow users to set a password on their account"
if request.user.is_anonymous():
return self.show_error(request, 'You need to log in first')
ChangePasswordForm = self.get_change_password_form_class(request)
if request.method == 'POST':
form = ChangePasswordForm(request.user, data=request.POST)
if form.is_valid():
u = request.user
u.set_password(form.cleaned_data['password'])
u.save()
return self.show_password_has_been_set(request)
else:
form = ChangePasswordForm(request.user)
return self.render(request, self.set_password_template, {
'form': form,
'action': request.path,
})
def show_password_has_been_set(self, request):
return self.show_message(
request, 'Password set', 'Your password has been set.'
)
def initial_from_sreg(self, sreg):
"Maps sreg to data for populating registration form"
fullname = sreg.get('fullname', '')
first_name, last_name = '', ''
if fullname:
bits = fullname.split()
first_name = bits[0]
if len(bits) > 1:
last_name = ' '.join(bits[1:])
return {
'username': self.suggest_nickname(sreg.get('nickname', '')),
'first_name': first_name,
'last_name': last_name,
'email': sreg.get('email', ''),
}
def suggest_nickname(self, nickname):
"Return a suggested nickname that has not yet been taken"
from django.contrib.auth.models import User
if not nickname:
return ''
original_nickname = nickname
suffix = None
while User.objects.filter(username = nickname).count():
if suffix is None:
suffix = 1
else:
suffix += 1
nickname = original_nickname + str(suffix)
return nickname
def show_unknown_openid(self, request, openid):
# If the user gets here, they have attempted to log in using an
# OpenID BUT it's an OpenID we have never seen before - so show
# them the index page but with an additional message
return self.do_index(request, self.unknown_openid_message)
def show_already_signed_in(self, request):
return self.show_message(
request, 'Already signed in', self.already_signed_in_message
)
and the login view:
def login(request, form_class=LoginForm, template_name="account/login.html",
success_url=None, associate_openid=False, openid_success_url=None,
url_required=False, extra_context=None):
if extra_context is None:
extra_context = {}
if success_url is None:
success_url = get_default_redirect(request)
if request.method == "POST" and not url_required:
form = form_class(request.POST)
if form.login(request):
if associate_openid and association_model is not None:
for openid in request.session.get('openids', []):
assoc, created = UserOpenidAssociation.objects.get_or_create(
user=form.user, openid=openid.openid
)
success_url = openid_success_url or success_url
return HttpResponseRedirect(success_url)
else:
form = form_class()
ctx = {
"form": form,
"url_required": url_required,
}
ctx.update(extra_context)
return render_to_response(template_name, ctx,
context_instance = RequestContext(request)
)
You ask the user. OpenID is inherently designed to not require providing anything except a user-unique identifier for authenticated users; any information beyond that is in the realm of application-specific.

Categories

Resources