Skip to content
This repository has been archived by the owner on Jan 19, 2021. It is now read-only.

Commit

Permalink
Implement API methods, add admin panel controls and more data.
Browse files Browse the repository at this point in the history
[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
glogiotatidis committed Oct 30, 2012
1 parent 57c907e commit d690ebd
Show file tree
Hide file tree
Showing 28 changed files with 1,097 additions and 211 deletions.
Empty file added apps/api/__init__.py
Empty file.
11 changes: 11 additions & 0 deletions apps/api/admin.py
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)
16 changes: 16 additions & 0 deletions apps/api/authenticators.py
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())

24 changes: 24 additions & 0 deletions apps/api/authorisers.py
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
81 changes: 81 additions & 0 deletions apps/api/migrations/0001_initial.py
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']
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 apps/api/migrations/0003_auto__add_field_apiapp_is_active.py
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 added apps/api/migrations/__init__.py
Empty file.
36 changes: 36 additions & 0 deletions apps/api/models.py
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()
2 changes: 1 addition & 1 deletion templates/api.html → apps/api/templates/api.html
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</head> </head>
<body> <body>
{% block content %} {% block content %}
<a id="json_url" href=""></a> <a id="json_url" href=""></a>
<pre id="json" class="prettyprint"> <pre id="json" class="prettyprint">
</pre> </pre>
{% endblock %} {% endblock %}
Expand Down
12 changes: 12 additions & 0 deletions apps/api/urls.py
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)),
)
18 changes: 0 additions & 18 deletions apps/common/api.py

This file was deleted.

4 changes: 1 addition & 3 deletions apps/common/tests.py
Original file line number Original file line Diff line number Diff line change
@@ -1,8 +1,6 @@
import random import random
from string import letters from string import letters


import pyes.exceptions

from django import test from django import test
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
Expand All @@ -13,7 +11,7 @@
from elasticutils.contrib.django import get_es from elasticutils.contrib.django import get_es


from apps.users.cron import index_all_profiles from apps.users.cron import index_all_profiles
from apps.users.models import UserProfile


class TestCase(test_utils.TestCase): class TestCase(test_utils.TestCase):
"""Tests for common package.""" """Tests for common package."""
Expand Down
2 changes: 1 addition & 1 deletion apps/phonebook/forms.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class Meta:
# Model form stuff # Model form stuff
model = UserProfile model = UserProfile
fields = ('ircname', 'website', 'bio', 'photo', 'country', 'region', fields = ('ircname', 'website', 'bio', 'photo', 'country', 'region',
'city') 'city', 'allows_community_sites', 'allows_mozilla_sites')
widgets = {'bio': forms.Textarea()} widgets = {'bio': forms.Textarea()}


def clean_groups(self): def clean_groups(self):
Expand Down
Loading

0 comments on commit d690ebd

Please sign in to comment.