This repository has been archived by the owner on Jan 19, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 329
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement API methods, add admin panel controls and more data.
[fix bug 795385] Add API controls to Admin panel. [fix bug 769070] Include more data in API. [bug 769069] Implement API methods. [fix bug 763717] Add search functionality to API. Search for groups, skills, languages, username, ircname, country, region, city, last_name, first_name, is_vouched. [fix bug 795380] Add API privacy controls.
- Loading branch information
1 parent
57c907e
commit d690ebd
Showing
28 changed files
with
1,097 additions
and
211 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,11 @@ | |||
from django.contrib import admin | |||
|
|||
from models import APIApp | |||
|
|||
|
|||
class APIAppAdmin(admin.ModelAdmin): | |||
"""APIApp Admin.""" | |||
list_display = ['name', 'key', 'owner', 'is_mozilla_app', 'is_active'] | |||
list_filter = ['is_mozilla_app', 'is_active'] | |||
|
|||
admin.site.register(APIApp, APIAppAdmin) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,16 @@ | |||
from tastypie.authentication import Authentication | |||
|
|||
from models import APIApp | |||
|
|||
|
|||
class AppAuthentication(Authentication): | |||
"""App Authentication.""" | |||
|
|||
def is_authenticated(self, request, **kwargs): | |||
"""Authenticate App.""" | |||
app_key = request.GET.get('app_key', None) | |||
app_name = request.GET.get('app_name', None) | |||
|
|||
return (APIApp.objects.filter(name__iexact=app_name, key=app_key, | |||
is_active=True).exists()) | |||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,24 @@ | |||
from tastypie.authorization import ReadOnlyAuthorization | |||
|
|||
from models import APIApp | |||
|
|||
|
|||
class MozillaOfficialAuthorization(ReadOnlyAuthorization): | |||
"""Authorize an App as official Mozilla or Community.""" | |||
|
|||
def is_authorized(self, request, object=None): | |||
"""Authorize App. | |||
Always authorize Apps. Community Apps get a 'restricted' URL | |||
parameter. | |||
""" | |||
app_name = request.GET.get('app_name', None) | |||
app_key = request.GET.get('app_key', None) | |||
app = APIApp.objects.get(name=app_name, key=app_key) | |||
|
|||
if not app.is_mozilla_app: | |||
data = request.GET.copy() | |||
data['restricted'] = True | |||
request.GET = data | |||
return True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,81 @@ | |||
# encoding: 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 'APIApp' | |||
db.create_table('api_apiapp', ( | |||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | |||
('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=100)), | |||
('description', self.gf('django.db.models.fields.TextField')()), | |||
('url', self.gf('django.db.models.fields.URLField')(default='', max_length=300, blank=True)), | |||
('owner', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), | |||
('key', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), | |||
('is_superapp', self.gf('django.db.models.fields.BooleanField')(default=False)), | |||
('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), | |||
)) | |||
db.send_create_signal('api', ['APIApp']) | |||
|
|||
|
|||
def backwards(self, orm): | |||
|
|||
# Deleting model 'APIApp' | |||
db.delete_table('api_apiapp') | |||
|
|||
|
|||
models = { | |||
'api.apiapp': { | |||
'Meta': {'object_name': 'APIApp'}, | |||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | |||
'description': ('django.db.models.fields.TextField', [], {}), | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'is_superapp': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | |||
'key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}), | |||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}), | |||
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), | |||
'url': ('django.db.models.fields.URLField', [], {'default': "''", 'max_length': '300', 'blank': 'True'}) | |||
}, | |||
'auth.group': { | |||
'Meta': {'object_name': 'Group'}, | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | |||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | |||
}, | |||
'auth.permission': { | |||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | |||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | |||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | |||
}, | |||
'auth.user': { | |||
'Meta': {'object_name': 'User'}, | |||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | |||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | |||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | |||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | |||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | |||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | |||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | |||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | |||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | |||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | |||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | |||
}, | |||
'contenttypes.contenttype': { | |||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | |||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | |||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | |||
} | |||
} | |||
|
|||
complete_apps = ['api'] |
77 changes: 77 additions & 0 deletions
77
...pi/migrations/0002_auto__del_field_apiapp_is_superapp__add_field_apiapp_is_mozilla_app.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,77 @@ | |||
# encoding: 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): | |||
|
|||
# Deleting field 'APIApp.is_superapp' | |||
db.delete_column('api_apiapp', 'is_superapp') | |||
|
|||
# Adding field 'APIApp.is_mozilla_app' | |||
db.add_column('api_apiapp', 'is_mozilla_app', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) | |||
|
|||
|
|||
def backwards(self, orm): | |||
|
|||
# Adding field 'APIApp.is_superapp' | |||
db.add_column('api_apiapp', 'is_superapp', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) | |||
|
|||
# Deleting field 'APIApp.is_mozilla_app' | |||
db.delete_column('api_apiapp', 'is_mozilla_app') | |||
|
|||
|
|||
models = { | |||
'api.apiapp': { | |||
'Meta': {'object_name': 'APIApp'}, | |||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | |||
'description': ('django.db.models.fields.TextField', [], {}), | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'is_mozilla_app': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | |||
'key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}), | |||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}), | |||
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), | |||
'url': ('django.db.models.fields.URLField', [], {'default': "''", 'max_length': '300', 'blank': 'True'}) | |||
}, | |||
'auth.group': { | |||
'Meta': {'object_name': 'Group'}, | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | |||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | |||
}, | |||
'auth.permission': { | |||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | |||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | |||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | |||
}, | |||
'auth.user': { | |||
'Meta': {'object_name': 'User'}, | |||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | |||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | |||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | |||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | |||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | |||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | |||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | |||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | |||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | |||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | |||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | |||
}, | |||
'contenttypes.contenttype': { | |||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | |||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | |||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | |||
} | |||
} | |||
|
|||
complete_apps = ['api'] |
72 changes: 72 additions & 0 deletions
72
apps/api/migrations/0003_auto__add_field_apiapp_is_active.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,72 @@ | |||
# encoding: 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 field 'APIApp.is_active' | |||
db.add_column('api_apiapp', 'is_active', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) | |||
|
|||
|
|||
def backwards(self, orm): | |||
|
|||
# Deleting field 'APIApp.is_active' | |||
db.delete_column('api_apiapp', 'is_active') | |||
|
|||
|
|||
models = { | |||
'api.apiapp': { | |||
'Meta': {'object_name': 'APIApp'}, | |||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | |||
'description': ('django.db.models.fields.TextField', [], {}), | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | |||
'is_mozilla_app': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | |||
'key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}), | |||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}), | |||
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), | |||
'url': ('django.db.models.fields.URLField', [], {'default': "''", 'max_length': '300', 'blank': 'True'}) | |||
}, | |||
'auth.group': { | |||
'Meta': {'object_name': 'Group'}, | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | |||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | |||
}, | |||
'auth.permission': { | |||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | |||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | |||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | |||
}, | |||
'auth.user': { | |||
'Meta': {'object_name': 'User'}, | |||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | |||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | |||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | |||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | |||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | |||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | |||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | |||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | |||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | |||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | |||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | |||
}, | |||
'contenttypes.contenttype': { | |||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | |||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | |||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | |||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | |||
} | |||
} | |||
|
|||
complete_apps = ['api'] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,36 @@ | |||
import hmac | |||
import uuid | |||
from hashlib import sha1 | |||
|
|||
from django.contrib.auth.models import User | |||
from django.db import models | |||
|
|||
|
|||
class APIApp(models.Model): | |||
"""APIApp Model.""" | |||
name = models.CharField(max_length=100, unique=True) | |||
description = models.TextField() | |||
url = models.URLField(max_length=300, blank=True, default='') | |||
owner = models.ForeignKey(User) | |||
key = models.CharField( | |||
help_text='Leave this field empty to generate a new API key.', | |||
max_length=256, blank=True, default='') | |||
is_mozilla_app = models.BooleanField(blank=True, default=False) | |||
is_active = models.BooleanField(blank=True, default=False) | |||
created = models.DateTimeField(auto_now_add=True) | |||
|
|||
def __unicode__(self): | |||
"""Return unicode representation of object.""" | |||
return "%s for %s" % (self.name, self.owner) | |||
|
|||
def save(self, *args, **kwargs): | |||
"""Generates a key if none and saves object.""" | |||
if not self.key: | |||
self.key = self.generate_key() | |||
|
|||
return super(APIApp, self).save(*args, **kwargs) | |||
|
|||
def generate_key(self): | |||
"""Return a key.""" | |||
new_uuid = uuid.uuid4() | |||
return hmac.new(str(new_uuid), digestmod=sha1).hexdigest() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,12 @@ | |||
from django.conf.urls.defaults import include, patterns, url | |||
|
|||
from tastypie.api import Api | |||
|
|||
import apps.users.api | |||
|
|||
v1_api = Api(api_name='v1') | |||
v1_api.register(apps.users.api.UserResource()) | |||
|
|||
urlpatterns = patterns('', | |||
url(r'', include(v1_api.urls)), | |||
) |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.