Add permissions to API keys

This commit is contained in:
2012-06-08 20:32:06 +01:00
parent 799cd0231b
commit 5180712cef
6 changed files with 146 additions and 14 deletions

View File

@@ -5,6 +5,7 @@ class AuthAPIKeyAdmin(admin.ModelAdmin):
list_display = ('key', 'name', 'url', 'active')
search_fields = ['name']
list_filter = ('active',)
filter_horizontal = ('permissions',)
class AuthAPILogAdmin(admin.ModelAdmin):

View File

@@ -4,6 +4,7 @@ from datetime import datetime
from django.http import HttpResponseForbidden
from django.contrib.auth.models import AnonymousUser
from django.utils.timezone import now
from django.core.urlresolvers import resolve
from api.models import AuthAPIKey, AuthAPILog
@@ -15,7 +16,7 @@ class APIKeyAuthentication(object):
try:
keyobj = AuthAPIKey.objects.get(key=request.GET.get('apikey', None))
except AuthAPIKey.DoesNotExist:
pass
return False
else:
if keyobj and keyobj.active:
params = request.GET.copy()
@@ -24,6 +25,8 @@ class APIKeyAuthentication(object):
url = "%s?%s" % (request.path, urlencode(params))
else:
url = request.path
if not keyobj.permissions.filter(key=resolve(request.path).url_name).count():
return False
AuthAPILog.objects.create(key=keyobj, access_datetime=now(), url=url)
request.user = AnonymousUser()
request.api_key = keyobj
@@ -31,4 +34,4 @@ class APIKeyAuthentication(object):
return False
def challenge(self):
return HttpResponseForbidden('Access Denied, use a API Key')
return HttpResponseForbidden('Access Denied, use a valid API Key for this request.')

View File

@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'AuthAPIKeyPermission'
db.create_table('api_authapikeypermission', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('key', self.gf('django.db.models.fields.CharField')(max_length=32)),
('name', self.gf('django.db.models.fields.CharField')(max_length=200)),
))
db.send_create_signal('api', ['AuthAPIKeyPermission'])
# Adding M2M table for field permissions on 'AuthAPIKey'
db.create_table('api_authapikey_permissions', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('authapikey', models.ForeignKey(orm['api.authapikey'], null=False)),
('authapikeypermission', models.ForeignKey(orm['api.authapikeypermission'], null=False))
))
db.create_unique('api_authapikey_permissions', ['authapikey_id', 'authapikeypermission_id'])
def backwards(self, orm):
# Deleting model 'AuthAPIKeyPermission'
db.delete_table('api_authapikeypermission')
# Removing M2M table for field permissions on 'AuthAPIKey'
db.delete_table('api_authapikey_permissions')
models = {
'api.authapikey': {
'Meta': {'object_name': 'AuthAPIKey'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'callback': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'keys'", 'symmetrical': 'False', 'to': "orm['api.AuthAPIKeyPermission']"}),
'url': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'})
},
'api.authapikeypermission': {
'Meta': {'object_name': 'AuthAPIKeyPermission'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'})
},
'api.authapilog': {
'Meta': {'ordering': "['access_datetime']", 'object_name': 'AuthAPILog'},
'access_datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'key': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['api.AuthAPIKey']"}),
'url': ('django.db.models.fields.CharField', [], {'max_length': '200'})
}
}
complete_apps = ['api']

View File

@@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
class Migration(DataMigration):
def forwards(self, orm):
from api.urls import urlpatterns as urls
for u in urls:
if not u.name is None:
orm['api.AuthAPIKeyPermission'].objects.get_or_create(key=u.name, name=u.name)
perms = orm['api.AuthAPIKeyPermission'].objects.all()
for key in orm['api.AuthAPIKey'].objects.all():
key.permissions.add(*perms)
def backwards(self, orm):
for key in orm['api.AuthAPIKey'].objects.all():
key.permissions.clear()
orm['api.AuthAPIKeyPermission'].objects.all().delete()
models = {
'api.authapikey': {
'Meta': {'object_name': 'AuthAPIKey'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'callback': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'key': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'keys'", 'symmetrical': 'False', 'to': "orm['api.AuthAPIKeyPermission']"}),
'url': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'})
},
'api.authapikeypermission': {
'Meta': {'object_name': 'AuthAPIKeyPermission'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'})
},
'api.authapilog': {
'Meta': {'ordering': "['access_datetime']", 'object_name': 'AuthAPILog'},
'access_datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'key': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['api.AuthAPIKey']"}),
'url': ('django.db.models.fields.CharField', [], {'max_length': '200'})
}
}
complete_apps = ['api']
symmetrical = True

View File

@@ -2,14 +2,28 @@ import uuid
from django.db import models
class AuthAPIKeyPermission(models.Model):
""" Auth API Key permissions """
key = models.CharField("Permission Key", max_length=32)
name = models.CharField("Permission Name", max_length=200)
def __unicode__(self):
return self.name
class Meta:
verbose_name = 'API Key Permission'
verbose_name_plural = 'API Key Permissions'
class AuthAPIKey(models.Model):
""" Auth API Key storage model """
name = models.CharField("Service Name", max_length=200)
url = models.CharField("Service URL", max_length=200, blank=True, help_text="URL that the service is available at")
url = models.CharField("Service URL", max_length=200, blank=True, help_text="URL that the service is available at.")
active = models.BooleanField(default=True)
key = models.CharField("API Key", max_length=200, blank=True, help_text="API key for the service to use")
callback = models.CharField("Callback URL", max_length=200, blank=True, help_text="URL for the callback service to connect to")
key = models.CharField("API Key", max_length=200, blank=True, help_text="API key for the service to use.")
callback = models.CharField("Callback URL", max_length=200, blank=True, help_text="URL for the callback service to connect to.")
permissions = models.ManyToManyField(AuthAPIKeyPermission, related_name='keys', help_text="API calls this API key is allowed to access.")
def save(self, *args, **kwargs):
if not self.key or self.key == '':

View File

@@ -21,15 +21,15 @@ announce_resource = Resource(handler=AnnounceHandler, **apikeyauth)
edkapi_resource = Resource(handler=EDKApiHandler, **apikeyauth)
urlpatterns = patterns('',
url(r'^1.0/user/$', user_resource),
url(r'^1.0/login/$', login_resource),
url(r'^1.0/eveapi/$', eveapi_resource),
url(r'^1.0/eveapi/', eveapiproxy_resource, name='api-eveapiproxy'),
url(r'^1.0/character/$', characters_resource),
url(r'^1.0/optimer/$', optimer_resource),
url(r'^1.0/blacklist/$', blacklist_resource),
url(r'^1.0/announce/$', announce_resource),
url(r'^1.0/edkapi/$', edkapi_resource),
url(r'^1.0/user/$', user_resource, name='v1-api-user'),
url(r'^1.0/login/$', login_resource, name='v1-api-login'),
url(r'^1.0/eveapi/$', eveapi_resource, name='v1-api-eveapi'),
url(r'^1.0/eveapi/', eveapiproxy_resource, name='v1-api-eveapiproxy'),
url(r'^1.0/character/$', characters_resource, name='v1-api-character'),
url(r'^1.0/optimer/$', optimer_resource, name='v1-api-optimer'),
url(r'^1.0/blacklist/$', blacklist_resource, name='v1-api-blacklist'),
url(r'^1.0/announce/$', announce_resource, name='v1-api-announce'),
url(r'^1.0/edkapi/$', edkapi_resource, name='v1-api-edkapi'),
)
# v2 APIs