django permissions to restrict view based on groups - django

I currently have an order management app. But the team I am creating this for has two departments the office and the factory who'll be using the same app but with each team having access to what they need. I'm confused if I should create two different apps to login into the same system (but that would redundant code) or if there's any other way I can set permissions. I have tried using the django admin permissions and they don't seem to work.

you can create different html pages for different teams like office team have their own html page and factory team have different html page .
def user_login(request):
if request.method == 'POST':
username=request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username,password=password)
if user:
if user.is_active:
if user.is_admin:
login(request,user)
return HttpResponseRedirect(reverse('adminpage'))
#return render(request,'admin.html')
else:
login(request,user)
return HttpResponseRedirect(reverse('userpage'))
#return render(request,'user.html')
else:
return HttpResponseRedirect('Account not active')
else:
#message={"info":"someone tried to login and failed! ","details":"username :{} and password: {}".format(username,password)}
return HttpResponse("someone tried to login and failed ! <br />details: <br />username: {} <br /> password:{} ".format(username,password))
else:
return render(request,'login.html')
you can create models with specified role as active according to condition.(you can create radio button for factory and office and according to radio button you models code work.
class MyUser(AbstractBaseUser):
email = models.EmailField(verbose_name='email address',max_length=255,unique=True,)
full_name = models.CharField(max_length=255,null=True,blank=True)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_agent = models.BooleanField(default=False)
choices are :
USER_CHOICES = (
('is_admin','ADMIN'),
('is_agent', 'AGENT')
)

You can have the same authentication page for both users and staff and redirect them to the same page, (suppose the dashboard ). Now you can add a link in the dashboard which is visible only if the logged in user is a superuser. The link would redirect to an admin interface.
The dashboard could be something common for both users.
Hope this helps.

Related

Django admin not showing users after user customization

I customized my user authentication. Using Django 3.
In models.py I have;
class User(AbstractUser):
is_patient = models.BooleanField(default=False)
is_dentist = models.BooleanField(default=False)
is_manager = models.BooleanField(default=False)
In views.py I have below for user creation and login;
def create_account_dentist(request):
if request.method == 'POST':
#Create Dentist Type User
username = request.POST.get('username')
password = request.POST.get('password')
mobile_num = request.POST.get('mobilenum')
user_profile = User()
user_profile.username = username
user_profile.email = username
user_profile.set_password(password)
user_profile.is_dentist = True
user_profile.is_staff = True
user_profile.is_active = True
user_profile.mobile_number = mobile_num
user_profile.save()
login(request, user_profile)
return redirect(reverse('dentist-section'))
My sttings.py : AUTH_USER_MODEL = 'myapp.User'
When i check /admin page i see only groups section.
But i want to see the users, permissions and user groups together.
My DB tables are :
auth_group,
auth_group_permissions,
auth_permission,
django_admin_log,
django_content_type,
django_migrations,
django_session,
myapp_dentist,
myapp_manager,
myapp_patient,
myapp_user,
myapp_user_groups,
myapp_user_user_permissions
Although i created users in myapp_user, i dont see and manage them in django admin page
Below is screeshot from myapp_user table :
You can check the admin.py file which is under the user's model folder, isn't it contain the admin.site.register(YUOR_MODEL_NAME) ,if you want to view the data in /admin page must have registered.
from django.contrib import admin
from YOUR_APP_NAME.models import User
admin.site.register(User)

How To Make User Profile In Django?

How To Make User Profile in Django?
Hi I Want to Know How To Make User Profile when user signup in our django app i want create a profile page for the person
Here is my Views.py
def user_reg(request):
register = False
if request.method == 'POST':
form = user_register_form(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.set_password(user.password)
user.save()
register = True
if register == True:
return HttpResponseRedirect("/accounts/login")
else:
print(form.errors)
else:
form = user_register_form()
context = {'reg':form,}
return render(request,'signup.html',context)
Models.py
class user_register_model(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
join_date = models.DateTimeField(default=timezone.now)
I Want To Know How To Create Profile Page If User sign Up in our website Problem is How To Create His Profile Page
For Example:
If You Register on Stack overflow You Click on profile icon and you can go to your page
Stack overflow Make Your Page
I Need Some Thing Like That
When User Signup i need user page but how to make that?
i research on google and youtube i can't find any prefect answer
can you please help me?
Create a URL in urls.py like this:
path('profile/<username>', views.user_profile, name='user_profile'),
views.py (If you are using User model to save user data.)
def user_profile(request, username):
user = User.objects.get(username=username)
context = {
"user": user
}
return render(request, 'user_profile.html', context)
user_profile.html (use profile data as per requirement)
{{ user.username }}
{{ user.first_name }}
You can check this on link http://127.0.0.1:8000/profile/<username>/. replace username with user's username and page will show data of only that user.
-----------Edit-----------
If you want to create link, use this:
<a class="nav-link navaour" href="{% url 'profile' username=<username> %}">
replace user's username.
You can just create a view with a template see this. You can have editable forms or anything you like. This view will be shown only if the user is logged in and for unauthorized users redirect them to your login page.

Handling duplicate email address in django allauth

What I am trying to do ?
I am trying to avoid duplicate email address by following these steps:
Before user login to my site from a social account I check to see if the email address already exists.
If no then login the user otherwise check the below steps.
Check to see if the provider of registered user match the user trying to login.
If no then don't allow user to login otherwise login the user.
What is the problem ?
I get the following error:
Error:AttributeError at /accounts/twitter/login/callback/
'QuerySet' object has no attribute 'profile'
My Code:
views.py:
#receiver(pre_social_login)
def handleDuplicateEmail(sender, request, sociallogin, **kwargs):
if sociallogin.account.provider == 'facebook' or sociallogin.account.provider == 'twitter':
email_address = sociallogin.account.extra_data['email'] # get email address from fb or twitter social account.
else:
email_address = sociallogin.account.extra_data['email-address'] # Get email from linkedin social account.
users = User.objects.all().filter(email=email_address) # This line is problematic
if users:
if not (users.profile.provider == sociallogin.account.provider): # Different user is trying to login with already existing user's email address.
response = 'Your social account email address is already registered to some account. Please choose a different one.'
raise ImmediateHttpResponse(render(request, 'index.html', {'type': True, 'response': response})) # redirect to index template with error message.
models.py:
class Profile(models.Model):
user = models.OneToOneField(User, related_name='profile', on_delete=models.CASCADE)
provider = models.CharField(max_length=256, blank=True, null=True) # for storing name of provider used to login with.
Edit:
Since Facebook, Twitter and Linkedin give users a choice to login with their phone number or email address and if they choose phone number then in that cause users won't have an email address associated with them to handle this situation I have updated my code like so:
if sociallogin.account.provider == 'facebook' or sociallogin.account.provider == 'twitter':
try:
email_address = sociallogin.account.extra_data['email']
except:
email_address = None # If social account was created on phone number for facebook & twitter
else:
try:
email_address = sociallogin.account.extra_data['email-address']
except:
email_address = None # If social account was created on phone number or linkedin
if email_address:
users = User.objects.all().filter(email=email_address)
if users.exists():
...
else:
response = 'You have not provided an email address in your social account. Please register as local user or use a different social account.'
raise ImmediateHttpResponse(render(request, 'index.html', {'type': True, 'response': response}))
users = User.objects.all().filter(email=email_address) returns a QuerySet so you can't just call .profile on it. In theory this query could return multiple User objects. But it could also contain 0 objects (which is more likely).
So you need to handle these cases:
if users.exists():
user = users.first() # assuming there will always only be one user
if not user.profile.provider == sociallogin.account.provider:
etc...
or
if users.exists():
for user in users:
if not user.profile.provider == sociallogin.account.provider:
etc...
break

Django all_auth and custom form

I'm using django allauth for social login/signup. Also, I've my own signup form as an alternate login/signup. Following are the fields that I'm fetching from the user in the alternate form.
class Profile(models.Model):
col1 = models.CharField(max_length=50, blank=True, null=True)
col2 = models.CharField(max_length=50, blank=True, null=True)
user = models.OneToOneField(User)
So, when the user signs up, it asks for additional fields as well(col1, col2), apart from username, email and password.
Following is the signup view.
user = User.objects.create_user(username, user_email, user_pass)
Profile.objects.create(user=user, col1=col1, col2=col2)
return
So, whenever the user signs up via the alternate form, the above view is called up.
Now, in contrast, when the user signs up from social account FB, it does not ask for extra info, ie col1/col2. It directly signs up without asking for extra info, neither I want it to ask.
I then create a row in Profile model post signup using signals.
#receiver(user_signed_up)
def create_profile(request, user, sociallogin=None, **kwargs):
if sociallogin:
if sociallogin.account.provider == 'facebook':
data = sociallogin.account.extra_data
col1 = data.get('col1')
col2 = data.get('col2')
Profile.objects.create(user=user, col1=col1, col2=col2)
So, (1) my problem is when creating a user using alternate form, no record is inserted in allauth tables, which i find weird.
(2) Consider, I signed up using alternate form using E1 as email id. Now I signup via allauth(FB) with the same id, it throws an error.
(3) How do I send confirmation mail to the users who signed up in alternate form using all_auth.
I played around with the library a bit and finally found the solution to my question. I'm pasting it over here for other's to review.
Add a signal pre_social_login that'll check for conditions.
class MySocialAccountAdapter(DefaultSocialAccountAdapter):
def pre_social_login(self, request, sociallogin=None, **kwargs):
if sociallogin:
user = User.objects.filter(email=email).first()
# If user already exists in custom local form, then login directly.
# Save/Update his details in social login tables.
if user:
# create or update social login tables to maintain the uniformity in the code.
token = sociallogin.token.token
socialaccount = SocialAccount.objects.filter(user=user).first()
if socialaccount: # If it exists, then update social tables.
# updating account.
socialaccount.extra_data = extra_data
socialaccount.save()
# updating token.
SocialToken.objects.filter(account=socialaccount) \
.update(token=token)
else: # else create.
# saving Social EmailAddress.
EmailAddress.objects.create(email=email, user=user)
# saving social account.
provider = 'facebook'
kwargs = {
'uid': extra_data.get('id'),
'provider': provider,
'extra_data': extra_data,
'user': user
}
socialaccount = SocialAccount.objects.create(**kwargs)
# saving social token.
app = SocialApp.objects.get(provider=provider)
kwargs = {
'token': token,
'account': socialaccount,
'app': app
}
SocialToken.objects.create(**kwargs)
# finally login.
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)
raise ImmediateHttpResponse(redirect(reverse('index')))

One blog for each Django user with the "blog role"

What approach is the best way to make content-types restricted to a user in Django?
Let us say I want all users with the user-role "blogger" to have its own blog.
I have created a weblog app. How do I restrict it so that the user logged in can only post in his "own" blog, and how do I make views that shows only a user's blog?
First your blog entries has to be attached to user, so you know on whos blog display, it, right? models.py:
class BlogEntry(models.Model):
user = models.ForeignKey(User, related_name='blog_entries')
other_field_1 = ...
other_field_2 = ...
Next, skip it in ModelForm, forms.py:
class BlogEntryModelForm(forms.ModelForm):
class Meta:
exclude = ('user',)
Then, when user want to post entry you require he's logged, views.py:
#login_required
def post_blog_entry(request):
....
if request.method == 'POST':
form = BlogEntryModelForm(request.POST)
if form.is_valid():
new_entry = form.save(commit=False)
new_entry.user = request.user
new_entry.save()
When you want display some user blog, views.py:
def view_blog(request, blogger_name):
user = get_object_or_404(User, username=blogger_name)
entries = user.blog_entries.all()
User is django.contrib.auth.models.User
You can add custom role checking to views above to display 404 page or error page if user has no rights to create blog.
Optionally you can replace User from django.contrib.auth with your own User implementation but you'll have to write model, authentication and middleware for it as well...
I didnt try to implement this, but I found another soultion that worked very good. It was easy to implement and did everything i wanted.
Check it out...