I am working with a site which is already connected to single sign on system. Now I want to add terms of agreement page. Here is the flow that I am thinking of:
If I have a record of the user who is logging in that means the user has already seen it so we no longer need to show the agreement page. But if the record doesn't exist in the table I want to redirect to a view that has terms of agreement and user can go further on the sign in process only upon acceptance. If fail to accept we show the non-signed on version of the site.
Since its a single sign on system I have created a table on my end to just keep track of the users who login-to the site. And this is the table I should look up for record.
Here is how I create the record when they sign in:
This is in the my middleware class
shib_umnPersonType = shib_meta.get('uPersonType','')
shib_uRole = shib_umnPersonType.strip().split(';')[0]
#raise(shib_meta)
try:
shib_user = ShibUser.objects.get(shib_username=username)
user = shib_user.auth_user
user.backend = "django.contrib.auth.backends.RemoteUserBackend"
except ObjectDoesNotExist:
user = auth.authenticate(remote_user=username)
user.shibuser_set.create(shib_username=username, shib_user_role=shib_uRole)
What I am thinking at this point is I should interrupt the request in the except: But I am not really sure if thats that the way it should be done. I am also not a experience django developer.
If thats the way to do it then I guess I should be calling a view with a form from that location then check the response ...?
You can do it with view decorator.
If you detect in decorator, that user has not agreed to recent Terms, then redirect it to Terms page with extra parameter passed on to that view. Pick that parameter up in the Terms view and based on that paramter redirect user to previous view if user accepted the Terms.
Related
I have the django model called "create-chat" and there I write names of people I want to see in a group chat.
So. I created the model, but I don't know how to make a condition whether user is in django_db or no, if so then I want to show them the button "join chat"
And after clicking the button he will be transferred to the url sitename.com/lobby/1
Now I have the view that shows the page /lobby/any_number
First of all I'd to block these pages from users and only if the user is in django_db
He is able to visit the page Lobby/1
ONLY THE lobby/1 not lobby/2
I don't ask you to do it, I just want you to explain me how to do it, or maybe advice me some articles about my problem.
https://i.stack.imgur.com/FQw4Y.jpg
..1). How to block all users for visiting this url sitename.com/1234 <- here goes any number u d liked. ( 4 characters )
So now I blocked all the users for visiting this page, and how now make it visible for a certain users/user?
I am assuming you are storing the information in User object.
usr = User.objects.get(username = whateveristheusername)
if usr is not None:
#User Exist. Click to join chat
else:
#Create User or any other viable functionality
I am designing a new AppEngine/Python HRD application. In this application, I need to ensure that each user that registers cannot use a name that has already been assigned to another user, and that if two users attempt to register with the same username at the exact same moment, that only one of them will be given the username.
If I were to put all usernames in a single entity group and use transactions to ensure uniqueness, then the writing of the username/object in a transaction could potentially slow down all registration processes. So this approach doesn't seem like a good idea.
Another option would be to use the username as the key, which has the disadvantage of possibly making it difficult for the user to later change their username.
What is the best/standard approach to achieve this in AppEngine?
Ok.
You don't need to stick all the usernames in a big entity group to guarantee consistency.
Make the username the Key of the datastore entity governing the login.
Then inside a transaction.
Try a get using the username as a key (this is a consistent operation)
if you find it then obviously it's not available
If not found then create the new login entity.
As an aside if you used email addresses then it would more than likely mean no clashes ever. and I am not sure why visible nick names need to be unique, but then you probably have a good reason.
Each actual user object can have a system generated unique id, (this is a separate entity to the login entity).
If you are really paranoid, then look at using memcache CAS operations to effectively act as a lock on the username key and prevent simultaneous operations, though I don't think it would be necessary.
Entities might look like
class Login(ndb.Model):
# other stuff neede for authentication etc..
user = ndb.KeyProperty(User)
#ndb.transactional(xg=True)
#classmethod
def create_login(cls,username):
# maybe pass in extra user details
key = ndb.Key(cls, keyname)
login = key.get()
if login:
raise DuplicateUsernameError(username)
login = Login(key_name=username)
user = User.create_user(login=login.key)
login.user = user.key
login.put()
return (login,user)
class User(ndb.Model):
login = ndb.KeyProperty(Login) # this property is only for convenience.
nickname = ndb.StringProperty()
# etc
#classmethod
def create_user(cls,login_key):
# yes you would pass in more user stuff.
user = cls(login=login_key)
user.put()
# the unique user key is system generated.
return user
This means only a single get() is required to fetch a login, and second to get the rest of the user details but is much cheaper/faster than queries. It also means that the login name/code could be changed over time without disrupting the actual user entity if you really wanted such functionality. Or possibly support multiple login methods for a single user - ie facebook and twitter. It also means a login entity can be removed and login re-used by other people over time, and the user entity can stay if system integrity/history is required.
App Engine allows up to 1 write per second within the same entity group. To surpass that barrier you have to have 60 x 60 x 24 = 86.4k registrations on the same day, which I think you can live with.
If you still think you need any faster process you could use sharding (more typically known for counters - https://developers.google.com/appengine/articles/sharding_counters), which is basically having different tables for users (or usernames) so that you can read them all to check for uniqueness (App Engine is good at doing many reads per second) and have as much better write pace as tables for usernames you add.
More of sharding on writes here - https://developers.google.com/appengine/articles/scaling/contention
Hope it helps.
I have a server which feeds several applications.
Please imagine that I'm a user registered in 2 or more of those applications and I use one different login info when accessing each one.
Now, as that user, I use the same browser with different tabs to access those applications...
Logging the first time (for the 1rst application) everything goes as intended, but when I access the 2nd application (as the second user), that request will access the same request.session object. When I invoke the login (from the auth framework) the current user will be compared with the user in the actual request.session (request.session[SESSION_KEY] != user.id) and request.session.flush() will be called.
This means that I will loose all of the request.session content for the user that accessed the 1st application, and that same user request.session will be "marked" to be the second user request.session from that point.
What I wanted, in this situation, was to have a function/method that permits to create a new request.session for the second user, leaving the original as it is.
Edited after the first answer:
First of all, thank you for the answer.
I was trying not to detail too much in order to avoid too oriented answers, but now I think I should do it:
Ok, I've called "it" applications before, but in truth, my project serves requests in order to offer the same final "product" (a game, for instance).
(I have several django applications inside my project. Each one with specific orientations and backend's depending of business considerations applied.)
It would be more detailed if I told that I have different entry points URL's, use the correct business backend in order to process the request and retrieve a game.
My main URL is the same (namespace) and my project has only one settings file.
There may be several answers to your question depending on whether you are ready to change the "use case" or not:
a) You can't change the use case: it's not possible because one Django session is bound to a browser session be it several browser windows instance or tabs.
b) You can change the use case: The user can still achieve this using several browsers (or profiles (or private browsing mode in chrome/chromium)) without any modification to your code.
c) You can implement an "user"-switch feature in your website that allow user to have several active profile in the same session in different windows, it's similar in purpose to github organization-switch feature or facebook page/organization-switch but you can have several user's profiles in several tabs which is not the case on github or facebook.
To achieve c) you need to have a "SubProfile" model instances attached to your "User" model, and activate the right SubProfile on each incoming request based on query string parameters and persist subprofile information across requests.
1) I guess you already have something like that Subprofile a model with a foreign key to django.contrib.auth.models.User, you may also have a view that allow an user to change its subprofile. In order to make subprofile-switch work, it needs to persist the information in the current tab session which subprofile it is using, for that it needs to add a parameter in the query string because it's the only place bound the tab and not the user-session. For instance "subprofile=123". You need to properly validate the subprofile with a form et al., the view looks like this:
def select_subprofile(request):
if request.method == 'POST':
form = SubProfileSelectForm(request)
if form.is_valid():
subprofile = form.cleaned_data['subprofile']
url = '%s?subprofile' % (reverse('homepage'), subprofile)
return redirect(url) # the redirect is something like '/homepage?subprofile=123'
else:
form = SubProfileSelectForm()
return render(request, 'myapp/subprofile_select.html', {'form':form})
This view can be the first page of each game.
2) After that, you need to retrieve the subprofile of the user for the current tab.
For this matter we will use the query string in a middleware (look for howtos on SO and example middlewares bundled with Django if you don't know what it is) can be used to attach current SubProfile instance to request.user. The middleware will for each incoming request attach the SubProfile instance corresponding to the current subprofile information found in query string to current user object, the middleware looks like this:
class SubProfileMiddleware(object):
def process_request(self, request):
subprofile = request.GET.get('subprofile', None)
if subprofile:
# it's important to check for user here or malicious users will be
# able to use Subprofiles of other users
subprofile = Subprofile.objects.filter(user=request.user, id=subprofile)
# This can also be written
# subprofile = request.user.subprofile_set.filter(id=subprofile)
if not subprofile:
# this is a malicious user
raise Http403
else:
request.user.subprofile = subprofile
else:
# set default subprofile
request.user.subprofile = self.user.default_subprofile
This way you have access in every view of your app to a SubProfile instance on subprofile attribute of request.user. If there is a valid query string subprofile=123 the user will have these subprofile active, if not it's the default subprofile.
Say your application is an application with Organization models each of which instances have walls, on which user's can post message using a subprofile, the function to post a message on a wall has the following signature post_on_organization_wall(subprofile, message, organization), the view that use this function will look like this:
def organization_wall_post(request, organization):
organization = Organization.objects.get_object_or_404(organization)
if request.method == 'POST':
form = MessageForm(request.POST)
if form.is_valid():
post_on_organization_wall(request.user.subprofile, message, organisation)
else:
form = MessageForm()
return render(request, 'organisation/wall_post.html', {'form': form})
3) Now you need to persist subprofile information across requests. Simplest way to do that is replace everycall to {% url %} to your own url template tag which checks for the request query string presence of subprofile key and add it to the requested url. You can reuse the code of Django's url template tag.
If I understand your problem correctly, the issue is that you're sharing sessions between applications even though the users are different. You should be able to solve this by setting either SESSION_COOKIE_DOMAIN, SESSION_COOKIE_PATH, or SESSION_COOKIE_NAME in settings.py to ensure that your applications don't clobber each others sessions.
I'm making a SAAS and I've been asking a slew of questions on here related to the Auth system built in. I'm having trouble understanding the "why" and "how". Primarily I don't understand how it fits in with my SAAS.
I (do) know the following:
You can do this: http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
There are many reasons to use the built in auth system (like security) instead of rolling your own
I (don't) know the following:
class MyUserProfile(models.Model):
"""
Administrator for an Account. Can edit tickets and other stuff.
"""
user = AutoOneToOneField(User, primary_key=True)
account = models.ForeignKey(Account)
dogs_name = models.CharField(max_length=255)
In the previous example, account is just what you'd expect; an entity that's paying to use my software. user is my main concern. Somebody goes to a page and creates a UserProfile with a username and password, etc. When they do this, where does the related User get created? Do I need to create it in my view manually based on the request.POST['username'], etc, and then do
myuserprof = MyUserProfile.create(user=foo_user_just_created, account=foo_account, dogs_name='Spot')
I don't know why but for some reason I feel like I'm missing something. This idea of asking somebody to sign up for an account, and then create a MyUserProfile with a form that asks for the password, username, email, et al, and then in my view creating 2 different objects (MyUserProfile and User) with different parts of the form data. I mean I shouldn't have a User form right? Like I said, I feel like I'm either skipping a step or I'm in the wrong paradigm. I'm not new to Django, but for some reason I have trouble with things that I didn't build (I think it might be a mental problem for real at this point).
Maybe there is a good example of this sort of thing being done on some open source project.
Update: Oops, forgot to mention that in the code above I tried to use AutoOneToOneField from django-annoying, but I have no idea where all the User's attributes get set or how to decide which User object to attach to it. This stuff is driving me crazy.
Also, do I need to use the sites app to do this stuff, and finally does a "super user" have all permissions to everything (I don't want people from Account "Acme" to access account "Microshaft" objects)? Or do they just have all permissions to all views?
Somebody goes to a page and creates a UserProfile with a username and password, etc.
UserProfile doesn't have an username or password field. So it should be somebody goes to a page and create an User. Then, it creates an UserProfile associated to that newly created User.
The question is, how and when do you want this UserProfile instance to be created?
Automatically, whenever a new User is created : use signals, as described in the docs
Automatically, whenever the profile is accessed from an user instance : use AutoOneToOneField, and access the profile using user.userprofile instead of user.get_profile()
Manually. But don't forget an user might have no UserProfile associated yet, so user.get_profile() might raise a DoesNotExist exception.
When they do this, where does the related User get created?
It doesn't. You have to create it explicitely.
This idea of asking somebody to sign up for an account, and then create a MyUserProfile with a form that asks for the password, username, email, et al, and then in my view creating 2 different objects (MyUserProfile and User) with different parts of the form data. I mean I shouldn't have a User form right?
Why not? You want here to create an User and his associated profile in one go, right? You could eventually use directly the POST data, or use a Form to access to the fields, or even better, use 2 ModelForm (one for User, one for UserProfile) that you will process in the same view (maybe this question can help?)
Maybe there is a good example of this sort of thing being done on some open source project.
I suggest you check out django-registration and django-profiles.
Note
You have another way of adding information to an User object, by extending the model itsel. It will allow you to put your extra fields directly in the user model and might be easier for you to understand and use.
I won't dive into details here, have a look at that tutorial for more informations.
Other questions
I tried to use AutoOneToOneField from django-annoying, but I have no idea where all the User's attributes get set or how to decide which User object to attach to it. This stuff is driving me crazy
See above on how to use it. If you feel uncomfortable with it, the best is to follow the documentation, which recommend using a ForeignKey with unique=True in user profiles.
Also, do I need to use the sites app to do this stuff
From the site framework docs : Use it if your single Django installation powers more than one site and you need to differentiate between those sites in some way.
and finally does a "super user" have all permissions to everything (I don't want people from Account "Acme" to access account "Microshaft" objects)?
Again, from the docs, Designates that this user has all permissions without explicitly assigning them. That means that everywhere Django is using the built-in permission system (e.g. default administration pages), a super-user will be authorized.
In views you're writing yourself, or if you tweak some ModelAdmin, it's up to you to decide how you are going to check permissions.
This question already has answers here:
How can I detect multiple logins into a Django web application from different locations?
(4 answers)
Closed 8 years ago.
is it possible to allow only one concurrent login per user in django application? if yes, how do you approach?
I needed this in my applications so I created a django package which is now on pypi (pip install django-preventconcurrentlogins).
The package is based on peterdemin's snippet: https://gist.github.com/peterdemin/5829440
Hope this helps someone in the future.
This question is mostly answered here (stackoverflow.com).
You need to create some model that save session_key for each user
And create middleware that checks session key in that model for each user - if it does not equal to request.session_key - than remove that session(=logout user, allowing only current to stay)
#models.py
class Visitor(model.model):
user = models.OneToOneField(User)
session_key = models.CharField(null=True, blank=True)
#and you need to setup signal catching from User model - so for each User Visitor is created
#middleware.py
class OnlyOneUserMiddleware(object):
def process_request(self, request):
cur_session_key = request.user.visitor.session_key
if cur_session_key and cur_session_key != request.session.session_key:
Session.objects.get(session_key=cur_session_key).delete()
#the following can be optimized(do not save each time if value not changed)
request.user.visitor.session_key = request.session.session_key
request.user.visitor.save()
I'm going to assume that you mean logged in at once, and not one "login" at the same time.
I've never written a Django application before. But one method I've used in other languages, is to store the session ID of the logged in user in their user row in the database.
For example, if you have a users table in your database, add a field "session_id" and then when the user logs in, set that to their current session_id. On every page load check to see if their current session matches the session_id in the users table. Remember whenever you regenerate their session_id in your application, you'll need to update the database so they don't get logged out.
Some people when a user logs in, just store all the users details into a session and never re-call the database on a new page load. So for some this "extra" SQL query might seem wrong. For me, I always do a new query on each page load to re-authenticate the user and make sure their account wasn't removed/suspended and to make sure their username/password combo is still the same. (What if someone from another location changed the password, or an administrator?)