I have a question regarding the user api for GAE Python.
For a new application for an already existing user base I would like to get two informations for a user. First is the name and the second would be a flag (0,1 or 2 in example).
It's an internal application and only people from the same domain can login. How can I access their information beyond whats in the users reference? And how could I set that additional flag?
Thanks alot.
from the User class you may get only the information it provides, everything else you have to solicit directly from your users using some kind of "Accounts" page, where they can input their name and/or change the value of a flag.
This information can be saved in the database as a separate entity UserData, preferably alond with user email or user_id received from the User class. Something along the lines of:
class UserData(db.Model) :
user = db.UserProperty()
name = db.StringProperty()
flag = db.IntegerProperty()
Related
I'm using Eve framework and I'm trying to use User-Restricted resource access as described in:
http://python-eve.org/authentication.html#user-restricted-resource-access
I'm doing something like:
class CustomAuth(TokenAuth):
def check_auth(self, token, allowed_roles, resource, method):
# Get user as an instance of UserResource.
if user and hasattr(user, 'id'):
self.set_request_auth_value(user['id'])
request.authenticated_user = user
...
So, there are a few question from my side:
Is it enough for using User-Restricted Resource Access?
How this field adds into user created objects?
Is this additional field called id in my user created objects? Is it possible to rename it?
As I understand it should be named same as it's called in User resource. Is it true?
Does this field (property) applies for newly created objects only? Is it possible to fetch previously created objects by current user following this way?
Well, I want to know an answers for my questions + clarify how it may be used.
Is it an expected way to extract it somehow in my hooks?
user_id = current_app.auth.get_request_auth_value()
current_app.data.driver.session.query(resource).find({'id': user_id})
Is this block of code from hook expected?
How it behaves if my requested resource has its own id field?
P.S. I was reading a post:
https://stackoverflow.com/a/35654252/7335432
The user-restricted access feature prevents users from accessing records they didn't create. The set_request_auth_value() method does:
1) Upon making a POST request to create a record, it automatically adds a field specified as AUTH_FIELD (or auth_field if you only want to do it to a specific resource). So for example, if you declare in settings.py
AUTH_FIELD = "my_auth_field"
and then add
set_request_auth_value(user['id'])
to your authentication method, that means that your app creates a field "my_auth_field" that has its value set to whatever user["id"] is. So if you were to go into Mongo Compass or some other DBMS and manually inspect your records, you'd see a "my_auth_field" field in there.
2) On GET requests when you access those records, Eve checks the "my_auth_field" value against whatever user["id"] is, and only displays the records where "my_auth_field" is equal to user["id"]. Since this field is added automatically when you create a record using Eve, it effectively filters out everything that specific user didn't create.
So yes, it only applies to newly created objects. I'm not sure exactly what you mean by "is it enough", but it doesn't look like 'user' is declared anywhere in your authentication class. You might wanna check out this tutorial they do incorporating user restricted access into token authentication.
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'm new to Django and python. I've done login forms but I need to know. How can I connect the contents of the page with the user.
For example: It's a Q&A site. When you logged in, It shows profile page with the questions that user asked before. How the datas are linked to the specific user ID in the model?
Can it be done using the User object? If so, could you give me some simple example with the script?
Thank you.
Anything that "belongs" to a user, should either have a ForeignKey or ManyToManyField (depending on whether the object is owned by one user or many) to User on it. Then you can either filter the model based on the User:
SomeModel.objects.filter(user=some_user)
# where `user` is the name of your foreign key field
Or you can access the model through the user via reverse relations, for example:
class SomeModel(models.Model):
...
user = models.ForeignKey(User)
# Later ...
some_user.somemodel_set.all()
The second method is more typical since you generally have the user already from the request, so in your view, you'd just do:
somemodels = request.user.somemodel_set.all()
To get all the SomeModels that belong to the currently logged-in user.
I'm trying to selectively process a field in my Django/Python application based on whether a user is logged in or not. Basically, I have a model similar to the following:
class Resource(models.Model):
uploaded = models.DateTimeField()
name = models.CharField(max_length=200)
description = models.CharField(max_length=500, blank=True)
file = models.CharField(max_length=200)
What I want to do is for the file attribute to be set to one value if the user happens to be logged in (and has access to this resource based on a test against some permissions backend), and another value if the user is not logged in. So, when any client code tries to access Resource.file, it will get something like the following if the user is not logged in 'http://mysite.com/dummy_resource_for_people_without_access'. However, if the user is logged in and passes some tests for permissions, then the value of resource.file will actually be the true url of that resource (including any security keys etc. to access that resource).
From what I've read, it seems that you can only take account of the currently logged in user by passing that through the request context from a view function to the model. However, in the above use case I am trying to control the access more closely in the model without needing the client code to call a special function.
Your best bet is to create a function used to access the file attribute, and check there. In general, it would possible to turn the attribute into a descriptor which does it implicitly, but Django's metaclass magic would impede that.
In general however, Django is designed to handle authentication at the view-level (and does it very cleanly). If you need database layer authentication, consider a different setup, such as CouchDB.
Just in case anyone's interested, I solved the above issue by actually creating a custom model field in django that could then have a method that takes a user to generate a URI. So, in the database, I store a key to the resource as above in the file column. However, now the file column is some custom field:
class CustomFileField(models.CharField):
def to_python(self, value):
...
return CustomFileResource(value)
class CustomFileResource:
def __init__(self, *args, **kwargs):
....
def uri(usr):
#this method then gets the uri selectively based on the user .
The pattern above is nice because I can wrap the db field and then create a specific method for getting the uri based on who is trying to access it.
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?)