What I'm trying to do is whenever the user requests an API key--regardless of whether the user already generated one or not--the system will generate an entirely new key.
I know that whenever calling ApiKey.objects.create() will generate an API key for the user that doesn't have one generated. However, if a user does have one, then trying to call the .create() method throws an error.
In this case, I figured that it would be best to write my own key generator. However, I am now hoping that maybe someone here might know of a helper function that will allow me to generate a random API key, and then let me save it to the database manually myself.
Would anyone might know of any such a helper function?
Or, you can just use tastypie's built-in command:
python manage.py backfill_api_keys
I figured it out.
First, you make an attempt to get the the user's API key. If it exists, then there will be no error thrown. To regenerate, set the value of the retrieved user's key to None, and then save the key.
If there was an error thrown, then simply create a new key.
try:
api_key = ApiKey.objects.get(user=someuser)
api_key.key = None
api_key.save()
except ApiKey.DoesNotExist:
api_key = ApiKey.objects.create(user=someuser)
Yes, the code for generating the key is defined as an instance method ApiKey.generate_key() which you can use directly.
Here's a simpler version that takes out some of the guesswork of whether the user already exists or not and uses ApiKey.generate_key() directly, rather than implicitly through ApiKey.save(), which I believe makes it a bit more clearer of what's trying to be accomplished:
api_key = ApiKey.objects.get_or_create(user=someuser)
api_key.key = api_key.generate_key()
api_key.save()
UPDATE:
Thus, the shortest version is:
return ApiKey.objects.get_or_create(user=someuser)[0].key
This will generate a new key or return an existing one.
Based on Filip Dupanović's answer the working code for me was something like this:
user = get_user_model().objects.get(email="some#email.com")
api_key = ApiKey.objects.get_or_create(user=user)
api_key[0].key = api_key[0].generate_key()
api_key[0].save()
Its way too easy to use inbuilt functions, always. To generate Api keys in Tastypie use "create_api_key" of TastypiesApikeyAuthentication`.
you have to just import "create_api_key" from tastypie.models
and then call it by django-signal or as per u require.
i.e.
signals.post_save.connect(create_api_key, sender=User)
Explained in detailed and easier at :
http://django-tastypie.readthedocs.org/en/latest/authentication.html#apikeyauthentication
Related
Let's say we have a model like this:
class UserConfig(ndb.Model):
name = ndb.StringProperty()
email_subscriber = ndb.BooleanProperty(default=True)
Let's assume email_subscriber was set to default True by mistake and we want to fix that mistake and use default=False instead. I tried changing the value to default=False and that works fine for users created after that code is deployed, but that doesn't fix the problem for existing users.
Is there a way (e.g. some internal property which isn't documented in Datastore documentation), which would provide info whether given prop value was set explicitly by user or using the provided default.
I can write an upgrade which would set email_subscriber=False for all users, but I'm afraid some users might have intentionally checked this property in the app and wouldn't like to break their experience.
tl;dr: How can I determine if value in ndb object was set using the default for that property or was provided explicitly.
There is no way to know this. Once a value is set in the database there is no way to know which part of your code (ndb runs in your code from the database perspective) set the value.
What are setMethod(parameter) and populateModel(string) in the given code of the ColdBox framework?
function addUser(event,rc,prc)
{
LOCAL.userBean = populateModel("userBean").init(5,prc.siteid,event.getValue('userid',0));
rc.user = securityService.getUser(LOCAL.userBean);
LOCAL.userBean.setMethod(3);
rc.genderList=globalsService.getGlobals(LOCAL.userBean);
LOCAL.userBean.setMethod(7);
rc.stateList=globalsService.getGlobals(LOCAL.userBean);
event.setLayout("Window");
event.setView("purchase/addUser");
}
SetMethod() would be something specific to the UserBean itself. That isn't something in ColdBox.
PopulateModel although can do a lot more, is usually a way to populate a model by passing a struct. The populate model will loop through the keys in the struct, and if there is a matching property in the model, it will set it.
So model.setUsername( rc.username ) for example, if there is a key called username.
PopulateModel assumes you're sending the rc scope in, but its usually best to validate, and add restrictions so someone can't pass a password via url and set that to a user for example.
Shawn's links are good ones, hope that all helps.
I'm currently building a Google Cloud Endpoints backend with the endpoints-proto-datastore library, and am running into trouble requiring an apikey when you request a user.
Once a user logs in, they receive an APIkey which they send back for successive puts (which works) but how do I require the username/email and apikey on a GET ? Currently if a user does a get like so:
#User.method(request_fields=('id', 'apiToken',), path='users', http_method='GET', name='user.get')
def user_get(self, query):
return query
The user is pulled from the datastore because the ID is correct, and it completely ignores the apiToken. How do I require both fields?
(on a different note, how do I send back the user's ID on a request?)
If you are implementing your own API key scheme, as your code suggests, then you need to manually check if the API key is valid or not yourself.
Your example looks like the one from the 'basic' example, and you've added parameters as per the 'simple_get' example. For some background, the docs in the 'simple_get' example mention that 'id' is one of five special helper properties automatically defined by EndpointsModel for common operations like retrieving by id. This is why your code works automatically without you doing anything 'special' with the 'id' parameter. The example still checks though that the entity exists if you try to get it:
if not my_model.from_datastore:
raise endpoints.NotFoundException('MyModel not found.')
Since there's no special helper property for your 'apiKey' field, you need to add your own code in the method to check if the key is valid and return a 401 or suitable error if it's not. Another option is to also utilize some of Google's built-in authentication as per the 'basic_with_auth' example.
Finally, since endpoints-proto-datastore is just syntactic sugar for the main endpoints library, you'll want to read the full documentation on that for more information on things like how to return values from your endpoints methods.
The easiest way I found to do this is:
#User.method(request_fields=('id', 'apiToken',), path='users', http_method='GET', name='user.get')
def user_get(self, user_model):
user = ndb.Key('User', int(user_model.id)).get()
if user.apiToken != user_model.apiToken:
raise endpoints.UnauthorizedException('You are not authorized to view this data')
return user.clean()
The user_model will have the userId and the apiToken stored in it, so I pull the "real" data from ndb with the key and check if the user_model has the correct token and return the model if it is correct, if not, I refuse
I'm trying to use the Yummly API. I've noticed that some of their developers have answered other questions here, so I'm hoping to catch their eye. I used the documentation at the yummly developer site https://developer.yummly.com/documentation#IDs.
Specifically here is my get request:
<http://api.yummly.com/v1/api/recipe/Avocado-cream-pasta-sauce-recipe-306039>
Which returns this:
Please include X-Yummly-App-ID and X-Yummly-App-Key
Seems like this is a sensible thing, except that I don't see anywhere in the documentation for the single recipe call where I'm supposed to insert that info. Any one out there know how to properly format this?
or include them as URL parameters:
_app_id=app-id&_app_key=app-key
https://developer.yummly.com/documentation#IDs
Try this:
http://api.yummly.com/v1/api/recipe/Avocado-cream-pasta-sauce-recipe-306039?_app_id=ID&_app_key=KEY
You need to take the URL you mentioned in the question and add your authentication parameters to it. So it becomes:
http://api.yummly.com/v1/api/recipe/Avocado-cream-pasta-sauce-recipe-306039?_app_id=ID&_app_key=KEY
Instead of ID and KEY insert the application id and key from your account on developer.yummly.com
I'm using django-nonrel (http://www.allbuttonspressed.com/projects/djangoappengine) on Google App Engine. I have my models etc. setup and everything works great. I had one question though. I want to be able to access an entity's key. Given a model named 'Review', I do Review.objects.get(pk = 1).key() which throws an error (AttributeError).
Is there any way I can get the given entity's key so that I can use it instead of being forced to use the pk/id? I want to use the key as a unique identifier for unique & secret URLS (if someone has a better suggestion to achieve this, I'm all ears).
You can get id by calling object.key().id() which returns a unique key inside python .In templates you can simply call object.key.id . Then you can use get_by_id to get the object
You can get your primary key on django-nonrel from the meta data:
review._meta.pk
or for key name:
key=getattr(review,review._meta.pk.column)
Apparently the 'id' field changes depending whether your on the dev or production server. So this works!
reference:
http://www.b-list.org/weblog/2007/nov/04/working-models/