0

I'm trying to use an app engine User object's user_id (returned by the User.user_id() method) as a key_name in my own User class. The problem is that it keeps telling me that it's an invalid key_name. I've tried sha2'ing it, and using the digest() as well as the hexdigest() method to reduce the number of possible characters, but still no good result. Is this because the value is too long, or because key names can't have certain characters? And also, how can I modify a user_id in such a way that it stays unique, but is also usable as a key_name for an entity? Extra bonus if it uses a hash so that thje user_id can't be guessed.

Here is the code where the error occured:

def get_current_user():
    return User.get(db.Key(hashlib.sha1(users.get_current_user().user_id()).hexdigest()))

I'm now doing some more testing, concidering suggestions from the comments and answer.

bigblind
  • 12,539
  • 14
  • 68
  • 123
  • Key_name in your user class is the PK of your User class? – Vishal Biyani Nov 30 '11 at 00:24
  • I believe valid key names include any Unicode string up to 500 characters. `user_id()` or a hash should certainly be completely valid. I suspect there's something else awry in your code. Are you sure you're setting the key name, and not the key itself? – Drew Sears Nov 30 '11 at 03:26
  • at this point, I'm not even setting the key. I'm trying to get a user from a database that does not exist. I'm only implementing the get_current_user method for my own user module. I'll add the code for it to the question. – bigblind Nov 30 '11 at 14:39
  • 1
    Note that if you'd included the stacktrace of the error, rather than paraphrasing it, it would've been immediately apparent what the issue was. – Nick Johnson Dec 09 '11 at 18:45

1 Answers1

1

I'm not sure why it isn't working for you, the following has no issues when I run it in the dev console.

from google.appengine.ext import db
from google.appengine.api import users

user = users.get_current_user()
name = user.user_id()
print db.Key.from_path ('User', name)

However if you are hashing it (which it sounds like you may be), be aware that you may get a collision. I would avoid against using a hash and would consider some other means of anonymization if you are giving the key to clients. Such as another model whose key you can give away, that has the user's key stored in it. Another method would be to encrypt the id (using the same key for all users) rather than hash it.

If you are doing something that generates binary data (encryption / hash digest) app engine (the sdk at-least) has issues, so you need to encode it first, and use that as the key_name.

name = user.user_id()

hashed_name = hashlib.sha1(name).digest()
encoded_name = base64.b64encode (name)
db.Key.from_path ('User', encoded_name)
Amerdrix
  • 143
  • 6
  • It's perfectly fine to use hashes for IDs, as long as the hashed text is guaranteed unique and you're not doing concatenations. For all practical purposes sha2 collisions don't happen. See [here](http://stackoverflow.com/questions/4014090/is-it-safe-to-ignore-the-possibility-of-sha-collisions-in-practice) for example. – Julian Go Nov 30 '11 at 11:22
  • thx. the example you are giving works. I was stupidly using the Key constructor instead of Key.from_path. – bigblind Nov 30 '11 at 14:50