django-push-notifications
django-push-notifications copied to clipboard
Disable duplicates of registration_id
Right now if I can add unlimited amount of duplicates and then when I'm using bulk send_message I'm getting duplicated push notifications equal to quantity of dups inside DB. Would be nice to prevent such thing and don't add duplicate value to DB
What value is duplicate? The registration_id?
correct. It's possible to commit multiple duplicates and when do send_message bulk - it sends a lot of dups
But where are the duplicates coming from? You don't create the registration_id yourself, those come from google.
Example for APNS:
POST /api/v1/devices/apns/ HTTP/1.1
Host: domain.com
Content-Type: application/json
Authorization: token 2192967b2fc60623597790783c9590a1964c6e62
Cache-Control: no-cache
{
"name": "iOS 6.1",
"registration_id": "4d2d8feaf9a2d780c6c2d18a83c94483462ebe74aafab1f989711e6292b96c9b"
}
response:
{
"registration_id": [
"This field must be unique."
]
}
example of GCM
POST /api/v1/devices/gcm/ HTTP/1.1
Host: domain.com
Content-Type: application/json
Authorization: token 2192967b2fc60623597790783c9590a1964c6e62
Cache-Control: no-cache
{
"name": "Android 5.0",
"registration_id": "APA91bF2FA873EZ8vv-JifiSKPP8wxBCxOfPhLaHkH2d9mYC-CEY_0I0ZRxRPrGqCdCgMybKUPtGKDqNN8ZgTdtHHp7IGdY5DNqzLUK2ylLpffclz-K4MS80XG16pV-DCuzi4EdRltMp"
}
response:
{
"name": "Android 5.0",
"registration_id": "APA91bF2FA873EZ8vv-JifiSKPP8wxBCxOfPhLaHkH2d9mYC-CEY_0I0ZRxRPrGqCdCgMybKUPtGKDqNN8ZgTdtHHp7IGdY5DNqzLUK2ylLpffclz-K4MS80XG16pV-DCuzi4EdRltMp",
"device_id": "",
"active": true,
"date_created": "2015-09-18T21:58:35.788556Z"
}
Another call with the same ID:
{
"name": "Android 5.0",
"registration_id": "APA91bF2FA873EZ8vv-JifiSKPP8wxBCxOfPhLaHkH2d9mYC-CEY_0I0ZRxRPrGqCdCgMybKUPtGKDqNN8ZgTdtHHp7IGdY5DNqzLUK2ylLpffclz-K4MS80XG16pV-DCuzi4EdRltMp",
"device_id": "",
"active": true,
"date_created": "2015-09-18T21:59:16.759302Z"
}
so I can submit tons of duplicates for GCM while I can't do the same for APNS using django-push-notifications
I propose a consisten behavior between 2 endpoints.
My question is, where are these reg ids coming from? It sounds like you are not handling the saving of the registration_id id correctly in your application.
class GCMDevice(Device):
registration_id = models.TextField(verbose_name=_("Registration ID"))
class APNSDevice(Device):
registration_id = models.CharField(verbose_name=_("Registration ID"), max_length=64, unique=True)
so what I see needed is unique=True to GCMDevice model definition
reg ids are coming from android app. I don't quite understand the question.
But if you are getting the same reg_id repeatedly, that means that you are not persisting the registration id properly on the device. Once you have a valid id, you should save it on the phone/tablet so that the next time you authenticate against the gcm server, you don't try and create a new device with your django app.
I've hit the same issue @saritasa has. Is there a good reason there is no unique constraint on the registration id? This not existing causes issues, at least with the rest_framework classes.
For example, if you plug in the GCMDeviceAuthorizedViewSet you can immediately create multiple entries with the same registration id. In turn, this being allowed breaks other endpoints in the viewset, for example viewing an individual GCM device (ie /device/gcm/<registration_id>). This endpoint will throw a "got multiple results" error.
I'm running with the changes in https://github.com/lukeburden/django-push-notifications/commit/c6e04bb2e1466aa064dd4d123ed24a3fe3107e3e for now. The included migration won't be friendly for existing installations with duplicates though. If you think this is the correct approach for your project I'll throw up a pull request. If you have any concrete issues with using a unique constraint for GCMDevice.registration_id, I'd be interest to know of them. :)
Thanks guys!
Like I said, if you are registering multiple devices at once with the same registration id, that sounds like user error, or an implementation error on your part. See issue #197 for a discussion on why registration_id should not be unique.
You don't usually have much control over how the client consumes an API. If you expose endpoints that let clients do something that can cause an internal server error (this is the current state of this library) it's cold comfort to point at the client and say, "You shouldn't do that.". Your poor ops person has still been woken up in the middle of the night by your monitoring system!
Thanks for referencing that other discussion, there are definitely a few complicating factors here.
Agreed with @lukeburden. APNS endpoint is working differently compared to GCM Endpoint and simply stating that the problem is device side doesn't mean GCM endpoint is correct. I had to implement alternative endpoint
POST /devices
{
"name": "iOS 6.1",
"type": "apns",
"registration_id": "4d2d8feaf9a2d780c6c2d18a83c94483462ebe74aafab1f989711e6292b96c9b"
}
and internally do validation and proper error handling for duplicates and routing to what table to persist depending on "type" value.
We should be able to apply the unique validator in the GCM serializer. It doesn't solve the underlying DB issue but it would address the client problem.
Hi all. What about the situation if I have more than one account in my application. I have single device. So if I switch accounts on the same device then client send to server the same registration_id! And I have more than one user with the same registration_id. But registration_id must be unique in django-push-notifications. I would like to know - why???
That is another good reason against unique reg ids. The good thing is that the model does not enforce the unique constraint, it is only on the django rest framework serializer. If you do not agree with the implementation, it is not hard to integrate drf yourself. I had been using it before it's inclusion in this library so these changes don't effect my app.
I think that best solution would be uniquetogether of reg_id and user_id. That way you will have protection against multiple regIds and option to have multiple accounts on same device
FWIW, I've ended up running with a unique_together of registration_id and user_id in my fork. It provides a sensible amount of restriction (a user shouldn't be able to register the same token twice) whilst coping more gracefully with the fact that you may have different users logging in using an installation of an app, hence with the same registration_id.
This also then plays nicely with the rest framework API components in this project, which are automatically contained to records relating to the authenticated user.
@lukeburden i tried your branch but keep getting tab indent error
@baneizalfe some mixed spacing may have crept in. Please create an issue on my fork, not here.
@lukeburden please enable issues on you fork
@baneizalfe done, but beware, my fork is for my personal needs at the moment. It has changes that may not play nicely with backends other than PostgreSQL, and especially not MySQL due to constraints on use of unique indexing and TextField. I recommend you use this project if you can.
I believe there are a number of valid approaches to handling the uniqueness of tokens and it will depend on the application designer to determine what is appropriate. I agree that it would be acceptable to use the registration_id and the user_id to determine uniqueness in most cases.
I do not use the user_id. I set the name field to something suitable unique and use that. Perhaps this could just be enforced at the application level? Either (user_id, registration_id) or (name, registration_id) would work well.
Does anyone know the conclusion of this issue? I'm getting issues with multiple reg_ids in GCM devices
Same issue here also. Quite annoying. Any idea?